@pensar/apex 2.6.1 → 2.7.0-canary.21cb83dc

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 (226) hide show
  1. package/build/{agent-yby11zaq.js → agent-68t2wzmc.js} +6 -6
  2. package/build/agent-jhekpern.js +13 -0
  3. package/build/{agent-ayreaj6z.js → agent-qvreg8a4.js} +5 -5
  4. package/build/{agent-runs-g37vkrjr.js → agent-runs-30dvbvmm.js} +18 -18
  5. package/build/agent-vybw255f.js +13 -0
  6. package/build/{apps-xn6km9yn.js → apps-na0y0992.js} +13 -13
  7. package/build/{auth-d105wc64.js → auth-dz2c5thx.js} +13 -13
  8. package/build/{blackboxAgent-s56sgx9b.js → blackboxAgent-2mwvaajb.js} +6 -6
  9. package/build/{blackboxPentest-ps78v3w7.js → blackboxPentest-s2mfze9p.js} +17 -12
  10. package/build/{cli-kb21qhvm.js → cli-1pmfnz1a.js} +4 -3
  11. package/build/{cli-ae8jqxqr.js → cli-563yntrb.js} +2 -2
  12. package/build/{cli-7eea4e2y.js → cli-5ab346kd.js} +6 -6
  13. package/build/{cli-1ve18npr.js → cli-72y76bpg.js} +3 -2
  14. package/build/{cli-fy6vh2a7.js → cli-98wmmphf.js} +1 -1
  15. package/build/{cli-c05y640n.js → cli-9jscnhtg.js} +1 -1
  16. package/build/{cli-3sp6nd8d.js → cli-9kk9tm58.js} +2 -2
  17. package/build/{cli-d37a42dc.js → cli-9pz9wjt2.js} +101 -18
  18. package/build/{cli-dpsw2fe6.js → cli-a6x4jm5a.js} +476 -193
  19. package/build/{cli-az3xq70v.js → cli-cfrdr25z.js} +1 -1
  20. package/build/{cli-ngq9dr8n.js → cli-fdrrbb9p.js} +3 -3
  21. package/build/{cli-k2nwxta0.js → cli-t09zj814.js} +2 -2
  22. package/build/{cli-qgz1q9g5.js → cli-t4q4t4dx.js} +223 -76
  23. package/build/{cli-xtc2t6me.js → cli-vdd1s3x9.js} +103 -39
  24. package/build/{cli-gx71jcke.js → cli-vn4cwac3.js} +1 -1
  25. package/build/{cli-65g6rcat.js → cli-w9nw2a4z.js} +1 -1
  26. package/build/{cli-n2en7j5b.js → cli-z7ysyrr4.js} +1 -1
  27. package/build/{cli-709rvekb.js → cli-zbbtr4sb.js} +4 -2
  28. package/build/cli.js +70 -40
  29. package/build/{config-zpqkd5cz.js → config-nkzm9arw.js} +1 -1
  30. package/build/{fastStrike-mcjdvwez.js → fastStrike-16jw1s61.js} +67 -15
  31. package/build/{fixes-kytx5dmj.js → fixes-6wxk22v5.js} +13 -13
  32. package/build/{index-4vqdgb42.js → index-36p56pcf.js} +1473 -1217
  33. package/build/{index-je6hcsqr.js → index-6nejymsc.js} +1 -1
  34. package/build/{index-fv64eb32.js → index-asm4y7e4.js} +2 -2
  35. package/build/{index-n65z6v7b.js → index-bfmn52za.js} +6 -6
  36. package/build/{index-qv4cc65p.js → index-bt4r13q7.js} +13 -13
  37. package/build/{index-dr3tg1w3.js → index-gfq1rp1q.js} +1 -1
  38. package/build/{index-wqetp6gq.js → index-j9pxgrzd.js} +12 -7
  39. package/build/{index-r9yjkfrv.js → index-n9kapn1x.js} +4 -4
  40. package/build/{index-ns4m4s01.js → index-tr6evhyg.js} +4 -4
  41. package/build/{issues-eb3q9d3a.js → issues-7rmf4ker.js} +13 -13
  42. package/build/{knowledge-fqsvtx0f.js → knowledge-s2sxh8nb.js} +13 -13
  43. package/build/lib/{chunk-1azdancq.js → chunk-0dnx79b1.js} +1 -1
  44. package/build/lib/{chunk-4hwzqthr.js → chunk-161ak2am.js} +3 -2
  45. package/build/lib/{chunk-z137x08b.js → chunk-1rqbhx4b.js} +7 -5
  46. package/build/lib/{chunk-1yct6cra.js → chunk-3hjvdf67.js} +1 -1
  47. package/build/lib/{chunk-r2dkp4tb.js → chunk-5j8pp0xf.js} +1 -1
  48. package/build/lib/{chunk-3c00n0cy.js → chunk-77se1d35.js} +8 -3
  49. package/build/lib/{chunk-yrnrbjes.js → chunk-7tft4b8b.js} +4 -2
  50. package/build/lib/{chunk-w66ce82a.js → chunk-8njjwwcw.js} +4 -2
  51. package/build/lib/{chunk-v3dk9j7k.js → chunk-aq9eyxas.js} +80 -21
  52. package/build/lib/{chunk-9tt2021m.js → chunk-d05cvnv8.js} +9 -9
  53. package/build/lib/{chunk-e8yy2k73.js → chunk-f3sq4896.js} +28 -2
  54. package/build/lib/{chunk-1fy8azee.js → chunk-fasqtjq1.js} +1 -1
  55. package/build/lib/{chunk-1jvwqnem.js → chunk-gm3b9j4y.js} +104 -40
  56. package/build/lib/{chunk-r4j8ybn9.js → chunk-hys7nemr.js} +87 -36
  57. package/build/lib/{chunk-7pwa92rn.js → chunk-j9668h16.js} +1 -1
  58. package/build/lib/{chunk-ba41jh41.js → chunk-kcw4cpr3.js} +418 -133
  59. package/build/lib/{chunk-z96pbjhd.js → chunk-m4swxy5r.js} +13 -6
  60. package/build/lib/{chunk-xhdpgpkm.js → chunk-mbsde9d0.js} +2 -2
  61. package/build/lib/{chunk-9yksqgzr.js → chunk-mpvjfvz0.js} +20 -13
  62. package/build/lib/{chunk-2qsq76xq.js → chunk-qkz5sm0d.js} +128 -34
  63. package/build/lib/{chunk-nhfax4gb.js → chunk-rfyjqybp.js} +1 -1
  64. package/build/lib/{chunk-mg03jdmt.js → chunk-vsnwzne5.js} +1 -1
  65. package/build/lib/{chunk-acgbyf5h.js → chunk-ydxhkgjw.js} +3 -2
  66. package/build/lib/{chunk-bb0ekhkw.js → chunk-z8kej0sp.js} +69 -18
  67. package/build/lib/core/agents/agentRuntime.d.ts +2 -1
  68. package/build/lib/core/agents/defineAgent.d.ts +3 -2
  69. package/build/lib/core/agents/offSecAgent/index.d.ts +3 -1
  70. package/build/lib/core/agents/offSecAgent/index.js +10 -8
  71. package/build/lib/core/agents/offSecAgent/prompt.d.ts +3 -1
  72. package/build/lib/core/agents/offSecAgent/subagentSpawner.d.ts +2 -1
  73. package/build/lib/core/agents/offSecAgent/subagentSpawner.js +5 -5
  74. package/build/lib/core/agents/offSecAgent/tools/index.js +4 -4
  75. package/build/lib/core/agents/offSecAgent/tools/listMemories.d.ts +11 -1
  76. package/build/lib/core/agents/offSecAgent/tools/reportError.d.ts +2 -1
  77. package/build/lib/core/agents/offSecAgent/tools/runPentestWorkflow.d.ts +20 -1
  78. package/build/lib/core/agents/offSecAgent/tools/spawnPentestAgent.d.ts +4 -7
  79. package/build/lib/core/agents/offSecAgent/tools/spawnPentestSwarm.d.ts +7 -1
  80. package/build/lib/core/agents/offSecAgent/tools/types.d.ts +2 -1
  81. package/build/lib/core/agents/offSecAgent/types.d.ts +7 -1
  82. package/build/lib/core/agents/specialized/attackSurface/blackboxAgent.js +9 -9
  83. package/build/lib/core/agents/specialized/attackSurface/schemas.js +9 -9
  84. package/build/lib/core/agents/specialized/authenticationAgent/index.js +10 -10
  85. package/build/lib/core/agents/specialized/codeAgent/agent.js +9 -9
  86. package/build/lib/core/agents/specialized/codeAgent/prompts.d.ts +1 -0
  87. package/build/lib/core/agents/specialized/findingJudge/agent.js +8 -8
  88. package/build/lib/core/agents/specialized/findingJudge/index.js +3 -3
  89. package/build/lib/core/agents/specialized/patching/index.js +10 -10
  90. package/build/lib/core/agents/specialized/pentest/agent.d.ts +18 -4
  91. package/build/lib/core/agents/specialized/pentest/agent.js +11 -9
  92. package/build/lib/core/agents/specialized/whiteboxAttackSurface/index.js +9 -9
  93. package/build/lib/core/ai/ai.d.ts +23 -6
  94. package/build/lib/core/ai/ai.js +2 -2
  95. package/build/lib/core/ai/index.js +2 -2
  96. package/build/lib/core/ai/models/claude-capabilities.d.ts +3 -2
  97. package/build/lib/core/ai/models/concentrate.d.ts +1 -0
  98. package/build/lib/core/ai/models/index.d.ts +1 -1
  99. package/build/lib/core/ai/providers/concentrate.d.ts +1 -0
  100. package/build/lib/core/ai/utils.d.ts +2 -0
  101. package/build/lib/core/ai/utils.js +4 -2
  102. package/build/lib/core/api/index.d.ts +3 -0
  103. package/build/lib/core/api/index.js +22 -19
  104. package/build/lib/core/api/targetedPentest.d.ts +1 -0
  105. package/build/lib/core/api/targetedPentest.js +10 -10
  106. package/build/lib/core/config/config.d.ts +3 -0
  107. package/build/lib/core/config/index.js +1 -1
  108. package/build/lib/core/findings/registry.js +3 -3
  109. package/build/lib/core/session/index.d.ts +12 -0
  110. package/build/lib/core/session/index.js +2 -2
  111. package/build/lib/core/session/persistence.d.ts +7 -0
  112. package/build/lib/core/session/persistence.js +7 -3
  113. package/build/lib/core/workflows/fastStrike.d.ts +3 -1
  114. package/build/lib/core/workflows/pentest.d.ts +8 -1
  115. package/build/lib/core/workflows/pentest.js +15 -15
  116. package/build/lib/core/workflows/seams.js +4 -4
  117. package/build/lib/core/workflows/whiteboxAttackSurface.js +11 -11
  118. package/build/lib/index.js +22 -22
  119. package/build/{logs-x62b7hk1.js → logs-70fyr848.js} +13 -13
  120. package/build/{native-rollout-evidence-c9yhfqcs.js → native-rollout-evidence-ntensvzb.js} +3 -3
  121. package/build/{offesecAgent-5whnpeta.js → offesecAgent-kk62tf60.js} +4 -4
  122. package/build/pentest-4jgznn7h.js +22 -0
  123. package/build/{pentests-e0f32aqx.js → pentests-3e41hj08.js} +13 -13
  124. package/build/recordedRunClient-w34kcch1.js +11 -0
  125. package/build/{targetedPentest-rcbs4nvp.js → targetedPentest-t9snxcj2.js} +18 -11
  126. package/build/{targets-xj9g3q0z.js → targets-1pyf21c7.js} +13 -13
  127. package/build/threatModel-48y5qjze.js +21 -0
  128. package/build/{uninstall-7s784q4a.js → uninstall-fbydd9t6.js} +1 -1
  129. package/build/{upload-4gvhwmvr.js → upload-sbhwe2fq.js} +4 -4
  130. package/build/{utils-cjrz64pc.js → utils-23903gcj.js} +3 -3
  131. package/package.json +1 -1
  132. package/src/cli.ts +48 -14
  133. package/src/core/agents/agentRuntime.test.ts +38 -0
  134. package/src/core/agents/agentRuntime.ts +5 -2
  135. package/src/core/agents/defineAgent.ts +3 -1
  136. package/src/core/agents/offSecAgent/index.ts +3 -0
  137. package/src/core/agents/offSecAgent/offensiveSecurityAgent.test.ts +92 -5
  138. package/src/core/agents/offSecAgent/offensiveSecurityAgent.ts +70 -31
  139. package/src/core/agents/offSecAgent/prompt.test.ts +46 -0
  140. package/src/core/agents/offSecAgent/prompt.ts +52 -8
  141. package/src/core/agents/offSecAgent/selectiveConstruction.publicPath.test.ts +38 -0
  142. package/src/core/agents/offSecAgent/selectiveConstruction.test.ts +64 -0
  143. package/src/core/agents/offSecAgent/subagentSpawner.ts +12 -1
  144. package/src/core/agents/offSecAgent/tools/delegateAuth.ts +1 -0
  145. package/src/core/agents/offSecAgent/tools/listMemories.test.ts +230 -0
  146. package/src/core/agents/offSecAgent/tools/listMemories.ts +73 -6
  147. package/src/core/agents/offSecAgent/tools/reportError.test.ts +6 -0
  148. package/src/core/agents/offSecAgent/tools/reportError.ts +10 -2
  149. package/src/core/agents/offSecAgent/tools/runAttackSurface.ts +2 -0
  150. package/src/core/agents/offSecAgent/tools/runPentestWorkflow.test.ts +57 -0
  151. package/src/core/agents/offSecAgent/tools/runPentestWorkflow.ts +19 -1
  152. package/src/core/agents/offSecAgent/tools/runWhiteboxScan.ts +5 -2
  153. package/src/core/agents/offSecAgent/tools/spawnCodingAgent.ts +1 -0
  154. package/src/core/agents/offSecAgent/tools/spawnPentestAgent.test.ts +72 -2
  155. package/src/core/agents/offSecAgent/tools/spawnPentestAgent.ts +32 -11
  156. package/src/core/agents/offSecAgent/tools/spawnPentestSwarm.ts +25 -5
  157. package/src/core/agents/offSecAgent/tools/threatModelGenerator.ts +1 -0
  158. package/src/core/agents/offSecAgent/tools/types.ts +6 -1
  159. package/src/core/agents/offSecAgent/tools/updateTask.ts +5 -1
  160. package/src/core/agents/offSecAgent/tools/whiteboxCandidates.ts +11 -4
  161. package/src/core/agents/offSecAgent/types.ts +9 -0
  162. package/src/core/agents/specialized/codeAgent/agent.test.ts +7 -0
  163. package/src/core/agents/specialized/codeAgent/agent.ts +9 -2
  164. package/src/core/agents/specialized/codeAgent/prompts.ts +6 -0
  165. package/src/core/agents/specialized/pentest/agent.test.ts +116 -0
  166. package/src/core/agents/specialized/pentest/agent.ts +178 -49
  167. package/src/core/agents/specialized/pentest/results.test.ts +59 -4
  168. package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.ts +1 -0
  169. package/src/core/ai/ai.operator-context.bench.test.ts +1408 -0
  170. package/src/core/ai/ai.recorded-context.test.ts +74 -0
  171. package/src/core/ai/ai.test.ts +54 -0
  172. package/src/core/ai/ai.ts +312 -82
  173. package/src/core/ai/compactionTelemetry.test.ts +2 -2
  174. package/src/core/ai/models/anthropic.ts +6 -0
  175. package/src/core/ai/models/bedrock.ts +18 -0
  176. package/src/core/ai/models/claude-capabilities.ts +29 -8
  177. package/src/core/ai/models/concentrate.ts +52 -0
  178. package/src/core/ai/models/index.ts +25 -4
  179. package/src/core/ai/models/models.test.ts +154 -0
  180. package/src/core/ai/models/openrouter.ts +43 -1
  181. package/src/core/ai/providers/anthropic-models.test.ts +60 -1
  182. package/src/core/ai/providers/bedrock-models.test.ts +81 -0
  183. package/src/core/ai/providers/concentrate.test.ts +31 -0
  184. package/src/core/ai/providers/concentrate.ts +11 -0
  185. package/src/core/ai/providers/gateway-models.test.ts +16 -6
  186. package/src/core/ai/utils.native-rollout-evidence.test.ts +1 -0
  187. package/src/core/ai/utils.ts +189 -143
  188. package/src/core/api/blackboxPentest.ts +9 -1
  189. package/src/core/api/index.ts +9 -0
  190. package/src/core/api/targetedPentest.ts +19 -5
  191. package/src/core/config/config.test.ts +35 -0
  192. package/src/core/config/config.ts +5 -0
  193. package/src/core/observability/telemetry.test.ts +2 -3
  194. package/src/core/session/index.ts +5 -0
  195. package/src/core/session/persistence.test.ts +62 -0
  196. package/src/core/session/persistence.ts +56 -0
  197. package/src/core/workflows/fastStrike.seams.test.ts +149 -0
  198. package/src/core/workflows/fastStrike.test.ts +18 -1
  199. package/src/core/workflows/fastStrike.ts +103 -11
  200. package/src/core/workflows/pentest.test.ts +104 -0
  201. package/src/core/workflows/pentest.ts +110 -7
  202. package/src/core/workflows/seams.test.ts +13 -0
  203. package/src/core/workflows/seams.ts +5 -1
  204. package/src/core/workflows/whiteboxAttackSurface.ts +1 -0
  205. package/src/tui/components/chat/loading-indicator.tsx +20 -4
  206. package/src/tui/components/chat/message-list.tsx +1 -0
  207. package/src/tui/components/commands/__tests__/advanced-settings-lifecycle.tsx +176 -0
  208. package/src/tui/components/commands/advanced-settings.test.ts +28 -0
  209. package/src/tui/components/commands/advanced-settings.tsx +237 -19
  210. package/src/tui/components/operator-dashboard/index.tsx +46 -9
  211. package/src/tui/components/operator-dashboard/logic.test.ts +106 -0
  212. package/src/tui/components/operator-dashboard/logic.ts +42 -2
  213. package/src/tui/components/operator-dashboard/run-events.test.ts +3 -1
  214. package/src/tui/components/shared/__tests__/tool-renderer-lifecycle.tsx +18 -0
  215. package/src/tui/components/shared/action-label.test.ts +9 -0
  216. package/src/tui/components/shared/compacting-icon.tsx +18 -0
  217. package/src/tui/components/shared/index.ts +1 -0
  218. package/src/tui/components/shared/tool-registry.ts +1 -0
  219. package/src/tui/components/shared/tool-renderer.tsx +21 -7
  220. package/src/tui/context/route.tsx +1 -0
  221. package/src/tui/keybindings/registry.ts +2 -0
  222. package/build/agent-6w7egcf1.js +0 -13
  223. package/build/agent-9zx75feh.js +0 -13
  224. package/build/pentest-e61hc38s.js +0 -22
  225. package/build/recordedRunClient-dp032c32.js +0 -11
  226. package/build/threatModel-jkxfa40s.js +0 -21
