@pensar/apex 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/assets/wordlists/LICENSE +21 -0
  2. package/assets/wordlists/README.md +36 -0
  3. package/assets/wordlists/common.txt +4751 -0
  4. package/assets/wordlists/large.txt +29999 -0
  5. package/assets/wordlists/tiny.txt +227 -0
  6. package/build/agent-0jmzw6zx.js +18 -0
  7. package/build/{agent-95ysppvr.js → agent-wmynfx37.js} +10 -9
  8. package/build/{auth-h84w23gx.js → auth-p2n15nfp.js} +4 -4
  9. package/build/{authentication-3m2qm7ym.js → authentication-ngxxzcvc.js} +11 -11
  10. package/build/blackboxAgent-v698p7e4.js +18 -0
  11. package/build/{blackboxPentest-kn3y84jf.js → blackboxPentest-7jvcbz3f.js} +15 -15
  12. package/build/{cli-r8cerdwk.js → cli-03z6pswp.js} +1 -1
  13. package/build/{cli-abkgxjcc.js → cli-06q6sz4x.js} +2 -2
  14. package/build/{cli-dfth2beg.js → cli-1tv4x6xh.js} +8 -8
  15. package/build/{cli-ey40xb9a.js → cli-1xdc0keq.js} +1 -1
  16. package/build/{cli-qcsv2e9h.js → cli-5xfjvm8j.js} +1 -1
  17. package/build/{cli-wqeja2k6.js → cli-6negm843.js} +1 -1
  18. package/build/{cli-x5t1x7ts.js → cli-ahmpjgg6.js} +1 -1
  19. package/build/{cli-j4qm285k.js → cli-ch1yfrj1.js} +2 -2
  20. package/build/{cli-dsybj1jp.js → cli-d5mcmzp1.js} +1 -1
  21. package/build/{cli-etrmgpa5.js → cli-gs7zy230.js} +5 -5
  22. package/build/{cli-awjwsbrz.js → cli-mazg4ajq.js} +2 -2
  23. package/build/{cli-mxj8tz9b.js → cli-nwcvgx5m.js} +51 -14
  24. package/build/{cli-r4jzb7aj.js → cli-st6vsbzv.js} +2 -1
  25. package/build/{cli-qvq41y3z.js → cli-t1nkahx2.js} +1 -1
  26. package/build/cli-tp1tqn3k.js +184 -0
  27. package/build/{cli-yz3dzpxd.js → cli-tyrzasca.js} +351 -104
  28. package/build/{cli-sgzbqavm.js → cli-yvnb3k0x.js} +1 -1
  29. package/build/cli.js +28 -27
  30. package/build/{doctor-b7612pzw.js → doctor-8tva8j99.js} +1 -1
  31. package/build/{fixes-5f9xv4yx.js → fixes-p4e3bjcg.js} +4 -4
  32. package/build/{index-b7e18f8m.js → index-esgrht7q.js} +7 -7
  33. package/build/{index-d86fgcjm.js → index-gpvx8y17.js} +4 -4
  34. package/build/{index-h5r11f3q.js → index-m6gw4113.js} +2 -2
  35. package/build/{index-0qfckx3a.js → index-ywrq8mhc.js} +1555 -1449
  36. package/build/{issues-dy4rrtr2.js → issues-8had86x1.js} +4 -4
  37. package/build/{logs-d3sjx7vk.js → logs-3fpd8xq8.js} +4 -4
  38. package/build/pentest-4ty38pt8.js +28 -0
  39. package/build/{pentests-vwekf0zm.js → pentests-tqv6zrqy.js} +4 -4
  40. package/build/{projects-se9jgfb0.js → projects-eh2g7061.js} +4 -4
  41. package/build/{targetedPentest-mhkts702.js → targetedPentest-60td56me.js} +10 -9
  42. package/build/{threatModel-gdvgv7pc.js → threatModel-v46xygtn.js} +10 -9
  43. package/build/{uninstall-11a98j87.js → uninstall-vz6jzt86.js} +1 -1
  44. package/build/{utils-zvr7bcyw.js → utils-8yqe12jr.js} +1 -1
  45. package/package.json +2 -1
  46. package/build/agent-e3r90w2x.js +0 -17
  47. package/build/blackboxAgent-4t68wah3.js +0 -18
  48. package/build/cli-6gtnyaqf.js +0 -109
  49. package/build/pentest-6ctf263k.js +0 -28
@@ -1,3 +1,6 @@
1
+ import {
2
+ detectOSAndEnhancePrompt
3
+ } from "./cli-tp1tqn3k.js";
1
4
  import {
2
5
  CredentialManager,
3
6
  NotFoundError,
@@ -13,7 +16,7 @@ import {
13
16
  update,
14
17
  write,
15
18
  writeRaw
16
- } from "./cli-wqeja2k6.js";
19
+ } from "./cli-6negm843.js";
17
20
  import {
18
21
  parseTargetUrl
19
22
  } from "./cli-3y0dgy56.js";