@@ -1,26 +1,26 @@
1
1
  import {
2
2
  createLogger,
3
3
  scopedLogger
4
- } from "./chunk-ba41jh41.js";
4
+ } from "./chunk-kcw4cpr3.js";
5
5
  import {
6
6
  OffensiveSecurityAgent2
7
- } from "./chunk-r4j8ybn9.js";
7
+ } from "./chunk-hys7nemr.js";
8
8
  import {
9
9
  inMemoryRegistryProvider2,
10
10
  withFindingPersistedHook2,
11
11
  assertDepth2,
12
12
  inProcessSeams2,
13
13
  resolveItemHooks2
14
- } from "./chunk-yrnrbjes.js";
14
+ } from "./chunk-7tft4b8b.js";
15
15
  import {
16
16
  FindingsRegistry2
17
- } from "./chunk-1azdancq.js";
17
+ } from "./chunk-0dnx79b1.js";
18
18
  import {
19
19
  inProcessSubagentSpawner2
20
- } from "./chunk-3c00n0cy.js";
20
+ } from "./chunk-77se1d35.js";
21
21
  import {
22
22
  PLAN_MODE_TOOL_NAMES2
23
- } from "./chunk-2qsq76xq.js";
23
+ } from "./chunk-qkz5sm0d.js";
24
24
  import {
25
25
  toGrpcPentestContext,
26
26
  grpcAuthorityTarget
@@ -36,13 +36,15 @@ import {
36
36
  } from "./chunk-q5e23acz.js";
37
37
  import {
38
38
  BlackboxAttackSurfaceAgent2
39
- } from "./chunk-1fy8azee.js";
39
+ } from "./chunk-fasqtjq1.js";
40
40
  import {
41
41
  TargetedPentestAgent2,
42
42
  buildPentestSystemPrompt2
43
- } from "./chunk-1jvwqnem.js";
43
+ } from "./chunk-gm3b9j4y.js";
44
44
  import {
45
45
  loadSubagentMessages2,
46
+ loadSubagentReportedFindings2,
47
+ loadSubagentObjectiveResults2,
46
48
  saveSubagentData2,
47
49
  writeAgentManifest2,
48
50
  readAgentManifest2,
@@ -51,10 +53,10 @@ import {
51
53
  finalizeManifest2,
52
54
  updateManifestEntryStatus2,
53
55
  getCompletedAgentIds2
54
- } from "./chunk-e8yy2k73.js";
56
+ } from "./chunk-f3sq4896.js";
55
57
  import {
56
58
  runWhiteboxAttackSurfaceWorkflow2
57
- } from "./chunk-z137x08b.js";
59
+ } from "./chunk-1rqbhx4b.js";
58
60
 
59
61
  // src/core/session/execution-metrics.ts
60
62
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
@@ -470,8 +472,22 @@ async function runPentestSwarmTarget2(target, index, input) {
470
472
  const entry = manifestEntries[index];
471
473
  const subagentId = entry.id;
472
474
  const subagentName = target.name ?? entry.name;
473
- if (completedIds.has(subagentId))
474
- return null;
475
+ if (completedIds.has(subagentId)) {
476
+ if (sharedHooks.findingPolicy !== "external")
477
+ return null;
478
+ const reportedFindings = loadSubagentReportedFindings2(session, subagentId);
479
+ const objectiveResults = loadSubagentObjectiveResults2(session, subagentId);
480
+ if (!reportedFindings || !objectiveResults) {
481
+ throw new Error(`Cannot resume externally graded pentest: findings or objective results for completed agent ${subagentId} are unavailable`);
482
+ }
483
+ return {
484
+ findings: [],
485
+ reportedFindings,
486
+ objectiveResults,
487
+ findingsPath: session.findingsPath,
488
+ pocsPath: session.pocsPath
489
+ };
490
+ }
475
491
  const itemHooks = resolveItemHooks2(sharedHooks, seams, target, index);
476
492
  const childSignal = abortSignal && itemHooks.abortSignal ? AbortSignal.any([abortSignal, itemHooks.abortSignal]) : abortSignal ?? itemHooks.abortSignal;
477
493
  const previousMessages = loadSubagentMessages2(session, subagentId);
@@ -568,14 +584,21 @@ async function runPentestSwarmTarget2(target, index, input) {
568
584
  abortSignal: childSignal
569
585
  });