@@ -49,18 +52,18 @@ import {
49
52
  union,
50
53
  unknown,
51
54
  zod_default
52
- } from "./cli-dfth2beg.js";
55
+ } from "./cli-1tv4x6xh.js";
53
56
  import {
54
57
  signGatewayRequest
55
- } from "./cli-qvq41y3z.js";
58
+ } from "./cli-t1nkahx2.js";
56
59
  import {
57
60
  config,
58
61
  ensureValidToken,
59
62
  getPensarApiUrl
60
- } from "./cli-qcsv2e9h.js";
63
+ } from "./cli-5xfjvm8j.js";
61
64
  import {
62
65
  getCurrentVersion
63
- } from "./cli-r4jzb7aj.js";
66
+ } from "./cli-st6vsbzv.js";
64
67
  import {
65
68
  __commonJS,
66
69
  __require,
@@ -47190,15 +47193,15 @@ var require_node = __commonJS((exports) => {
47190
47193
  Object.defineProperty(exports, "__esModule", { value: true });
47191
47194
  exports.cloneNode = exports.hasChildren = exports.isDocument = exports.isDirective = exports.isComment = exports.isText = exports.isCDATA = exports.isTag = exports.Element = exports.Document = exports.CDATA = exports.NodeWithChildren = exports.ProcessingInstruction = exports.Comment = exports.Text = exports.DataNode = exports.Node = undefined;
47192
47195
  var domelementtype_1 = require_lib4();
47193
- var Node = function() {
47194
- function Node2() {
47196
+ var Node2 = function() {
47197
+ function Node3() {
47195
47198
  this.parent = null;
47196
47199
  this.prev = null;
47197
47200
  this.next = null;
47198
47201
  this.startIndex = null;
47199
47202
  this.endIndex = null;
47200
47203
  }
47201
- Object.defineProperty(Node2.prototype, "parentNode", {
47204
+ Object.defineProperty(Node3.prototype, "parentNode", {
47202
47205
  get: function() {
47203
47206
  return this.parent;
47204
47207
  },
@@ -47208,7 +47211,7 @@ var require_node = __commonJS((exports) => {
47208
47211
  enumerable: false,
47209
47212
  configurable: true
47210
47213
  });
47211
- Object.defineProperty(Node2.prototype, "previousSibling", {
47214
+ Object.defineProperty(Node3.prototype, "previousSibling", {
47212
47215
  get: function() {
47213
47216
  return this.prev;
47214
47217
  },
@@ -47218,7 +47221,7 @@ var require_node = __commonJS((exports) => {
47218
47221
  enumerable: false,
47219
47222
  configurable: true
47220
47223
  });
47221
- Object.defineProperty(Node2.prototype, "nextSibling", {
47224
+ Object.defineProperty(Node3.prototype, "nextSibling", {
47222
47225
  get: function() {
47223
47226
  return this.next;
47224
47227
  },
@@ -47228,15 +47231,15 @@ var require_node = __commonJS((exports) => {
47228
47231
  enumerable: false,
47229
47232
  configurable: true
47230
47233
  });
47231
- Node2.prototype.cloneNode = function(recursive) {
47234
+ Node3.prototype.cloneNode = function(recursive) {
47232
47235
  if (recursive === undefined) {
47233
47236
  recursive = false;
47234
47237
  }
47235
47238
  return cloneNode(this, recursive);
47236
47239
  };
47237
- return Node2;
47240
+ return Node3;
47238
47241
  }();
47239
- exports.Node = Node;
47242
+ exports.Node = Node2;
47240
47243
  var DataNode = function(_super) {
47241
47244
  __extends(DataNode2, _super);
47242
47245
  function DataNode2(data) {
@@ -47255,7 +47258,7 @@ var require_node = __commonJS((exports) => {
47255
47258
  configurable: true
47256
47259
  });
47257
47260
  return DataNode2;
47258
- }(Node);
47261
+ }(Node2);
47259
47262
  exports.DataNode = DataNode;
47260
47263
  var Text = function(_super) {
47261
47264
  __extends(Text2, _super);
@@ -47342,7 +47345,7 @@ var require_node = __commonJS((exports) => {
47342
47345
  configurable: true
47343
47346
  });
47344
47347
  return NodeWithChildren2;
47345
- }(Node);
47348
+ }(Node2);
47346
47349
  exports.NodeWithChildren = NodeWithChildren;
47347
47350
  var CDATA = function(_super) {
47348
47351
  __extends(CDATA2, _super);
@@ -99637,6 +99640,162 @@ function buildExplanation(riskLevel, assetType, _baseScore, totalScore, breakdow
99637
99640
  return parts.join(" ");
99638
99641
  }
99639
99642
 
99643
+ // node_modules/yocto-queue/index.js
99644
+ class Node {
99645
+ value;
99646
+ next;
99647
+ constructor(value) {
99648
+ this.value = value;
99649
+ }
99650
+ }
99651
+
99652
+ class Queue {
99653
+ #head;
99654
+ #tail;
99655
+ #size;
99656
+ constructor() {
99657
+ this.clear();
99658
+ }
99659
+ enqueue(value) {
99660
+ const node = new Node(value);
99661
+ if (this.#head) {
99662
+ this.#tail.next = node;
99663
+ this.#tail = node;
99664
+ } else {
99665
+ this.#head = node;
99666
+ this.#tail = node;
99667
+ }
99668
+ this.#size++;
99669
+ }
99670
+ dequeue() {
99671
+ const current = this.#head;
99672
+ if (!current) {
99673
+ return;
99674
+ }
99675
+ this.#head = this.#head.next;
99676
+ this.#size--;
99677
+ if (!this.#head) {
99678
+ this.#tail = undefined;
99679
+ }
99680
+ return current.value;
99681
+ }
99682
+ peek() {
99683
+ if (!this.#head) {
99684
+ return;
99685
+ }
99686
+ return this.#head.value;
99687
+ }
99688
+ clear() {
99689
+ this.#head = undefined;
99690
+ this.#tail = undefined;
99691
+ this.#size = 0;
99692
+ }
99693
+ get size() {
99694
+ return this.#size;
99695
+ }
99696
+ *[Symbol.iterator]() {
99697
+ let current = this.#head;
99698
+ while (current) {
99699
+ yield current.value;
99700
+ current = current.next;
99701
+ }
99702
+ }
99703
+ *drain() {
99704
+ while (this.#head) {
99705
+ yield this.dequeue();
99706
+ }
99707
+ }
99708
+ }
99709
+
99710
+ // node_modules/p-limit/index.js
99711
+ function pLimit(concurrency) {
99712
+ let rejectOnClear = false;
99713
+ if (typeof concurrency === "object") {
99714
+ ({ concurrency, rejectOnClear = false } = concurrency);
99715
+ }
99716
+ validateConcurrency(concurrency);
99717
+ if (typeof rejectOnClear !== "boolean") {
99718
+ throw new TypeError("Expected `rejectOnClear` to be a boolean");
99719
+ }
99720
+ const queue = new Queue;
99721
+ let activeCount = 0;
99722
+ const resumeNext = () => {
99723
+ if (activeCount < concurrency && queue.size > 0) {
99724
+ activeCount++;
99725
+ queue.dequeue().run();
99726
+ }
99727
+ };
99728
+ const next = () => {
99729
+ activeCount--;
99730
+ resumeNext();
99731
+ };
99732
+ const run = async (function_, resolve5, arguments_) => {
99733
+ const result = (async () => function_(...arguments_))();
99734
+ resolve5(result);
99735
+ try {
99736
+ await result;
99737
+ } catch {}
99738
+ next();
99739
+ };
99740
+ const enqueue = (function_, resolve5, reject, arguments_) => {
99741
+ const queueItem = { reject };
99742
+ new Promise((internalResolve) => {
99743
+ queueItem.run = internalResolve;
99744
+ queue.enqueue(queueItem);
99745
+ }).then(run.bind(undefined, function_, resolve5, arguments_));
99746
+ if (activeCount < concurrency) {
99747
+ resumeNext();
99748
+ }
99749
+ };
99750
+ const generator = (function_, ...arguments_) => new Promise((resolve5, reject) => {
99751
+ enqueue(function_, resolve5, reject, arguments_);
99752
+ });
99753
+ Object.defineProperties(generator, {
99754
+ activeCount: {
99755
+ get: () => activeCount
99756
+ },
99757
+ pendingCount: {
99758
+ get: () => queue.size
99759
+ },
99760
+ clearQueue: {
99761
+ value() {
99762
+ if (!rejectOnClear) {
99763
+ queue.clear();
99764
+ return;
99765
+ }
99766
+ const abortError = AbortSignal.abort().reason;
99767
+ while (queue.size > 0) {
99768
+ queue.dequeue().reject(abortError);
99769
+ }
99770
+ }
99771
+ },
99772
+ concurrency: {
99773
+ get: () => concurrency,
99774
+ set(newConcurrency) {
99775
+ validateConcurrency(newConcurrency);
99776
+ concurrency = newConcurrency;
99777
+ queueMicrotask(() => {
99778
+ while (activeCount < concurrency && queue.size > 0) {
99779
+ resumeNext();
99780
+ }
99781
+ });
99782
+ }
99783
+ },
99784
+ map: {
99785
+ async value(iterable, function_) {
99786
+ const promises = Array.from(iterable, (value, index) => this(function_, value, index));
99787
+ return Promise.all(promises);
99788
+ }
99789
+ }
99790
+ });
99791
+ return generator;
99792
+ }
99793
+ function validateConcurrency(concurrency) {
99794
+ if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
99795
+ throw new TypeError("Expected `concurrency` to be a number from 1 and up");
99796
+ }
99797
+ }
99798
+
99640
99799
  // src/core/agents/offSecAgent/tools/threatModelGenerator.ts
99641
99800
  init_zod();
99642
99801
 
@@ -99747,6 +99906,8 @@ class AgentEventBus {
99747
99906
  }
99748
99907
 
99749
99908
  // src/core/agents/offSecAgent/tools/threatModelGenerator.ts
99909
+ var THREAT_MODEL_CONCURRENCY = 10;
99910
+ var threatModelLimiter = pLimit(THREAT_MODEL_CONCURRENCY);
99750
99911
  var PentestObjectiveSchema = exports_external.object({
99751
99912
  title: exports_external.string().describe("Short human-readable name. E.g. 'IDOR via orderId path param'."),
99752
99913
  hypothesis: exports_external.string().describe("Falsifiable negative statement the test aims to prove true. " + "E.g. 'The endpoint fails to validate that the authenticated user owns the order " + "referenced by :orderId, permitting cross-tenant reads.'"),
@@ -99788,61 +99949,66 @@ Your output is consumed by an automated pentest agent. The clarity and specifici
99788
99949
  async function generateThreatModelForEndpoint(ctx, input) {
99789
99950
  if (!ctx.model)
99790
99951
  return null;
99791
- const { CodeAgent } = await import("./agent-e3r90w2x.js");
99792
- const subagentId = `threat-model-${sanitize(input.appName)}-${sanitize(input.routePath)}`;
99793
- ctx.eventBus?.emit("subagent-spawn", {
99794
- subagentId,
99795
- name: `Threat Model: ${input.routePath}`,
99796
- input: { app: input.appName, endpoint: input.routePath }
99797
- });
99798
- const localBus = new AgentEventBus;
99799
- AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
99800
- const prompt = buildThreatModelPrompt(input, ctx.projectThreatModel);
99801
- const agent = new CodeAgent({
99802
- codebasePath: ctx.agentCwd,
99803
- objective: prompt,
99804
- system: THREAT_MODEL_SYSTEM_PROMPT,
99805
- model: ctx.model,
99806
- session: ctx.session,
99807
- authConfig: ctx.authConfig,
99808
- abortSignal: ctx.abortSignal,
99809
- eventBus: localBus,
99810
- subagentId,
99811
- responseSchema: ThreatModelResultSchema,
99812
- excludeTools: ["document_endpoint", "document_app"]
99813
- });
99814
- try {
99815
- const result = await agent.consume();
99816
- ctx.eventBus?.emit("subagent-complete", {
99952
+ const model = ctx.model;
99953
+ return threatModelLimiter(async () => {
99954
+ if (ctx.abortSignal?.aborted)
99955
+ return null;
99956
+ const { CodeAgent } = await import("./agent-0jmzw6zx.js");
99957
+ const subagentId = `threat-model-${sanitize(input.appName)}-${sanitize(input.routePath)}`;
99958
+ ctx.eventBus?.emit("subagent-spawn", {
99817
99959
  subagentId,
99818
- status: "completed"
99960
+ name: `Threat Model: ${input.routePath}`,
99961
+ input: { app: input.appName, endpoint: input.routePath }
99819
99962
  });
99820
- if (!result)
99821
- return null;
99822
- const totalScore = result.exposure + result.dataSensitivity + result.functionCriticality + result.securityIndicators;
99823
- return {
99824
- businessLogic: result.businessLogic,
99825
- threatModel: result.threatModel,
99826
- riskScore: {
99827
- score: totalScore,
99828
- explanation: result.riskScoreJustification,
99829
- breakdown: {
99830
- exposure: result.exposure,
99831
- dataSensitivity: result.dataSensitivity,
99832
- functionCriticality: result.functionCriticality,
99833
- securityIndicators: result.securityIndicators
99834
- }
99835
- },
99836
- pentestObjectives: (result.pentestObjectives ?? []).map(flattenPentestObjective)
99837
- };
99838
- } catch (error) {
99839
- ctx.eventBus?.emit("subagent-complete", {
99963
+ const localBus = new AgentEventBus;
99964
+ AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
99965
+ const prompt = buildThreatModelPrompt(input, ctx.projectThreatModel);
99966
+ const agent = new CodeAgent({
99967
+ codebasePath: ctx.agentCwd,
99968
+ objective: prompt,
99969
+ system: THREAT_MODEL_SYSTEM_PROMPT,
99970
+ model,
99971
+ session: ctx.session,
99972
+ authConfig: ctx.authConfig,
99973
+ abortSignal: ctx.abortSignal,
99974
+ eventBus: localBus,
99840
99975
  subagentId,
99841
- status: "failed"
99976
+ responseSchema: ThreatModelResultSchema,
99977
+ excludeTools: ["document_endpoint", "document_app"]
99842
99978
  });
99843
- console.error(`Threat model generation failed for ${input.routePath}: ${error instanceof Error ? error.message : String(error)}`);
99844
- return null;
99845
- }
99979
+ try {
99980
+ const result = await agent.consume();
99981
+ ctx.eventBus?.emit("subagent-complete", {
99982
+ subagentId,
99983
+ status: "completed"
99984
+ });
99985
+ if (!result)
99986
+ return null;
99987
+ const totalScore = result.exposure + result.dataSensitivity + result.functionCriticality + result.securityIndicators;
99988
+ return {
99989
+ businessLogic: result.businessLogic,
99990
+ threatModel: result.threatModel,
99991
+ riskScore: {
99992
+ score: totalScore,
99993
+ explanation: result.riskScoreJustification,
99994
+ breakdown: {
99995
+ exposure: result.exposure,
99996
+ dataSensitivity: result.dataSensitivity,
99997
+ functionCriticality: result.functionCriticality,
99998
+ securityIndicators: result.securityIndicators
99999
+ }
100000
+ },
100001
+ pentestObjectives: (result.pentestObjectives ?? []).map(flattenPentestObjective)
100002
+ };
100003
+ } catch (error) {
100004
+ ctx.eventBus?.emit("subagent-complete", {
100005
+ subagentId,
100006
+ status: "failed"
100007
+ });
100008
+ console.error(`Threat model generation failed for ${input.routePath}: ${error instanceof Error ? error.message : String(error)}`);
100009
+ return null;
100010
+ }
100011
+ });
99846
100012
  }
99847
100013
  function buildThreatModelPrompt(input, projectThreatModel) {
99848
100014
  const lineRange = input.line ? `around line ${input.line}` : "";
@@ -100476,7 +100642,7 @@ When to use delegate_to_auth_subagent vs authenticate_session:
100476
100642
  if (credentials) {
100477
100643
  ctx.session.credentialManager.addFromAuthCredentials(credentials);
100478
100644
  }
100479
- const { runAuthenticationAgent } = await import("./authentication-3m2qm7ym.js");
100645
+ const { runAuthenticationAgent } = await import("./authentication-ngxxzcvc.js");
100480
100646
  const localBus = new AgentEventBus;
100481
100647
  AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
100482
100648
  const result = await runAuthenticationAgent({
@@ -101389,7 +101555,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
101389
101555
  });
101390
101556
  if (cwd) {
101391
101557
  try {
101392
- const { WhiteboxAttackSurfaceAgent } = await import("./agent-95ysppvr.js");
101558
+ const { WhiteboxAttackSurfaceAgent } = await import("./agent-wmynfx37.js");
101393
101559
  const localBus = new AgentEventBus;
101394
101560
  AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
101395
101561
  const agent = new WhiteboxAttackSurfaceAgent({
@@ -101438,7 +101604,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
101438
101604
  }
101439
101605
  }
101440
101606
  try {
101441
- const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-4t68wah3.js");
101607
+ const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-v698p7e4.js");
101442
101608
  const localBus = new AgentEventBus;
101443
101609
  AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
101444
101610
  const agent = new BlackboxAttackSurfaceAgent({
@@ -101514,7 +101680,7 @@ Pass every target you want tested — the swarm handles concurrency automaticall
101514
101680
  toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
101515
101681
  }),
101516
101682
  execute: async ({ targets }) => {
101517
- const { runPentestSwarm, DEFAULT_CONCURRENCY } = await import("./pentest-6ctf263k.js");
101683
+ const { runPentestSwarm, DEFAULT_CONCURRENCY } = await import("./pentest-4ty38pt8.js");
101518
101684
  if (!ctx.model) {
101519
101685
  return {
101520
101686
  success: false,
@@ -101642,7 +101808,7 @@ Returns an array of results with the text output from each agent.`,
101642
101808
  });
101643
101809
  }
101644
101810
  async function runSingleCodingAgent(ctx, codebasePath, objective, agentIndex, name) {
101645
- const { CodeAgent } = await import("./agent-e3r90w2x.js");
101811
+ const { CodeAgent } = await import("./agent-0jmzw6zx.js");
101646
101812
  const subagentId = `coding-agent-${agentIndex}`;
101647
101813
  ctx.eventBus?.emit("subagent-spawn", {
101648
101814
  subagentId,
@@ -101703,7 +101869,7 @@ Omit \`cwd\` for blackbox mode (live target probing only).`,
101703
101869
  toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
101704
101870
  }),
101705
101871
  execute: async ({ target, cwd }) => {
101706
- const { runPentestWorkflow: workflow } = await import("./pentest-6ctf263k.js");
101872
+ const { runPentestWorkflow: workflow } = await import("./pentest-4ty38pt8.js");
101707
101873
  if (!ctx.model) {
101708
101874
  return {
101709
101875
  success: false,
@@ -105935,6 +106101,29 @@ function hasStdbuf() {
105935
106101
  stdbufAvailable = res.status === 0;
105936
106102
  return stdbufAvailable;
105937
106103
  }
106104
+ function extractFallbackStdout(cmd) {
106105
+ if (cmd.authoritativeStdout) {
106106
+ let s2 = cmd.authoritativeStdout;
106107
+ const exitIdx2 = s2.indexOf(cmd.exitMarkerPrefix);
106108
+ if (exitIdx2 !== -1) {
106109
+ s2 = s2.substring(0, exitIdx2);
106110
+ }
106111
+ return s2 || "(no output)";
106112
+ }
106113
+ let s = cmd.streamedStdout;
106114
+ const cutIdx = s.indexOf(cmd.cutoverMarker);
106115
+ if (cutIdx !== -1) {
106116
+ s = s.substring(cutIdx + cmd.cutoverMarker.length);
106117
+ if (s.startsWith(`
106118
+ `))
106119
+ s = s.substring(1);
106120
+ }
106121
+ const exitIdx = s.indexOf(cmd.exitMarkerPrefix);
106122
+ if (exitIdx !== -1) {
106123
+ s = s.substring(0, exitIdx);
106124
+ }
106125
+ return s || "(no output)";
106126
+ }
105938
106127
 
105939
106128
  class PersistentShell {
105940
106129
  proc = null;
@@ -105981,7 +106170,7 @@ class PersistentShell {
105981
106170
  this.current = null;
105982
106171
  this.pendingCancel = null;
105983
106172
  cmd.resolve({
105984
- stdout: cmd.stdout || "(no output)",
106173
+ stdout: extractFallbackStdout(cmd),
105985
106174
  stderr: cmd.stderr || "",
105986
106175
  exitCode: 1
105987
106176
  });
@@ -106001,22 +106190,40 @@ class PersistentShell {
106001
106190
  const cmd = this.current;
106002
106191
  if (!cmd)
106003
106192
  return;
106004
- const chunk = data.toString();
106005
- if (cmd.onData) {
106006
- const mIdx = chunk.indexOf(cmd.exitMarkerPrefix);
106007
- const visible = mIdx === -1 ? chunk : chunk.substring(0, mIdx);
106008
- if (visible.length > 0)
106009
- cmd.onData(visible);
106010
- }
106011
- cmd.stdout += chunk;
106012
- const markerIdx = cmd.stdout.indexOf(cmd.exitMarkerPrefix);
106193
+ let chunk = data.toString();
106194
+ if (!cmd.cutoverSeen) {
106195
+ const prevLen = cmd.streamedStdout.length;
106196
+ cmd.streamedStdout += chunk;
106197
+ const cutIdx = cmd.streamedStdout.indexOf(cmd.cutoverMarker);
106198
+ if (cutIdx === -1) {
106199
+ if (chunk.length > 0 && cmd.onData)
106200
+ cmd.onData(chunk);
106201
+ if (cmd.streamedStdout.length > MAX_BUFFER) {
106202
+ cmd.streamedStdout = cmd.streamedStdout.substring(cmd.streamedStdout.length - MAX_BUFFER);
106203
+ }
106204
+ return;
106205
+ }
106206
+ const chunkCutOffset = cutIdx - prevLen;
106207
+ if (chunkCutOffset > 0 && cmd.onData) {
106208
+ cmd.onData(chunk.substring(0, chunkCutOffset));
106209
+ }
106210
+ const postMarker = cmd.streamedStdout.substring(cutIdx + cmd.cutoverMarker.length);
106211
+ cmd.cutoverSeen = true;
106212
+ cmd.streamedStdout = "";
106213
+ chunk = postMarker.startsWith(`
106214
+ `) ? postMarker.substring(1) : postMarker;
106215
+ if (chunk.length === 0)
106216
+ return;
106217
+ }
106218
+ cmd.authoritativeStdout += chunk;
106219
+ const markerIdx = cmd.authoritativeStdout.indexOf(cmd.exitMarkerPrefix);
106013
106220
  if (markerIdx !== -1) {
106014
- const afterPrefix = cmd.stdout.substring(markerIdx + cmd.exitMarkerPrefix.length);
106221
+ const afterPrefix = cmd.authoritativeStdout.substring(markerIdx + cmd.exitMarkerPrefix.length);
106015
106222
  const nlIdx = afterPrefix.indexOf(`
106016
106223
  `);
106017
106224
  const exitStr = nlIdx >= 0 ? afterPrefix.substring(0, nlIdx) : afterPrefix;
106018
106225
  const naturalExitCode = parseInt(exitStr, 10);
106019
- let commandOutput = cmd.stdout.substring(0, markerIdx);
106226
+ let commandOutput = cmd.authoritativeStdout.substring(0, markerIdx);
106020
106227
  if (cmd.stdoutTruncated) {
106021
106228
  commandOutput = `(stdout truncated)...
106022
106229
  ` + commandOutput;
@@ -106033,8 +106240,8 @@ class PersistentShell {
106033
106240
  });
106034
106241
  return;
106035
106242
  }
106036
- if (cmd.stdout.length > MAX_BUFFER) {
106037
- cmd.stdout = cmd.stdout.substring(cmd.stdout.length - MAX_BUFFER);
106243
+ if (cmd.authoritativeStdout.length > MAX_BUFFER) {
106244
+ cmd.authoritativeStdout = cmd.authoritativeStdout.substring(cmd.authoritativeStdout.length - MAX_BUFFER);
106038
106245
  cmd.stdoutTruncated = true;
106039
106246
  }
106040
106247
  }
@@ -106066,12 +106273,16 @@ class PersistentShell {
106066
106273
  }
106067
106274
  const marker = `__APEX_${randomBytes(8).toString("hex")}__`;
106068
106275
  const exitMarkerPrefix = `${marker}_EXIT_`;
106276
+ const cutoverMarker = `${marker}_CUTOVER`;
106069
106277
  return new Promise((resolve5) => {
106070
106278
  let resolved = false;
106071
106279
  let timeoutTimer;
106072
106280
  let killEscalationTimer;
106073
106281
  const pending = {
106074
- stdout: "",
106282
+ streamedStdout: "",
106283
+ authoritativeStdout: "",
106284
+ cutoverSeen: false,
106285
+ cutoverMarker,
106075
106286
  stderr: "",
106076
106287
  stdoutTruncated: false,
106077
106288
  exitMarkerPrefix,
@@ -106110,7 +106321,7 @@ class PersistentShell {
106110
106321
  if (resolved)
106111
106322
  return;
106112
106323
  pending.resolve({
106113
- stdout: pending.stdout || "(no output)",
106324
+ stdout: extractFallbackStdout(pending),
106114
106325
  stderr: (pending.stderr || "") + (pending.forcedStderrSuffix ?? ""),
106115
106326
  exitCode: 130
106116
106327
  });
@@ -106134,7 +106345,7 @@ class PersistentShell {
106134
106345
  if (resolved)
106135
106346
  return;
106136
106347
  pending.resolve({
106137
- stdout: pending.stdout || "(no output)",
106348
+ stdout: extractFallbackStdout(pending),
106138
106349
  stderr: pending.stderr || "",
106139
106350
  exitCode: 124
106140
106351
  });
@@ -106142,22 +106353,20 @@ class PersistentShell {
106142
106353
  }, 500);
106143
106354
  }, timeoutSeconds * 1000);
106144
106355
  }
106145
- const streaming = hasStdbuf();
106356
+ const tailCmd = hasStdbuf() ? `stdbuf -oL tail -n +1 -f -s 0.05 "$__APEX_OUT"` : `tail -n +1 -f -s 0.05 "$__APEX_OUT"`;
106146
106357
  const wrapped = [
106147
106358
  `__APEX_OUT=$(mktemp 2>/dev/null || echo /tmp/.apex_out_$$)`,
106148
106359
  `__APEX_ERR=$(mktemp 2>/dev/null || echo /tmp/.apex_err_$$)`,
106149
- ...streaming ? [
106150
- `stdbuf -oL tail -n +1 -f -s 0.05 "$__APEX_OUT" 2>/dev/null &`,
106151
- `__APEX_TAIL=$!`
106152
- ] : [],
106360
+ `${tailCmd} 2>/dev/null &`,
106361
+ `__APEX_TAIL=$!`,
106153
106362
  `{ ${command}
106154
106363
  } </dev/null >"$__APEX_OUT" 2>"$__APEX_ERR"`,
106155
106364
  `__APEX_EC=$?`,
106156
- ...streaming ? [
106157
- `sleep 0.1`,
106158
- `kill "$__APEX_TAIL" 2>/dev/null`,
106159
- `wait "$__APEX_TAIL" 2>/dev/null`
106160
- ] : [`cat "$__APEX_OUT"`],
106365
+ `sleep 0.1`,
106366
+ `kill "$__APEX_TAIL" 2>/dev/null`,
106367
+ `wait "$__APEX_TAIL" 2>/dev/null`,
106368
+ `printf '%s\\n' "${cutoverMarker}"`,
106369
+ `cat "$__APEX_OUT"`,
106161
106370
  `cat "$__APEX_ERR" >&2`,
106162
106371
  `rm -f "$__APEX_OUT" "$__APEX_ERR"`,
106163
106372
  `echo "${exitMarkerPrefix}$__APEX_EC"`,
@@ -106189,7 +106398,7 @@ class PersistentShell {
106189
106398
  killDescendants(this.proc.pid, "SIGKILL");
106190
106399
  setTimeout(() => {
106191
106400
  cmd.resolve({
106192
- stdout: cmd.stdout || "(no output)",
106401
+ stdout: extractFallbackStdout(cmd),
106193
106402
  stderr: (cmd.stderr || "") + (cmd.forcedStderrSuffix ?? ""),
106194
106403
  exitCode: 130
106195
106404
  });
@@ -106197,7 +106406,7 @@ class PersistentShell {
106197
106406
  }, 500);
106198
106407
  } else {
106199
106408
  cmd.resolve({
106200
- stdout: cmd.stdout || "(no output)",
106409
+ stdout: extractFallbackStdout(cmd),
106201
106410
  stderr: (cmd.stderr || "") + (cmd.forcedStderrSuffix ?? ""),
106202
106411
  exitCode: 130
106203
106412
  });
@@ -106327,6 +106536,8 @@ You can perform the full lifecycle of a penetration test and support a wide rang
106327
106536
  - **execute_command** — Run shell commands (curl, nmap, nikto, ffuf, gobuster, dig, etc.). Use for anything that needs a CLI tool.
106328
106537
  - **http_request** — Make HTTP requests with full control over method, headers, body, and redirect behavior. Redirects are NOT followed by default so you can inspect Location headers and Set-Cookie values.
106329
106538
 
106539
+ **Wordlist tools (operator-mode addition).** Tier selection is governed by the \`[BUNDLED ASSETS]\` env block. Operator-only rule: before escalating to \`LARGE_WORDLIST\`, confirm with the user via the \`response\` tool with a one-sentence rationale, unless the user pre-directed (e.g. "deep scan", "use the larger wordlist", "quick smoke check").
106540
+
106330
106541
  ## Browser Automation
106331
106542
  - **browser_navigate** — Navigate the browser to a URL (renders JS).
106332
106543
  - **browser_snapshot** — Get the accessibility tree with element refs. Always call this before clicking or filling.
@@ -106511,6 +106722,7 @@ var OperatorSettingsObject = exports_external.object({
106511
106722
  // src/core/operator/approvalGate.ts
106512
106723
  import { EventEmitter as EventEmitter3 } from "events";
106513
106724
  import { randomBytes as randomBytes2 } from "crypto";
106725
+ var DEFAULT_DECISION_TIMEOUT_MS = 15 * 60 * 1000;
106514
106726
 
106515
106727
  class ApprovalGate extends EventEmitter3 {
106516
106728
  config;
@@ -106518,7 +106730,10 @@ class ApprovalGate extends EventEmitter3 {
106518
106730
  actionHistory = [];
106519
106731
  constructor(config2) {
106520
106732
  super();
106521
- this.config = config2;
106733
+ this.config = {
106734
+ decisionTimeoutMs: DEFAULT_DECISION_TIMEOUT_MS,
106735
+ ...config2
106736
+ };
106522
106737
  }
106523
106738
  updateConfig(config2) {
106524
106739
  this.config = { ...this.config, ...config2 };
@@ -106553,14 +106768,37 @@ class ApprovalGate extends EventEmitter3 {
106553
106768
  return new Promise((resolve5, reject) => {
106554
106769
  const deferred = { approval, resolve: resolve5, reject };
106555
106770
  this.pendingApprovals.set(approval.id, deferred);
106771
+ const timeoutMs = this.config.decisionTimeoutMs;
106772
+ if (timeoutMs !== undefined && timeoutMs > 0) {
106773
+ deferred.timeoutHandle = setTimeout(() => {
106774
+ this.timeoutApproval(approval.id, timeoutMs);
106775
+ }, timeoutMs);
106776
+ }
106556
106777
  this.emitEvent({ type: "approval-needed", approval });
106557
106778
  });
106558
106779
  }
106780
+ timeoutApproval(approvalId, timeoutMs) {
106781
+ const deferred = this.pendingApprovals.get(approvalId);
106782
+ if (!deferred)
106783
+ return;
106784
+ this.pendingApprovals.delete(approvalId);
106785
+ const entry = this.recordAction(deferred.approval.toolName, deferred.approval.toolCallId, "denied");
106786
+ entry.resultSummary = `decision_timeout:${timeoutMs}ms`;
106787
+ this.emitEvent({
106788
+ type: "approval-resolved",
106789
+ id: approvalId,
106790
+ decision: "denied"
106791
+ });
106792
+ this.emitEvent({ type: "action-completed", entry });
106793
+ deferred.reject(new ApprovalTimeoutError(`Operator decision timeout after ${timeoutMs}ms for ${deferred.approval.toolName} — default-safe deny`));
106794
+ }
106559
106795
  approve(approvalId) {
106560
106796
  const deferred = this.pendingApprovals.get(approvalId);
106561
106797
  if (!deferred) {
106562
106798
  throw new Error(`No pending approval with id: ${approvalId}`);
106563
106799
  }
106800
+ if (deferred.timeoutHandle)
106801
+ clearTimeout(deferred.timeoutHandle);
106564
106802
  this.pendingApprovals.delete(approvalId);
106565
106803
  const entry = this.recordAction(deferred.approval.toolName, deferred.approval.toolCallId, "approved");
106566
106804
  this.emitEvent({
@@ -106575,6 +106813,8 @@ class ApprovalGate extends EventEmitter3 {
106575
106813
  const deferred = this.pendingApprovals.get(approvalId);
106576
106814
  if (!deferred)
106577
106815
  return;
106816
+ if (deferred.timeoutHandle)
106817
+ clearTimeout(deferred.timeoutHandle);
106578
106818
  this.pendingApprovals.delete(approvalId);
106579
106819
  const entry = this.recordAction(deferred.approval.toolName, deferred.approval.toolCallId, "denied");
106580
106820
  this.emitEvent({
@@ -106623,6 +106863,13 @@ class ApprovalDeniedError extends Error {
106623
106863
  this.name = "ApprovalDeniedError";
106624
106864
  }
106625
106865
  }
106866
+
106867
+ class ApprovalTimeoutError extends ApprovalDeniedError {
106868
+ constructor(message) {
106869
+ super(message);
106870
+ this.name = "ApprovalTimeoutError";
106871
+ }
106872
+ }
106626
106873
  // src/core/session/index.ts
106627
106874
  init_zod();
106628
106875
  import path from "path";
@@ -107435,9 +107682,9 @@ class OffensiveSecurityAgent {
107435
107682
  }
107436
107683
  }, PERSIST_INTERVAL_MS);
107437
107684
  };
107438
- const baseSystemPrompt = input.system ?? buildBaseSystemPrompt({
107685
+ const baseSystemPrompt = input.system ?? detectOSAndEnhancePrompt(buildBaseSystemPrompt({
107439
107686
  sandboxMode: agentCwd === input.session.rootPath
107440
- });
107687
+ }));
107441
107688
  const systemPrompt = baseSystemPrompt + buildSessionWorkspaceSection(input.session, agentCwd);
107442
107689
  traceWriter.writeInit({
107443
107690
  model: input.model,