570
586
  const result = await agent.consume();
587
+ if (itemHooks.findingPolicy === "external" && (!Array.isArray(result.reportedFindings) || !Array.isArray(result.objectiveResults))) {
588
+ throw new Error(`Externally graded pentest worker ${subagentId} ended without structured findings and objective results`);
589
+ }
571
590
  saveSubagentData2(session, {
572
591
  agentName: subagentId,
573
592
  target: target.target,
574
593
  objective: objectiveStr,
575
594
  status: "completed",
576
- findingsCount: result.findings.length,
595
+ findingsCount: result.reportedFindings?.length ?? result.findings.length,
596
+ ...itemHooks.findingPolicy === "external" ? {
597
+ reportedFindings: result.reportedFindings,
598
+ objectiveResults: result.objectiveResults
599
+ } : {},
577
600
  messages: [...previousMessages, ...lastMessages],
578
- systemPrompt: buildPentestSystemPrompt2(session),
601
+ systemPrompt: buildPentestSystemPrompt2(session, "orchestrator", "default", undefined, undefined, itemHooks.findingPolicy),
579
602
  userPrompt: agent.userPrompt
580
603
  });
581
604
  updateManifestEntryStatus2(session, subagentId, "completed");
@@ -593,7 +616,7 @@ async function runPentestSwarmTarget2(target, index, input) {
593
616
  status: "failed",
594
617
  error: error instanceof Error ? error.message : String(error),
595
618
  messages: [...previousMessages, ...lastMessages],
596
- systemPrompt: buildPentestSystemPrompt2(session),
619
+ systemPrompt: buildPentestSystemPrompt2(session, "orchestrator", "default", undefined, undefined, itemHooks.findingPolicy),
597
620
  userPrompt: agent?.userPrompt ?? ""
598
621
  });
599
622
  updateManifestEntryStatus2(session, subagentId, "failed");
@@ -639,7 +662,8 @@ async function runPentestSwarm2(input) {
639
662
  languageModelMiddleware,
640
663
  usageRecorder,
641
664
  streamIdFactory,
642
- ...hooks
665
+ ...hooks,
666
+ findingPolicy: hooks?.findingPolicy ?? input.findingPolicy
643
667
  };
644
668
  const findingsRegistry = withFindingPersistedHook2(rawFindingsRegistry, seams.hooks.onFindingPersisted);
645
669
  const completedIds = getCompletedAgentIds2(session);
@@ -668,11 +692,14 @@ async function runPentestSwarm2(input) {
668
692
  };
669
693
  const results = await seams.fanOut.spawnMany(targets, (target, index) => runPentestSwarmTarget2(target, index, targetInput), { concurrency, abortSignal });
670
694
  finalizeManifest2(session, manifestEntries, results);
695
+ if (sharedHooks.findingPolicy === "external" && results.some((result) => result === null)) {
696
+ throw new Error("Externally graded pentest has an incomplete swarm target; findings cannot be aggregated");
697
+ }
671
698
  return results;
672
699
  }
673
700
  async function runPentestWorkflow2(input) {
674
701
  if (input.fastStrike) {
675
- const { runFastStrike } = await import("./chunk-bb0ekhkw.js");
702
+ const { runFastStrike } = await import("./chunk-z8kej0sp.js");
676
703
  return runFastStrike(input);
677
704
  }
678
705
  const {
@@ -692,6 +719,7 @@ async function runPentestWorkflow2(input) {
692
719
  threatModel,
693
720
  surfaceIntegrationEnabled
694
721
  } = input;
722
+ const findingPolicy = input.hooks?.findingPolicy ?? input.findingPolicy;
695
723
  const seams = input.seams ?? inProcessSeams2({
696
724
  fanOut: input.hooks?.subagentSpawner ?? input.subagentSpawner,
697
725
  registries: {
@@ -767,7 +795,8 @@ ${combined}` : combined;
767
795
  languageModelMiddleware: input.languageModelMiddleware,
768
796
  usageRecorder: input.usageRecorder,
769
797
  streamIdFactory: input.streamIdFactory,
770
- ...input.hooks
798
+ ...input.hooks,
799
+ findingPolicy
771
800
  },
772
801
  seams
773
802
  });
@@ -787,7 +816,8 @@ ${combined}` : combined;
787
816
  languageModelMiddleware: input.languageModelMiddleware,
788
817
  usageRecorder: input.usageRecorder,
789
818
  streamIdFactory: input.streamIdFactory,
790
- ...input.hooks
819
+ ...input.hooks,
820
+ findingPolicy
791
821
  }
792
822
  });
793
823
  }
@@ -803,6 +833,16 @@ ${combined}` : combined;
803
833
  throw new DOMException("Pentest aborted by user", "AbortError");
804
834
  }
805
835
  if (swarmTargets.length === 0) {
836
+ if (findingPolicy === "external") {
837
+ return {
838
+ findings: [],
839
+ reportedFindings: [],
840
+ objectiveResults: [],
841
+ findingsPath: session.findingsPath,
842
+ pocsPath: session.pocsPath,
843
+ reportPath: null
844
+ };
845
+ }
806
846
  const report = buildPentestReport([], {
807
847
  target,
808
848
  model,
@@ -826,9 +866,12 @@ ${combined}` : combined;
826
866
  });
827
867
  const findingsRegistry = seams.registries.findings();
828
868
  const completedCount = getCompletedAgentIds2(session).size;
829
- if (completedCount < swarmTargets.length) {
830
- await runPentestSwarm2({
869
+ let externalReportedFindings = [];
870
+ let externalObjectiveResults = [];
871
+ if (findingPolicy === "external" || completedCount < swarmTargets.length) {
872
+ const swarmResults = await runPentestSwarm2({
831
873
  targets: swarmTargets,
874
+ findingPolicy,
832
875
  model,
833
876
  session,
834
877
  authConfig,
@@ -847,10 +890,26 @@ ${combined}` : combined;
847
890
  hooks: input.hooks,
848
891
  seams
849
892
  });
893
+ externalReportedFindings = swarmResults.flatMap((result) => result?.reportedFindings ?? []);
894
+ externalObjectiveResults = swarmResults.flatMap((result) => result?.objectiveResults ?? []);
850
895
  }
851
896
  if (abortSignal?.aborted) {
852
897
  throw new DOMException("Pentest aborted by user", "AbortError");
853
898
  }
899
+ if (findingPolicy === "external") {
900
+ eventBus?.emit("workflow-phase-complete", {
901
+ phase: "pentesting",
902
+ summary: { findingsCount: externalReportedFindings.length }
903
+ });
904
+ return {
905
+ findings: [],
906
+ reportedFindings: externalReportedFindings,
907
+ objectiveResults: externalObjectiveResults,
908
+ findingsPath: session.findingsPath,
909
+ pocsPath: session.pocsPath,
910
+ reportPath: null
911
+ };
912
+ }
854
913
  eventBus?.emit("workflow-phase-start", {
855
914
  phase: "reporting",
856
915
  label: "Report Generation"
@@ -1,26 +1,26 @@
1
1
  import {
2
2
  AuthenticationAgent2,
3
3
  runAuthenticationAgent3
4
- } from "./chunk-xhdpgpkm.js";
5
- import"./chunk-acgbyf5h.js";
6
- import"./chunk-r4j8ybn9.js";
7
- import"./chunk-3c00n0cy.js";
8
- import"./chunk-yrnrbjes.js";
4
+ } from "./chunk-mbsde9d0.js";
5
+ import"./chunk-ydxhkgjw.js";
6
+ import"./chunk-hys7nemr.js";
7
+ import"./chunk-77se1d35.js";
8
+ import"./chunk-7tft4b8b.js";
9
9
  import"./chunk-7gjdygcx.js";
10
10
  import"./chunk-b8eq85d2.js";
11
- import"./chunk-2qsq76xq.js";
11
+ import"./chunk-qkz5sm0d.js";
12
12
  import"./chunk-ja7j565c.js";
13
13
  import"./chunk-3q89v4xv.js";
14
14
  import"./chunk-fy3bbbqy.js";
15
- import"./chunk-1azdancq.js";
15
+ import"./chunk-0dnx79b1.js";
16
16
  import"./chunk-t5bt5vn1.js";
17
17
  import"./chunk-eb4h4k1f.js";
18
18
  import"./chunk-vx228eeq.js";
19
- import"./chunk-ba41jh41.js";
19
+ import"./chunk-kcw4cpr3.js";
20
20
  import"./chunk-8vhr65w3.js";
21
21
  import"./chunk-2njv7wz3.js";
22
22
  import"./chunk-jdjagvgr.js";
23
- import"./chunk-w66ce82a.js";
23
+ import"./chunk-8njjwwcw.js";
24
24
  import"./chunk-zrbqn62x.js";
25
25
  import"./chunk-mv74mq5n.js";
26
26
  import"./chunk-q5e23acz.js";
@@ -6,7 +6,7 @@ import {
6
6
  normalizeMessages2,
7
7
  createLogger,
8
8
  scopedLogger
9
- } from "./chunk-ba41jh41.js";
9
+ } from "./chunk-kcw4cpr3.js";
10
10
  import {
11
11
  __export
12
12
  } from "./chunk-n0ba7khr.js";
@@ -19,6 +19,8 @@ __export(exports_persistence, {
19
19
  finalizeManifest: () => finalizeManifest2,
20
20
  getCompletedAgentIds: () => getCompletedAgentIds2,
21
21
  loadSubagentMessages: () => loadSubagentMessages2,
22
+ loadSubagentObjectiveResults: () => loadSubagentObjectiveResults2,
23
+ loadSubagentReportedFindings: () => loadSubagentReportedFindings2,
22
24
  loadSubagents: () => loadSubagents2,
23
25
  readAgentManifest: () => readAgentManifest2,
24
26
  reconcileManifestOnResume: () => reconcileManifestOnResume2,
@@ -58,6 +60,28 @@ function loadSubagentMessages2(session, key) {
58
60
  return [];
59
61
  }
60
62
  }
63
+ function loadSubagentReportedFindings2(session, key) {
64
+ const snapshotPath = join(session.rootPath, SUBAGENTS_DIR, `${key}.json`);
65
+ if (!existsSync(snapshotPath))
66
+ return null;
67
+ try {
68
+ const data = JSON.parse(readFileSync(snapshotPath, "utf-8"));
69
+ return data.status === "completed" && Array.isArray(data.reportedFindings) && data.reportedFindings.every((finding) => typeof finding === "string") ? data.reportedFindings : null;
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+ function loadSubagentObjectiveResults2(session, key) {
75
+ const snapshotPath = join(session.rootPath, SUBAGENTS_DIR, `${key}.json`);
76
+ if (!existsSync(snapshotPath))
77
+ return null;
78
+ try {
79
+ const data = JSON.parse(readFileSync(snapshotPath, "utf-8"));
80
+ return data.status === "completed" && Array.isArray(data.objectiveResults) && data.objectiveResults.every((result) => result !== null && typeof result === "object" && typeof result.objective === "string" && typeof result.completed === "boolean" && (result.result === undefined || typeof result.result === "string")) ? data.objectiveResults : null;
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
61
85
  function saveSubagentData2(session, data) {
62
86
  const subagentsDir = join(session.rootPath, SUBAGENTS_DIR);
63
87
  mkdirSync(subagentsDir, { recursive: true });
@@ -83,6 +107,8 @@ function saveSubagentData2(session, data) {
83
107
  toolCallCount,
84
108
  stepCount,
85
109
  findingsCount: data.findingsCount ?? 0,
110
+ reportedFindings: data.reportedFindings,
111
+ objectiveResults: data.objectiveResults,
86
112
  status: data.status,
87
113
  error: data.error,
88
114
  messages: data.messages,
@@ -569,4 +595,4 @@ function rehydrateFromConsoleTree2(sessionId, tree) {
569
595
  return { rootPath, messages: rootMessages, subagentMessages };
570
596
  }
571
597
 
572
- export { loadSubagentMessages2, saveSubagentData2, writeAgentManifest2, readAgentManifest2, buildManifestEntries2, reconcileManifestOnResume2, finalizeManifest2, updateManifestEntryStatus2, getCompletedAgentIds2, convertModelMessagesToUI2, loadSubagents2, repairOrphanToolCalls2, rehydrateFromConsoleTree2, exports_persistence };
598
+ export { loadSubagentMessages2, loadSubagentReportedFindings2, loadSubagentObjectiveResults2, saveSubagentData2, writeAgentManifest2, readAgentManifest2, buildManifestEntries2, reconcileManifestOnResume2, finalizeManifest2, updateManifestEntryStatus2, getCompletedAgentIds2, convertModelMessagesToUI2, loadSubagents2, repairOrphanToolCalls2, rehydrateFromConsoleTree2, exports_persistence };
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  AgentRuntime,
6
6
  defineAgent
7
- } from "./chunk-acgbyf5h.js";
7
+ } from "./chunk-ydxhkgjw.js";
8
8
 
9
9
  // src/core/agents/specialized/attackSurface/blackboxAgent.ts
10
10
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createLogger,
3
3
  scopedLogger
4
- } from "./chunk-ba41jh41.js";
4
+ } from "./chunk-kcw4cpr3.js";
5
5
  import {
6
6
  isMemoryEnabled2
7
7
  } from "./chunk-t5bt5vn1.js";
@@ -15,7 +15,7 @@ import {
15
15
  REPORT_ERROR_TOOL_NAME2,
16
16
  createReportErrorTool2,
17
17
  PentestReportedError2
18
- } from "./chunk-2qsq76xq.js";
18
+ } from "./chunk-qkz5sm0d.js";
19
19
  import {
20
20
  GOOGLE_SIGNIN_PROMPT_GUIDANCE,
21
21
  browserEngineForGoogleSignIn
@@ -26,7 +26,7 @@ import {
26
26
  import {
27
27
  AgentRuntime,
28
28
  defineAgent
29
- } from "./chunk-acgbyf5h.js";
29
+ } from "./chunk-ydxhkgjw.js";
30
30
 
31
31
  // src/core/agents/specialized/pentest/agent.ts
32
32
  import { existsSync, readdirSync, readFileSync } from "node:fs";
@@ -66,6 +66,13 @@ var PentestResponseSchema2 = z.object({
66
66
  newObjectives: z.array(z.string()).optional().describe("Objectives for the NEXT run of this endpoint. Populate this directly from everything you observed: worker outcomes, what was confirmed or conclusively ruled out, recon anomalies nobody investigated, and the technology you fingerprinted. Each entry must be a focused, self-contained objective the next run can act on directly — name a concrete attack class against a concrete parameter, header, or flow. Do NOT restate anything tested this run or already marked completed in your assignment context; find the coverage gaps. Emit a small, high-signal set (typically 2-6), preferring breadth across distinct untested attack classes over payload variants. Empty/omitted when the endpoint is genuinely exhausted."),
67
67
  noFindingsReason: z.string().optional().describe("If no findings were documented, explain why (e.g., target not vulnerable, endpoint unreachable)")
68
68
  });
69
+ var PentestExternalResponseSchema2 = PentestResponseSchema2.omit({
70
+ findingsDocumented: true
71
+ }).extend({
72
+ objectiveResults: z.array(ObjectiveResultSchema).describe("Status of each assigned objective, including findings or limitations."),
73
+ reportedFindings: z.array(z.string()).describe("One concise evidence-backed finding per vulnerability, including the affected target and security impact. An empty array is valid."),
74
+ noFindingsReason: z.string().optional().describe("If no findings are reported, explain why.")
75
+ });
69
76
  function resolvePentestBrowserEngine2(hasGoogleSignIn) {
70
77
  return browserEngineForGoogleSignIn(hasGoogleSignIn);
71
78
  }
@@ -83,55 +90,67 @@ var targetedPentestWorker2 = defineAgent({
83
90
  helperWorkspaceRoot: effectiveRole === "worker" ? pentestHelperWorkspaceRoot(opts.session, opts.subagentId, opts.sandbox?.type) : undefined
84
91
  };
85
92
  },
86
- system: (opts, state) => buildPentestSystemPrompt2(opts.session, state.effectiveRole, state.mode, opts.systemScope, state.helperWorkspaceRoot),
93
+ system: (opts, state) => buildPentestSystemPrompt2(opts.session, state.effectiveRole, state.mode, opts.systemScope, state.helperWorkspaceRoot, opts.findingPolicy),
87
94
  fileWorkspaceRoot: (_opts, state) => state.helperWorkspaceRoot,
88
95
  grpc: (opts) => opts.grpc,
89
96
  browserEngine: (opts) => resolvePentestBrowserEngine2(opts.session.credentialManager?.hasGoogleSignIn() === true),
90
97
  target: (opts) => opts.target,
91
98
  systemScope: (opts) => opts.systemScope,
92
99
  mode: (_opts, state) => state.mode,
93
- activeTools: (opts, state) => buildPentestActiveTools2(state.effectiveRole, opts.session),
94
- responseSchema: () => PentestResponseSchema2,
95
- prompt: (opts, state) => buildPentestPrompt2(opts.target, opts.objectives, opts.session, opts.findingsRegistry, opts.context, opts.environmentVariables ? Object.keys(opts.environmentVariables) : undefined, opts.subagentId, state.effectiveRole, opts.session.credentialManager?.formatForPrompt(), opts.grpc, state.mode),
96
- extraTools: (_opts, state) => ({
100
+ activeTools: (opts, state) => buildPentestActiveTools2(state.effectiveRole, opts.session, opts.findingPolicy),
101
+ responseSchema: (opts) => opts.findingPolicy === "external" ? PentestExternalResponseSchema2 : PentestResponseSchema2,
102
+ prompt: (opts, state) => buildPentestPrompt2(opts.target, opts.objectives, opts.session, opts.findingsRegistry, opts.context, opts.environmentVariables ? Object.keys(opts.environmentVariables) : undefined, opts.subagentId, state.effectiveRole, opts.session.credentialManager?.formatForPrompt(), opts.grpc, state.mode, opts.findingPolicy),
103
+ extraTools: (opts, state) => ({
97
104
  [REPORT_ERROR_TOOL_NAME2]: createReportErrorTool2((err) => {
98
105
  state.reportedError = err;
99
- })
106
+ }, opts.findingPolicy)
100
107
  }),
101
108
  stopWhen: () => hasToolCall(REPORT_ERROR_TOOL_NAME2),
102
- resolveResult: async (opts, state, streamResult) => {
109
+ resolveResult: async (opts, state, streamResult, validatedResponse) => {
103
110
  if (state.reportedError) {
104
111
  throw new PentestReportedError2(state.reportedError);
105
112
  }
106
113
  let objectiveResults;
107
114
  let newObjectives;
108
- try {
109
- const response = await streamResult.response;
110
- for (const msg of response.messages ?? []) {
111
- if (msg.role !== "assistant" || !Array.isArray(msg.content))
112
- continue;
113
- for (const part of msg.content) {
114
- if (part.type === "tool-call" && part.toolName === "response" && part.input) {
115
- const input = part.input;
116
- if (input.result?.objectiveResults) {
117
- objectiveResults = input.result.objectiveResults;
118
- }
119
- if (input.result?.newObjectives) {
120
- newObjectives = input.result.newObjectives;
115
+ let reportedFindings;
116
+ if (opts.findingPolicy === "external") {
117
+ const parsed = PentestExternalResponseSchema2.safeParse(validatedResponse);
118
+ if (!parsed.success) {
119
+ throw new Error("Externally graded pentest ended without a structured findings response");
120
+ }
121
+ objectiveResults = parsed.data.objectiveResults;
122
+ newObjectives = parsed.data.newObjectives;
123
+ reportedFindings = parsed.data.reportedFindings;
124
+ } else {
125
+ try {
126
+ const response = await streamResult.response;
127
+ for (const msg of response.messages ?? []) {
128
+ if (msg.role !== "assistant" || !Array.isArray(msg.content))
129
+ continue;
130
+ for (const part of msg.content) {
131
+ if (part.type === "tool-call" && part.toolName === "response" && part.input) {
132
+ const input = part.input;
133
+ if (input.result?.objectiveResults) {
134
+ objectiveResults = input.result.objectiveResults;
135
+ }
136
+ if (input.result?.newObjectives) {
137
+ newObjectives = input.result.newObjectives;
138
+ }
121
139
  }
122
140
  }
123
141
  }
124
- }
125
- } catch {}
142
+ } catch {}
143
+ }
126
144
  const sandboxed = opts.backends?.sandboxed === true;
127
145
  const findingsPath = sandboxed ? `${SANDBOX_ARTIFACTS_ROOT}/findings` : opts.session.findingsPath;
128
- const findings = sandboxed && opts.backends ? await loadSandboxFindings(opts.backends, findingsPath, opts.abortSignal) : loadFindings(findingsPath);
146
+ const findings = opts.findingPolicy === "external" ? [] : sandboxed && opts.backends ? await loadSandboxFindings(opts.backends, findingsPath, opts.abortSignal) : loadFindings(findingsPath);
129
147
  return {
130
148
  findings,
131
149
  findingsPath,
132
150
  pocsPath: sandboxed ? `${SANDBOX_ARTIFACTS_ROOT}/pocs` : opts.session.pocsPath,
133
151
  objectiveResults,
134
- newObjectives
152
+ newObjectives,
153
+ reportedFindings
135
154
  };
136
155
  }
137
156
  });
@@ -499,14 +518,16 @@ ${SECTION_SECURITY_HEADERS_CORS}
499
518
  ${SECTION_FINDING_QUALITY}
500
519
 
501
520
  ${SECTION_STATE_CHECKPOINTING}`;
502
- function destructiveSection(allow) {
503
- return allow ? SECTION_DESTRUCTIVE_ALLOWED : SECTION_DESTRUCTIVE_BLOCKED;
521
+ function destructiveSection(allow, findingPolicy = "native") {
522
+ if (allow)
523
+ return SECTION_DESTRUCTIVE_ALLOWED;
524
+ return findingPolicy === "external" ? SECTION_DESTRUCTIVE_BLOCKED.replace(" and document_vulnerability", "") : SECTION_DESTRUCTIVE_BLOCKED;
504
525
  }
505
526
  function rateLimitTestingSection(allow) {
506
527
  return allow ? SECTION_RATE_LIMITING_TESTING_ALLOWED : SECTION_RATE_LIMITING_TESTING_BLOCKED;
507
528
  }
508
- function buildPentestSystemPrompt2(session, role = "orchestrator", mode = "default", systemScope, helperWorkspaceRoot) {
509
- const destructive = destructiveSection(session.config?.allowDestructiveActions);
529
+ function buildPentestSystemPrompt2(session, role = "orchestrator", mode = "default", systemScope, helperWorkspaceRoot, findingPolicy = "native") {
530
+ const destructive = destructiveSection(session.config?.allowDestructiveActions, findingPolicy);
510
531
  const rateLimitTesting = rateLimitTestingSection(session.config?.allowRateLimitTesting);
511
532
  const guardrails = `${destructive}
512
533
 
@@ -515,11 +536,42 @@ ${rateLimitTesting}
515
536
  ${SECTION_SIDE_EFFECT_SAFETY}`;
516
537
  const systemSection = systemScope && systemScope.memberHosts.length > 0 ? `
517
538
 
518
- ${SECTION_SYSTEM_SCOPE(systemScope.memberHosts)}` : "";
539
+ ${SECTION_SYSTEM_SCOPE(systemScope.memberHosts, findingPolicy)}` : "";
519
540
  const sourceRoot = mode === "fast-strike" ? session.config?.codebasePath : undefined;
520
541
  const helperToolsSection = role === "orchestrator" && mode !== "fast-strike" ? "" : `
521
542
 
522
543
  ${SECTION_HELPER_FILE_WORKSPACE(helperWorkspaceRoot ?? session.scratchpadPath, Boolean(sourceRoot))}`;
544
+ if (findingPolicy === "external") {
545
+ const sourcePolicy = sourceRoot ? `Read-only Source Access:
546
+ - The configured repository at ${sourceRoot} is in scope for read-only analysis. Use source-assessment tools or execute_command to inspect it. Keep generated helpers in the file workspace; do not modify target source.` : SECTION_SOURCE_CODE_PROHIBITION;
547
+ const roleMethod = mode === "fast-strike" ? `Run a focused Strike assessment against the supplied target. Work alone: observe, form the strongest hypothesis, test it with the available HTTP, browser, source, and command tools, then move to the next lead only when evidence rules the first out. Use editable scripts for stateful or multi-stage work. Do not spawn agents or create task lists.` : role === "orchestrator" ? `Lead a focused assessment. State a short plan, perform light reconnaissance and any needed authentication, then call spawn_pentest_agent for each assigned objective that needs testing. Investigate chains or untested leads with another worker when the objective calls for it. For detection-only work, stop when the requested evidence is sufficient. Combine the workers' findings and objective results in your response; workers do not write to a shared finding registry in this run.` : session.config?.taskDriven ? `Test each assigned objective. Decompose techniques with create_task, update each task as you test, adapt when a lead fails, and use list_tasks to check coverage before finishing.` : `Test each assigned objective with the strongest available techniques. Verify reachability and authentication, inspect source when explicitly in scope, probe plausible weaknesses, and distinguish genuine security impact from benign behavior.`;
548
+ const authentication = SECTION_AUTHENTICATION.replace("Build verifiable POCs, but bound the blast radius.", "When the assigned objective requires a live proof, bound the blast radius.");
549
+ const exfilGoal = session.config?.exfilMode ? `
550
+
551
+ Exfiltration goal: Locate and extract a flag in the format FLAG{...} or the assigned sensitive data. Pivot through a confirmed vulnerability when needed to reach it. Do not stop at discovery; demonstrate extraction before calling response.` : "";
552
+ return `You are an expert offensive security agent. ${roleMethod}
553
+ ${exfilGoal}
554
+
555
+ ${sourcePolicy}
556
+
557
+ Finding boundary: The caller evaluates findings after this run. Put every credible vulnerability in the response tool's reportedFindings array with its affected target, observed evidence, and likely impact. For detection-only objectives, do not build a separate proof-of-concept script, seek a second in-run review, or continue exploiting once the requested evidence is sufficient. If the objective requires exploitation or extraction, pursue that objective fully.
558
+
559
+ Use the browser for interactive or authenticated flows, HTTP tools for direct probes, and the shell for scripts or source analysis. Stay within the supplied scope and report uncertainty honestly. Complete every assigned objective before calling response.
560
+
561
+ ${guardrails}${systemSection}${helperToolsSection}
562
+
563
+ ${authentication}
564
+
565
+ ${SECTION_MATERIALITY_GUIDANCE}
566
+
567
+ ${SECTION_CREDENTIAL_DISCOVERY}
568
+
569
+ ${SECTION_SECURITY_HEADERS_CORS}
570
+
571
+ ${SECTION_STATE_CHECKPOINTING}${session.config?.promptInjectionLibrarySource ? `
572
+
573
+ ${SECTION_PROMPT_INJECTION}` : ""}`;
574
+ }
523
575
  if (mode === "fast-strike") {
524
576
  const sourcePolicy = sourceRoot ? `Read-only Source Access:
525
577
  - The configured repository at ${sourceRoot} is in scope for read-only analysis. Use available source-assessment tools or execute_command to inspect it.
@@ -547,12 +599,12 @@ ${guardrails}${systemSection}${helperToolsSection}`;
547
599
 
548
600
  ${SECTION_PROMPT_INJECTION}` : withGuardrails;
549
601
  }
550
- var SECTION_SYSTEM_SCOPE = (memberHosts) => `System Scope (structured):
602
+ var SECTION_SYSTEM_SCOPE = (memberHosts, findingPolicy = "native") => `System Scope (structured):
551
603
  - This engagement covers a multi-application System. Member hosts already present in session targets: ${memberHosts.join(", ")}.
552
604
  - Declared relationships in the application context prioritize investigation order; undeclared paths between members remain in scope when discovered.
553
605
  - For cross-service follow-ups, an orchestrator MAY set a worker \`target\` to a full URL on another member host listed above. Workers receive this same System Scope. Do not invent hosts outside that set.
554
606
  - Authentication state is origin-specific. Before dispatching an authenticated cross-service follow-up, the orchestrator must establish and verify a session on that member origin. The worker must verify access on its assigned origin and follow the Authentication rules below if access is denied.
555
- - When a confirmed finding spans multiple members, populate the \`attackPath\` argument of \`document_vulnerability\` with the ordered member-to-member hop chain. Do not leave the chain only in the narrative.`;
607
+ ${findingPolicy === "external" ? "- When a finding spans multiple members, describe the ordered member-to-member path in your reported finding." : "- When a confirmed finding spans multiple members, populate the `attackPath` argument of `document_vulnerability` with the ordered member-to-member hop chain. Do not leave the chain only in the narrative."}`;
556
608
  var SECTION_ORCHESTRATOR_DELEGATION = `Sub-Agent Delegation Rules:
557
609
  - You DO NOT call document_vulnerability directly. Findings are documented by the workers you spawn.
558
610
  - You DO NOT execute deep exploitation attempts yourself. Your tools (execute_command, http_request, browser_*) are for INITIAL RECON only — fingerprinting, sanity-checking the target, observing baseline behavior.
@@ -599,7 +651,7 @@ ${SECTION_MATERIALITY_GUIDANCE}
599
651
  ${SECTION_BROWSER_INTERACTION}
600
652
 
601
653
  ${SECTION_STATE_CHECKPOINTING}`;
602
- function buildPentestPrompt2(target, objectives, session, findingsRegistry, context, envVarNames, subagentId, role = "orchestrator", credentialContext, grpc, mode = "default") {
654
+ function buildPentestPrompt2(target, objectives, session, findingsRegistry, context, envVarNames, subagentId, role = "orchestrator", credentialContext, grpc, mode = "default", findingPolicy = "native") {
603
655
  const sessionRootPath = session.rootPath;
604
656
  const exfilMode = session.config?.exfilMode ?? false;
605
657
  const taskDriven = mode === "fast-strike" || role === "orchestrator" ? false : session.config?.taskDriven ?? false;
@@ -638,7 +690,7 @@ For \`http_request\`, pass these as the \`headers\` parameter.`, `For \`execute_
638
690
  } catch {}
639
691
  }
640
692
  let knownFindingsSection = "";
641
- if (findingsRegistry && findingsRegistry.size > 0) {
693
+ if (findingPolicy !== "external" && findingsRegistry && findingsRegistry.size > 0) {
642
694
  const existing = findingsRegistry.getFindings().map((f) => `- [${f.severity}] ${f.title} (endpoint: ${f.endpoint})`).join(`
643
695
  `);
644
696
  knownFindingsSection = `
@@ -731,7 +783,19 @@ Do NOT discover or enumerate other endpoints or services. Focus exclusively on t
731
783
  If your assignment lists ZERO open objectives (everything is already completed), skip steps 4-5, do light recon only, then finish — still populating newObjectives so the run is productive rather than re-testing completed objectives.
732
784
 
733
785
  Do NOT call document_vulnerability — that is the workers' job. Do NOT discover or enumerate other endpoints or services beyond the assigned target except for cross-service follow-ups explicitly authorized by the structured System Scope.`;
734
- const instructions = role === "orchestrator" ? orchestratorInstructions : taskDriven ? taskDrivenInstructions : exfilMode ? `## Goal
786
+ const externalInstructions = role === "orchestrator" ? `## Instructions
787
+ 1. State a short plan, perform light reconnaissance and authenticate if needed.
788
+ 2. Delegate each assigned objective with spawn_pentest_agent. Follow a concrete chain or anomaly only when the assignment calls for it or the detection objective remains unmet.
789
+ 3. Include every credible vulnerability from the workers in reportedFindings. Summarize objective coverage and any remaining leads in objectiveResults and newObjectives. The caller evaluates findings after this run.` : taskDriven ? `## Instructions
790
+ 1. Create tasks for the supplied objectives and test them with the available tools.
791
+ 2. Update task results as evidence develops; inspect list_tasks before finishing.
792
+ 3. Put each credible vulnerability in reportedFindings with the affected target, evidence, and likely impact. Follow the assigned objective's discovery or exploitation boundary. The caller evaluates findings after this run.` : `## Instructions
793
+ 1. Test the supplied objectives using the available tools and follow the strongest evidence first.
794
+ 2. Put each credible vulnerability in reportedFindings with the affected target, evidence, and likely impact. For detection-only objectives, stop when the requested evidence is sufficient; exploit or pivot only if the objective requires it.
795
+ 3. Finish with objectiveResults for each objective and any high-signal newObjectives. The caller evaluates findings after this run.`;
796
+ const instructions = findingPolicy === "external" ? `${externalInstructions}${exfilMode ? `
797
+
798
+ This is an exfiltration run: locate and extract FLAG{...} or the assigned sensitive data before finishing. Pivot through a confirmed weakness when necessary; report the result in objectiveResults without invoking a finding judge.` : ""}` : role === "orchestrator" ? orchestratorInstructions : taskDriven ? taskDrivenInstructions : exfilMode ? `## Goal
735
799
  Your target is a flag with the format FLAG{...}. Locate and extract it.
736
800
 
737
801
  ## Instructions
@@ -858,10 +922,10 @@ var SHARED_PENTEST_TOOLS = [
858
922
  "checkpoint_state"
859
923
  ];
860
924
  var MEMORY_TOOL_NAMES = ["add_memory", "list_memories", "get_memory"];
861
- function buildPentestActiveTools2(role, session) {
925
+ function buildPentestActiveTools2(role, session, findingPolicy = "native") {
862
926
  const tools = role === "orchestrator" ? [...WORKER_RECON_TOOLS, ...SHARED_PENTEST_TOOLS, "spawn_pentest_agent"] : [
863
927
  ...WORKER_RECON_TOOLS,
864
- "document_vulnerability",
928
+ ...findingPolicy === "external" ? [] : ["document_vulnerability"],
865
929
  ...WORKER_HELPER_FILE_TOOLS,
866
930
  ...SHARED_PENTEST_TOOLS,
867
931
  ...session.config?.taskDriven ? ["create_task", "update_task", "list_tasks"] : [],
@@ -919,4 +983,4 @@ function loadFindings(findingsPath) {
919
983
  }
920
984
  }).filter((f) => f !== null);
921
985
  }
922
- export { resolvePentestAgentRole2, PentestResponseSchema2, resolvePentestBrowserEngine2, targetedPentestWorker2, TargetedPentestAgent2, buildPentestSystemPrompt2, buildPentestPrompt2, buildPentestActiveTools2 };
986
+ export { resolvePentestAgentRole2, PentestResponseSchema2, PentestExternalResponseSchema2, resolvePentestBrowserEngine2, targetedPentestWorker2, TargetedPentestAgent2, buildPentestSystemPrompt2, buildPentestPrompt2, buildPentestActiveTools2 };