@pensar/apex 2.4.0 → 2.5.0-canary.22f2eb52

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 (94) hide show
  1. package/build/agent-7qtpem5z.js +12 -0
  2. package/build/agent-9khcyh5t.js +14 -0
  3. package/build/agent-bsyhck0a.js +12 -0
  4. package/build/{agent-5ejt5vpz.js → agent-ywewzc2h.js} +42 -42
  5. package/build/{apps-17wvz1d7.js → apps-11akynyv.js} +74 -43
  6. package/build/{auth-z3h9859n.js → auth-dd6r9mk4.js} +57 -61
  7. package/build/blackboxAgent-hbra4k00.js +12 -0
  8. package/build/blackboxPentest-bn5evs2z.js +61 -0
  9. package/build/{cli-xshasbwe.js → cli-3v9zs5wm.js} +31 -52
  10. package/build/{cli-mavved45.js → cli-4z46kyrk.js} +86 -93
  11. package/build/cli-7vby0hk6.js +12136 -0
  12. package/build/{cli-gq40s5b3.js → cli-8kkaeb70.js} +33 -46
  13. package/build/cli-8w8k4dph.js +15 -0
  14. package/build/cli-ag6jtndp.js +32 -0
  15. package/build/{cli-2cbwdk78.js → cli-ak78mweh.js} +4 -4
  16. package/build/cli-bb02pjt0.js +1485 -0
  17. package/build/{cli-k71t434r.js → cli-ec2hwkv3.js} +34 -76
  18. package/build/{cli-vnynf0js.js → cli-f5rw841m.js} +11 -5
  19. package/build/{cli-k8kc47pq.js → cli-gamfs2yq.js} +118 -115
  20. package/build/{cli-32z0017y.js → cli-gq5sk2j3.js} +36 -60
  21. package/build/{cli-bc05qbss.js → cli-h6y3bt60.js} +13 -21
  22. package/build/{cli-tkc598ey.js → cli-j1916nvj.js} +10035 -7661
  23. package/build/{cli-5k33webc.js → cli-jw1xftqm.js} +355 -332
  24. package/build/{cli-tznv8pf1.js → cli-n4h7ygp5.js} +4 -4
  25. package/build/{cli-b1adytsy.js → cli-q45hcq3f.js} +67 -39
  26. package/build/{cli-repbyhkk.js → cli-qkb3v2nw.js} +26063 -25373
  27. package/build/{cli-j54qa6tm.js → cli-qktcyj48.js} +1 -1
  28. package/build/cli-retw3rw5.js +12 -0
  29. package/build/cli-tjm77pmx.js +12075 -0
  30. package/build/{cli-dm0fc0bm.js → cli-v1sarr4y.js} +5 -9
  31. package/build/{cli-9rhzhgx2.js → cli-v8ph8hy2.js} +5 -5
  32. package/build/{cli-vq52kp7j.js → cli-vkxx4jzv.js} +147 -128
  33. package/build/cli-wfb4gde1.js +22 -0
  34. package/build/{cli-ee3axgts.js → cli-xbhr5khz.js} +1 -1
  35. package/build/cli-z82n3qk1.js +6 -0
  36. package/build/cli.js +689 -132
  37. package/build/{config-f1mj4nhd.js → config-kv5v9ctn.js} +29 -29
  38. package/build/{doctor-ekneewa3.js → doctor-xs4s5km8.js} +4 -9
  39. package/build/{fastStrike-8zka43xs.js → fastStrike-b8t8f916.js} +26 -28
  40. package/build/{fixes-b89s5haw.js → fixes-kcckqx3s.js} +22 -27
  41. package/build/getMachineId-bsd-zr67nd9p.js +36 -0
  42. package/build/getMachineId-darwin-fd1d562d.js +36 -0
  43. package/build/getMachineId-linux-kjmg243j.js +29 -0
  44. package/build/getMachineId-unsupported-n4r58vke.js +19 -0
  45. package/build/getMachineId-win-yzgpfsrb.js +38 -0
  46. package/build/index-3mzr07h0.js +9 -0
  47. package/build/index-63zf8jxx.js +12 -0
  48. package/build/index-a1bg29j1.js +1559 -0
  49. package/build/{index-cbwn03kz.js → index-a2xycbjs.js} +12 -31
  50. package/build/{index-6d22pyxt.js → index-ae81pvwg.js} +2995 -2432
  51. package/build/index-cbajq2xy.js +17 -0
  52. package/build/index-cn4p95gh.js +100 -0
  53. package/build/index-kas88svr.js +36 -0
  54. package/build/index-mr20g8k4.js +22 -0
  55. package/build/{index-psqjpw5m.js → index-nweqptgs.js} +7 -7
  56. package/build/{index-sf16jm0m.js → index-rx5jn1nz.js} +137 -162
  57. package/build/{issues-xx5bs4md.js → issues-jm28k288.js} +81 -35
  58. package/build/{logs-qtxe51w2.js → logs-r02tbz89.js} +20 -25
  59. package/build/{multipart-parser-g2xxkezz.js → multipart-parser-vjjdbpd1.js} +10 -10
  60. package/build/{offesecAgent-b9e2xm6v.js → offesecAgent-mmfejh1j.js} +6 -13
  61. package/build/{parse-rtccymzn.js → parse-cqecqrc5.js} +0 -4
  62. package/build/pentest-13jcm4cy.js +21 -0
  63. package/build/{pentests-6ks3szc4.js → pentests-jyn4zs7n.js} +23 -28
  64. package/build/{targetedPentest-s1ptvq8e.js → targetedPentest-m3qkbpv6.js} +16 -20
  65. package/build/{targets-sxygyj87.js → targets-rqv57as0.js} +22 -27
  66. package/build/threatModel-scmz36xr.js +19 -0
  67. package/build/{token-3bbp59y6.js → token-n0tmq8n5.js} +2 -2
  68. package/build/{token-util-6xjme11b.js → token-util-bv80pj47.js} +1 -2
  69. package/build/{uninstall-tvsh81v8.js → uninstall-bme62bdg.js} +7 -4
  70. package/build/{upload-7wdyyqmr.js → upload-hwpgx1ha.js} +7 -13
  71. package/build/{utils-7fwdkqk6.js → utils-abtz5mmk.js} +7 -29
  72. package/package.json +8 -2
  73. package/build/agent-mvpgvgks.js +0 -19
  74. package/build/agent-nhs1w5w0.js +0 -29
  75. package/build/authentication-3s97cpk4.js +0 -19
  76. package/build/blackboxAgent-gw0a1ca4.js +0 -19
  77. package/build/blackboxPentest-44333zss.js +0 -37
  78. package/build/cli-0n4r54hq.js +0 -414
  79. package/build/cli-72cvcqhg.js +0 -22
  80. package/build/cli-qqt4gj1w.js +0 -53
  81. package/build/cli-swpbx60z.js +0 -24441
  82. package/build/index-4ad3sdwk.js +0 -39
  83. package/build/index-ghwf5z3v.js +0 -12
  84. package/build/index-hqjdg6fg.js +0 -205
  85. package/build/index-mtq7kmxz.js +0 -12856
  86. package/build/index-rbzhk712.js +0 -33
  87. package/build/index-y5w6n3tb.js +0 -19
  88. package/build/main-mmjp338j.js +0 -324
  89. package/build/pentest-xtc1sjdw.js +0 -29
  90. package/build/threatModel-xsm6fwk5.js +0 -27
  91. /package/build/{cli-c8131c4q.js → cli-0wsh8j2t.js} +0 -0
  92. /package/build/{cli-e08r86zk.js → cli-b3dvxjgk.js} +0 -0
  93. /package/build/{cli-fw5r7pfj.js → cli-q126f6ef.js} +0 -0
  94. /package/build/{cli-9fsre5pt.js → cli-qba2x69h.js} +0 -0
@@ -0,0 +1,61 @@
1
+ import"./cli-qkb3v2nw.js";
2
+ import"./cli-wfb4gde1.js";
3
+ import"./cli-j1916nvj.js";
4
+ import"./cli-n4h7ygp5.js";
5
+ import"./cli-8kkaeb70.js";
6
+ import"./cli-4z46kyrk.js";
7
+ import"./cli-q45hcq3f.js";
8
+ import {
9
+ readExecutionMetrics,
10
+ writeExecutionMetrics,
11
+ runPentestWorkflow2
12
+ } from "./cli-jw1xftqm.js";
13
+ import"./cli-gq5sk2j3.js";
14
+ import"./cli-gamfs2yq.js";
15
+ import {
16
+ EMPTY_SESSION_TOKEN_USAGE,
17
+ accumulateSessionTokens
18
+ } from "./cli-ag6jtndp.js";
19
+ import"./cli-qba2x69h.js";
20
+ import"./cli-qktcyj48.js";
21
+
22
+ // src/core/api/blackboxPentest.ts
23
+ async function runPentestAgent(input) {
24
+ const persisted = readExecutionMetrics(input.session.rootPath)?.tokenUsage;
25
+ let tokenUsage = persisted ?? EMPTY_SESSION_TOKEN_USAGE;
26
+ const onStepFinish = async (event) => {
27
+ tokenUsage = accumulateSessionTokens(tokenUsage, event.usage ?? {});
28
+ await input.onStepFinish?.(event);
29
+ };
30
+ const onCacheMetrics = (metrics) => {
31
+ tokenUsage = accumulateSessionTokens(tokenUsage, {
32
+ cacheReadTokens: metrics.cacheReadInputTokens,
33
+ cacheWriteTokens: metrics.cacheCreationInputTokens
34
+ });
35
+ input.onCacheMetrics?.(metrics);
36
+ };
37
+ let result;
38
+ try {
39
+ result = await runPentestWorkflow2({
40
+ ...input,
41
+ onStepFinish,
42
+ onCacheMetrics
43
+ });
44
+ } finally {
45
+ writeExecutionMetrics({
46
+ sessionRootPath: input.session.rootPath,
47
+ tokenUsage
48
+ });
49
+ }
50
+ const { findings, findingsPath, pocsPath, reportPath } = result;
51
+ console.log(`
52
+ Found ${findings.length} vulnerabilities`);
53
+ console.log(`Findings: ${findingsPath}`);
54
+ console.log(`POCs: ${pocsPath}`);
55
+ if (reportPath)
56
+ console.log(`Report: ${reportPath}`);
57
+ return { findings, findingsPath, pocsPath, reportPath };
58
+ }
59
+ export {
60
+ runPentestAgent
61
+ };
@@ -1,17 +1,20 @@
1
+ import {
2
+ hasToolCall,
3
+ init_dist,
4
+ scopedLogger,
5
+ init_lazyLogger,
6
+ createLogger,
7
+ init_structured
8
+ } from "./cli-j1916nvj.js";
1
9
  import {
2
10
  OffensiveSecurityAgent
3
- } from "./cli-repbyhkk.js";
11
+ } from "./cli-qkb3v2nw.js";
4
12
  import {
5
13
  detectOSAndEnhancePrompt
6
- } from "./cli-tznv8pf1.js";
14
+ } from "./cli-n4h7ygp5.js";
7
15
  import {
8
- createLogger,
9
- hasToolCall,
10
- init_dist,
11
- init_lazyLogger,
12
- init_structured,
13
- scopedLogger
14
- } from "./cli-tkc598ey.js";
16
+ MOBILE_OTP_PROMPT_GUIDANCE
17
+ } from "./cli-retw3rw5.js";
15
18
 
16
19
  // src/core/agents/specialized/authenticationAgent/agent.ts
17
20
  init_dist();
@@ -141,6 +144,11 @@ every 30 seconds, so run this immediately before filling the field. If the code
141
144
  retry once (you may have crossed a period boundary). Only report an MFA barrier if no seed is available
142
145
  or two fresh codes are both rejected.
143
146
 
147
+ ${MOBILE_OTP_PROMPT_GUIDANCE}
148
+
149
+ TOTP-via-environment-variable above is unchanged and still applies when the login asks for an authenticator
150
+ app code.
151
+
144
152
  # Error Recovery
145
153
 
146
154
  If authentication fails, try these mechanical fixes (they are login mechanics, not credential changes):
@@ -191,42 +199,12 @@ var log = scopedLogger(() => createLogger("authentication-agent"));
191
199
 
192
200
  class AuthenticationAgent extends OffensiveSecurityAgent {
193
201
  constructor(opts) {
194
- const {
195
- model,
196
- target,
197
- session,
198
- authHints,
199
- authConfig,
200
- onStepFinish,
201
- abortSignal,
202
- eventBus,
203
- subagentId,
204
- context,
205
- environmentVariables,
206
- secretValues,
207
- enableThinking,
208
- thinkingEffort,
209
- openAIReasoningEffort
210
- } = opts;
202
+ const { target, authHints, context, ...base } = opts;
203
+ const { session } = base;
211
204
  const cm = session.credentialManager;
212
205
  super({
206
+ ...base,
213
207
  system: detectOSAndEnhancePrompt(AUTH_SUBAGENT_SYSTEM_PROMPT),
214
- prompt: buildAuthPrompt(target, authHints, cm, context, environmentVariables ? Object.keys(environmentVariables) : undefined),
215
- model,
216
- session,
217
- target,
218
- authConfig,
219
- onStepFinish,
220
- abortSignal,
221
- eventBus,
222
- subagentId,
223
- subagentName: opts.subagentName,
224
- environmentVariables,
225
- secretValues,
226
- enableThinking,
227
- thinkingEffort,
228
- openAIReasoningEffort,
229
- toolChoice: "auto",
230
208
  activeTools: [
231
209
  "execute_command",
232
210
  "complete_authentication",
@@ -243,14 +221,14 @@ class AuthenticationAgent extends OffensiveSecurityAgent {
243
221
  "email_search_messages",
244
222
  "email_get_message",
245
223
  "send_email",
224
+ "sms_list_messages",
246
225
  "web_search",
247
226
  "get_page"
248
227
  ],
249
228
  stopWhen: hasToolCall("complete_authentication"),
250
- resolveResult: () => {
251
- const authDataPath = join(session.rootPath, "auth", "auth-data.json");
252
- return loadAuthResult(authDataPath);
253
- }
229
+ resolveResult: () => loadAuthResult(join(session.rootPath, "auth", "auth-data.json")),
230
+ target,
231
+ prompt: buildAuthPrompt(target, authHints, cm, context, base.environmentVariables ? Object.keys(base.environmentVariables) : undefined)
254
232
  });
255
233
  }
256
234
  }
@@ -328,6 +306,10 @@ function buildAuthPrompt(target, authHints, credentialManager, context, envVarNa
328
306
  parts.push("");
329
307
  }
330
308
  if (credBlock) {
309
+ const hasMobileOtp = credentialManager?.listReferences().some((ref) => ref.additionalFieldKeys?.includes("phoneNumber"));
310
+ const smsInstructions = hasMobileOtp ? `
311
+ ${MOBILE_OTP_PROMPT_GUIDANCE}
312
+ ` : "";
331
313
  parts.push(`INSTRUCTIONS:
332
314
  You have credentials available via credential IDs — authenticate immediately.
333
315
  1. For API/form logins, use execute_command (curl) to submit credentials and capture the Set-Cookie / token response
@@ -335,7 +317,7 @@ You have credentials available via credential IDs — authenticate immediately.
335
317
  pass credentialId + credentialField (e.g. credentialField="password") instead of the raw value —
336
318
  the secret is resolved securely at execution time. NEVER type a password directly.
337
319
  3. Call complete_authentication with exported cookies/headers to persist credentials and end the run
338
-
320
+ ${smsInstructions}
339
321
  The credentials above were provided to you and have already been verified — they are SHARED across runs, so
340
322
  do not modify them or their account settings. NEVER change the password, complete a password reset /
341
323
  forced-password-change / account-recovery flow, or modify MFA/2FA settings (enrolling, disabling, or
@@ -354,14 +336,11 @@ and only pollutes results — fail fast with success=false instead.`);
354
336
  return parts.join(`
355
337
  `);
356
338
  }
357
- async function runAuthenticationAgent(input) {
339
+ async function runAuthenticationAgent2(input) {
358
340
  const agent = new AuthenticationAgent(input);
359
341
  const result = await agent.consume();
360
342
  log.info(`Authentication ${result.success ? "succeeded" : "failed"}: ${result.summary}`);
361
343
  return result;
362
344
  }
363
345
 
364
- // src/core/api/authentication.ts
365
- var runAuthenticationAgent2 = runAuthenticationAgent;
366
-
367
- export { runAuthenticationAgent2 as runAuthenticationAgent };
346
+ export { runAuthenticationAgent2 };
@@ -1,23 +1,30 @@
1
1
  import {
2
- OffensiveSecurityAgent,
3
- PentestReportedError,
4
- REPORT_ERROR_TOOL_NAME,
5
- createReportErrorTool,
6
- isMemoryEnabled,
7
- readPlan
8
- } from "./cli-repbyhkk.js";
9
- import {
10
- createLogger,
2
+ init_zod,
11
3
  hasToolCall,
12
4
  init_dist,
5
+ scopedLogger,
13
6
  init_lazyLogger,
14
- init_structured,
15
- scopedLogger
16
- } from "./cli-tkc598ey.js";
7
+ createLogger,
8
+ init_structured
9
+ } from "./cli-j1916nvj.js";
17
10
  import {
18
- exports_external,
19
- init_zod
20
- } from "./cli-swpbx60z.js";
11
+ isMemoryEnabled,
12
+ readPlan,
13
+ REPORT_ERROR_TOOL_NAME,
14
+ createReportErrorTool,
15
+ PentestReportedError,
16
+ OffensiveSecurityAgent
17
+ } from "./cli-qkb3v2nw.js";
18
+ import {
19
+ MOBILE_OTP_PROMPT_GUIDANCE
20
+ } from "./cli-retw3rw5.js";
21
+ import {
22
+ string,
23
+ number,
24
+ boolean,
25
+ array,
26
+ object
27
+ } from "./cli-tjm77pmx.js";
21
28
 
22
29
  // src/core/agents/specialized/pentest/agent.ts
23
30
  init_dist();
@@ -27,81 +34,53 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
27
34
  import { join } from "node:path";
28
35
  init_lazyLogger();
29
36
  var log = scopedLogger(() => createLogger("pentest-agent"));
30
- function resolvePentestAgentRole(mode = "default", role = "orchestrator") {
31
- return mode === "fast-strike" ? "worker" : role;
37
+ function resolvePentestAgentRole(mode = "default", role = "orchestrator", disableSubagents = false) {
38
+ if (mode === "fast-strike")
39
+ return "worker";
40
+ if (disableSubagents)
41
+ return "worker";
42
+ return role;
32
43
  }
33
- var ObjectiveResultSchema = exports_external.object({
34
- objective: exports_external.string().describe("The objective text, exactly as it was provided or a refined version"),
35
- completed: exports_external.boolean().describe("true if this objective was thoroughly tested and can be considered done for this endpoint; false if it still needs further testing in future runs"),
36
- result: exports_external.string().optional().describe("Brief description of what was found or why this objective is complete/incomplete")
44
+ var ObjectiveResultSchema = object({
45
+ objective: string().describe("The objective text, exactly as it was provided or a refined version"),
46
+ completed: boolean().describe("true if this objective was thoroughly tested and can be considered done for this endpoint; false if it still needs further testing in future runs"),
47
+ result: string().optional().describe("Brief description of what was found or why this objective is complete/incomplete")
37
48
  });
38
- var PentestResponseSchema = exports_external.object({
39
- summary: exports_external.string().describe("Brief summary of testing performed and results"),
40
- findingsDocumented: exports_external.number().describe("Number of vulnerabilities documented via document_vulnerability"),
41
- objectivesCovered: exports_external.array(exports_external.string()).describe("Which objectives were tested"),
42
- objectiveResults: exports_external.array(ObjectiveResultSchema).describe("Status of each objective: mark as completed if thoroughly tested (vulnerability confirmed and documented, OR conclusively not vulnerable), or incomplete if further testing is warranted. Include new objectives discovered during testing that should be added for future runs."),
43
- newObjectives: exports_external.array(exports_external.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."),
44
- noFindingsReason: exports_external.string().optional().describe("If no findings were documented, explain why (e.g., target not vulnerable, endpoint unreachable)")
49
+ var PentestResponseSchema = object({
50
+ summary: string().describe("Brief summary of testing performed and results"),
51
+ findingsDocumented: number().describe("Number of vulnerabilities documented via document_vulnerability"),
52
+ objectivesCovered: array(string()).describe("Which objectives were tested"),
53
+ objectiveResults: array(ObjectiveResultSchema).describe("Status of each objective: mark as completed if thoroughly tested (vulnerability confirmed and documented, OR conclusively not vulnerable), or incomplete if further testing is warranted. Include new objectives discovered during testing that should be added for future runs."),
54
+ newObjectives: array(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."),
55
+ noFindingsReason: string().optional().describe("If no findings were documented, explain why (e.g., target not vulnerable, endpoint unreachable)")
45
56
  });
46
57
 
47
- class TargetedPentestAgent extends OffensiveSecurityAgent {
58
+ class TargetedPentestAgent2 extends OffensiveSecurityAgent {
48
59
  constructor(opts) {
49
60
  const {
50
- model,
51
61
  target,
52
62
  grpc,
53
63
  objectives,
54
- session,
55
- authConfig,
56
- onStepFinish,
57
- onCacheMetrics,
58
- abortSignal,
59
- eventBus,
60
- subagentId,
61
- sandbox,
62
- findingsRegistry,
63
- messages,
64
64
  context,
65
- environmentVariables,
66
- secretValues,
67
- enableThinking,
68
- thinkingEffort,
69
- openAIReasoningEffort,
70
65
  role = "orchestrator",
71
66
  mode = "default",
72
- browserSession,
73
- display
67
+ ...base
74
68
  } = opts;
75
- const effectiveRole = resolvePentestAgentRole(mode, role);
69
+ const { session } = base;
70
+ const effectiveRole = resolvePentestAgentRole(mode, role, session.config?.disableSubagents ?? false);
71
+ const systemScope = opts.systemScope;
76
72
  let reportedError = null;
77
73
  super({
78
- system: buildPentestSystemPrompt(session, effectiveRole, mode),
79
- prompt: buildPentestPrompt(target, objectives, session, findingsRegistry, context, environmentVariables ? Object.keys(environmentVariables) : undefined, subagentId, effectiveRole, session.credentialManager?.formatForPrompt(), grpc, mode),
80
- model,
81
- session,
82
- target,
74
+ ...base,
75
+ system: buildPentestSystemPrompt2(session, effectiveRole, mode, systemScope),
83
76
  grpc,
84
- authConfig,
85
- onStepFinish,
86
- onCacheMetrics,
87
- abortSignal,
88
- eventBus,
89
- subagentId,
90
- subagentName: opts.subagentName,
91
- sandbox,
92
- findingsRegistry,
93
- messages,
94
- environmentVariables,
95
- secretValues,
96
- enableThinking,
97
- thinkingEffort,
98
- openAIReasoningEffort,
99
- browserSession,
100
- display,
77
+ target,
78
+ prompt: buildPentestPrompt(target, objectives, session, base.findingsRegistry, context, base.environmentVariables ? Object.keys(base.environmentVariables) : undefined, base.subagentId, effectiveRole, session.credentialManager?.formatForPrompt(), grpc, mode),
101
79
  mode,
102
80
  activeTools: buildPentestActiveTools(effectiveRole, session),
103
81
  responseSchema: PentestResponseSchema,
104
82
  extraTools: {
83
+ ...base.extraTools,
105
84
  [REPORT_ERROR_TOOL_NAME]: createReportErrorTool((err) => {
106
85
  reportedError = err;
107
86
  })
@@ -204,13 +183,13 @@ var SECTION_BROWSER_INTERACTION = `Browser Interaction:
204
183
  - Screenshots are cheap — prefer taking one and not needing it over skipping one and losing visibility. Do NOT attempt to conserve tokens by skipping screenshots during browser-driven testing.
205
184
  - Screenshots are automatically stored and displayed alongside your tool call logs, so each one directly improves the user's ability to follow the test in real time.`;
206
185
  var SECTION_AUTHENTICATION = `Authentication:
207
- - If the prompt includes an "Existing Authentication Session" section, USE those cookies/headers on every request and do NOT re-authenticate up front. If such a request returns 401/403, that provided session has expired note it in your findings (and call report_error if it blocks all further testing). Only log in yourself (following any "Available Credentials" instructions) if that provided session expires mid-run.
186
+ - If the prompt includes an "Existing Authentication Session" section, use those cookies/headers on requests to the origin they authorize and do NOT re-authenticate up front there. Verify them against a protected resource on your assigned origin. A 401/403 from one resource does not by itself prove authentication failure. Verify the session against a known protected or session endpoint and re-authenticate on the assigned origin only if needed. Call report_error with reason "authentication_failed" only if required authentication cannot be established and this blocks the assigned objective or all further testing; otherwise continue any reachable testing.
208
187
  - Otherwise, if the target requires authentication, log in yourself. When an "Available Credentials" section is present, follow the authentication instructions in each credential's Context exactly — use the method it describes (for example, a token/API exchange driven with execute_command or http_request) instead of defaulting to a browser login. Only fall back to driving the login flow in the browser with browser_navigate + browser_fill when the Context does not specify how to authenticate. Prefer credentialId + credentialField so secrets are resolved securely; injected credential environment variables are also available inside execute_command.
209
188
  - After a successful login, capture the resulting session credentials and reuse them for raw requests. For a browser login, call browser_get_cookies to extract the session cookies (including httpOnly ones) — pass them as the Cookie header to http_request, or as -H "Cookie: ..." / -b flags to execute_command (curl). Any worker you spawn automatically inherits a snapshot of your authenticated browser session.
210
189
  - For http_request: include the captured Cookie and any Authorization headers on every call. For execute_command (curl): include -H "Cookie: ..." and/or -H "Authorization: ..." flags.
211
- - If a request returns 401/403 after you logged in yourself, your captured session may have expired re-authenticate the same way you did originally and refresh your session cookies/tokens.
212
- - Do NOT spin your wheels on authentication. If you have followed the credential Context instructions and still cannot authenticate, do NOT try to work around it — do NOT register a new account, self-sign-up, or fabricate credentials to authenticate. Those are not the credentials under test and only pollute results. (Registering a throwaway account is acceptable only as a disposable *target* for destructive-flow POCs per the blast-radius rungs below — never as a substitute for authenticating as the credential under test.) Make at most a couple of genuine attempts, then call report_error with reason "authentication_failed" and a specific message describing exactly what you tried and how it failed.
213
- - If you cannot authenticate with the available credentials, or another runtime condition blocks all testing, call report_error with a clear, specific message instead of giving up silently or documenting a non-finding.
190
+ - If a request returns 401/403 after you logged in yourself, verify the session against a known protected or session endpoint. Re-authenticate the same way you did originally and refresh your session cookies/tokens only when that verification shows the session is missing or expired.
191
+ - Do NOT spin your wheels on authentication. If you have followed the credential Context instructions and still cannot authenticate, do NOT try to work around it — do NOT register a new account, self-sign-up, or fabricate credentials to authenticate. Those are not the credentials under test and only pollute results. (Registering a throwaway account is acceptable only as a disposable *target* for destructive-flow POCs per the blast-radius rungs below — never as a substitute for authenticating as the credential under test.) Make at most a couple of genuine attempts. If required authentication still cannot be established and blocks the assigned objective or all further testing, call report_error with reason "authentication_failed" and a specific message describing exactly what you tried and how it failed; otherwise continue reachable testing and include the limitation in your final response.
192
+ - If unavailable authentication or another runtime condition blocks the assigned objective or all further testing, call report_error with a clear, specific message instead of giving up silently or documenting a non-finding. Do not abort for a non-blocking limitation.
214
193
  - Build verifiable POCs, but bound the blast radius. Prove impact with the least-invasive action that still demonstrates the flaw, preferring earlier rungs:
215
194
  1. Prove a broken-authorization / privileged-role / IDOR boundary with a READ, or with a benign, reversible write to a low-impact field (e.g. your own display name). That a privileged call is accepted against an object you should not be able to reach is usually the finding — prefer this over disabling security controls, changing quotas/limits, or mutating another user.
216
195
  2. If a reversible state-changing write is the only convincing proof, capture the current value, make the change, capture evidence (response/screenshot), then immediately restore the original value — and prefer your own account or a throwaway account you registered for this test over a shared or provided account. Do NOT rely on end-of-run cleanup alone; a crash mid-run can strip it before it runs.
@@ -495,7 +474,7 @@ function destructiveSection(allow) {
495
474
  function rateLimitTestingSection(allow) {
496
475
  return allow ? SECTION_RATE_LIMITING_TESTING_ALLOWED : SECTION_RATE_LIMITING_TESTING_BLOCKED;
497
476
  }
498
- function buildPentestSystemPrompt(session, role = "orchestrator", mode = "default") {
477
+ function buildPentestSystemPrompt2(session, role = "orchestrator", mode = "default", systemScope) {
499
478
  const destructive = destructiveSection(session.config?.allowDestructiveActions);
500
479
  const rateLimitTesting = rateLimitTestingSection(session.config?.allowRateLimitTesting);
501
480
  const guardrails = `${destructive}
@@ -503,38 +482,48 @@ function buildPentestSystemPrompt(session, role = "orchestrator", mode = "defaul
503
482
  ${rateLimitTesting}
504
483
 
505
484
  ${SECTION_SIDE_EFFECT_SAFETY}`;
485
+ const systemSection = systemScope && systemScope.memberHosts.length > 0 ? `
486
+
487
+ ${SECTION_SYSTEM_SCOPE(systemScope.memberHosts)}` : "";
506
488
  if (mode === "fast-strike") {
507
- const withGuardrails2 = `${PENTEST_SYSTEM_PROMPT_STRIKE}
489
+ const withGuardrails = `${PENTEST_SYSTEM_PROMPT_STRIKE}
508
490
 
509
- ${guardrails}`;
510
- return session.config?.promptInjectionLibrarySource ? `${withGuardrails2}
491
+ ${guardrails}${systemSection}`;
492
+ return session.config?.promptInjectionLibrarySource ? `${withGuardrails}
511
493
 
512
- ${SECTION_PROMPT_INJECTION}` : withGuardrails2;
494
+ ${SECTION_PROMPT_INJECTION}` : withGuardrails;
513
495
  }
514
496
  if (role === "orchestrator") {
515
497
  return `${PENTEST_SYSTEM_PROMPT_ORCHESTRATOR}
516
498
 
517
- ${guardrails}`;
499
+ ${guardrails}${systemSection}`;
518
500
  }
519
501
  const taskDriven = session.config?.taskDriven ?? false;
520
502
  const exfilMode = session.config?.exfilMode ?? false;
521
503
  const base = taskDriven ? exfilMode ? PENTEST_SYSTEM_PROMPT_TASK_DRIVEN_EXFIL : PENTEST_SYSTEM_PROMPT_TASK_DRIVEN : exfilMode ? PENTEST_SYSTEM_PROMPT_EXFIL : PENTEST_SYSTEM_PROMPT_BASE;
522
504
  const withGuardrails = `${base}
523
505
 
524
- ${guardrails}`;
506
+ ${guardrails}${systemSection}`;
525
507
  return session.config?.promptInjectionLibrarySource ? `${withGuardrails}
526
508
 
527
509
  ${SECTION_PROMPT_INJECTION}` : withGuardrails;
528
510
  }
511
+ var SECTION_SYSTEM_SCOPE = (memberHosts) => `System Scope (structured):
512
+ - This engagement covers a multi-application System. Member hosts already present in session targets: ${memberHosts.join(", ")}.
513
+ - Declared relationships in the application context prioritize investigation order; undeclared paths between members remain in scope when discovered.
514
+ - 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.
515
+ - 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.
516
+ - 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.`;
529
517
  var SECTION_ORCHESTRATOR_DELEGATION = `Sub-Agent Delegation Rules:
530
518
  - You DO NOT call document_vulnerability directly. Findings are documented by the workers you spawn.
531
519
  - 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.
532
520
  - Each spawn_pentest_agent call MUST cover exactly ONE objective from the assignment, plus optional supporting context. Do not batch multiple objectives into one spawn — the UI surfaces each spawn as its own timeline, and per-objective spawns give each worker a clean, focused context window.
533
- - Target URL propagation: the \`target\` you received already encodes the specific domain + endpoint path the caller wants tested (e.g. https://example.com/api/users/{id}). Forward that EXACT URL into every spawn_pentest_agent call's \`target\` field. Do NOT strip the path back to a bare domain, do NOT swap the path for some other endpoint, and do NOT invent new endpoints workers do not perform endpoint discovery, they deeply test the path they are given. The only time a worker's \`target\` should differ from yours is when recon surfaced a closely-related sibling endpoint on the same host that belongs to a follow-up objective; even then, send the full URL with the new path, not a bare host.
534
- - After all per-objective workers complete, spawn ONE final "chain & explore" worker. Pass it: a brief summary of what earlier workers found (or didn't find), plus any anomalous behaviors observed during recon. Its job is to chain confirmed findings into higher-impact attacks AND probe for additional vulnerabilities that fall outside the original objective list. Send it the same endpoint URL unless an earlier worker confirmed a vulnerability on a sibling endpoint that the chain depends on in which case pass that sibling's full URL.
521
+ - Target URL propagation: use the full assigned URL by default and never strip it to a bare domain. A worker may receive a recon-supported sibling endpoint that belongs to its follow-up objective. Change hosts only for a cross-service follow-up when the structured System Scope explicitly lists that member host. Always send a full URL, and never invent a host or endpoint outside the authorized session scope.
522
+ - After all per-objective workers complete, spawn ONE final "chain & explore" worker. Pass it: a brief summary of what earlier workers found (or didn't find), plus any anomalous behaviors observed during recon. Its job is to chain confirmed findings into higher-impact attacks AND probe for additional vulnerabilities that fall outside the original objective list. Send it the same endpoint URL unless an earlier worker confirmed a vulnerability on a related sibling endpoint — including an explicitly listed System Scope member — that the chain depends on; then pass that endpoint's full URL.
535
523
  - Do not call spawn_pentest_agent before stating your plan in plain text. The plan must be visible to the user as an assistant message, not just inferred from tool calls.
536
524
  - Cloned browser session — every worker you spawn gets its OWN isolated Chromium, seeded at spawn time with a snapshot of your current cookies and per-origin localStorage. Practical implications:
537
- - If authentication is required, log in ONCE in YOUR browser during recon. Every worker you spawn after that will start already authenticated do NOT instruct workers to re-authenticate. Workers that authenticate themselves only authenticate their own cloned browser, so re-auth wastes turns.
525
+ - If authentication is required, authenticate in YOUR browser during recon. Workers assigned to an origin you authenticated will start with that state, so do NOT instruct them to re-authenticate up front.
526
+ - Authentication does not automatically carry to another origin. Before spawning a cross-service worker that needs authenticated access, establish and verify a session on its target origin. Tell the worker which origin was verified; if access is denied, it must follow the Authentication rules below rather than treating one 401/403 as a blocking authentication failure.
538
527
  - Worker browser actions are LOCAL to the worker's clone. A worker's navigations, form fills, \`browser_evaluate\` mutations, and \`localStorage\`/\`sessionStorage\` writes are NOT visible to you or to sibling workers. So workers can fire payloads, trigger alerts, or clobber DOM state without breaking each other or you.
539
528
  - Conversely, if you want state to be visible to the next worker, set it up in YOUR browser before spawning. Each worker sees the snapshot of your browser AT THE MOMENT YOU CALL spawn_pentest_agent — later mutations in your browser propagate to subsequent spawns but not to in-flight workers.
540
529
  - Worker sessions are torn down when the worker finishes, so any cookies the worker acquired during testing (post-auth flows, OAuth callbacks, etc.) are discarded. If a worker discovers a useful login flow, summarize the credentials in your final response or repeat the flow in YOUR browser before the next spawn.`;
@@ -550,7 +539,7 @@ Your methodology:
550
539
  3. RECON & AUTHENTICATE — Perform LIGHT initial reconnaissance to confirm the target is reachable and understand baseline behavior. Use http_request for a handful of probes, browser_navigate + browser_snapshot to see the surface, and execute_command sparingly. Do NOT begin exploitation here — that is the workers' job. Note any anomalies (unusual error responses, exposed headers, framework fingerprints, surprising endpoint behavior) for the final exploratory worker.
551
540
  - If authentication is required (an "Existing Authentication Session" section is absent and the target / objectives need a logged-in session), you MUST authenticate NOW, in YOUR browser, BEFORE any fan-out. Follow the "Available Credentials" instructions exactly — use the method each credential's Context describes (e.g. a token/API exchange via execute_command or http_request) rather than defaulting to a browser login; only drive the browser login flow (browser_navigate + browser_fill with credentialId/credentialField) when the Context does not specify how.
552
541
  - VERIFY the session before fanning out: request a protected resource and confirm it does NOT return 401/403. Use browser_get_cookies to capture the session cookies for reuse in raw http_request / curl calls.
553
- - Authenticating HERE (not in the workers) is critical: each worker you spawn inherits a snapshot of YOUR browser's authenticated cookies + localStorage at spawn time, so ONE successful login up front propagates to every worker. Do NOT instruct workers to re-authenticate.
542
+ - Authenticating HERE (not in the workers) is critical: each worker you spawn inherits YOUR browser's cookies + localStorage for origins where you established a session. Before an authenticated cross-service spawn, establish and verify the session on that member origin too. Do NOT instruct a worker to re-authenticate up front for an origin you already verified; if access is denied, it must follow the Authentication rules below.
554
543
  - If you cannot authenticate and the objectives require it, call report_error with reason "authentication_failed" and a specific message BEFORE spawning any workers — do not fan out unauthenticated workers that will all fail, and do not report non-findings.
555
544
  4. FAN OUT — For EACH objective, call spawn_pentest_agent EXACTLY ONCE. Each spawn dispatches a focused worker that will perform the full PLAN → VERIFY → PREPARE → TEST → EXPLOIT → DOCUMENT loop on its objective. Workers write findings to the shared findings registry — you do NOT need to forward findings between them.
556
545
  5. CHAIN & EXPLORE — After all per-objective workers complete, call spawn_pentest_agent ONE FINAL TIME with a synthesized objective that:
@@ -588,7 +577,7 @@ function buildPentestPrompt(target, objectives, session, findingsRegistry, conte
588
577
  const parts = [
589
578
  `
590
579
  ## Existing Authentication Session`,
591
- `An authenticated session already exists **do NOT re-authenticate**. Include these credentials in every request.
580
+ `An authenticated session already exists. Use these credentials on the origin they authorize and do not re-authenticate up front there. On another structured System member origin, verify protected access first; if access is denied, follow the system Authentication rules.
592
581
  `
593
582
  ];
594
583
  if (authData.cookies) {
@@ -690,18 +679,19 @@ Do NOT discover or enumerate other endpoints or services. Focus exclusively on t
690
679
  1. Call list_memories to review any prior knowledge relevant to this target or engagement.
691
680
  2. State the objectives and outline your orchestration plan in plain text BEFORE any tool calls — one bullet per objective, briefly naming the attack class each worker should focus on.
692
681
  3. Perform LIGHT initial recon (a handful of http_request probes, browser_navigate + browser_snapshot to see the surface). Do NOT begin exploitation here — that is the workers' job. Note any anomalies you observe for the final exploratory worker.
693
- - AUTHENTICATE FIRST if the target/objectives need a logged-in session and no "Existing Authentication Session" is provided: log in ONCE in YOUR browser during this recon step, following the "Available Credentials" instructions exactly (prefer the credential Context's method; use credentialId/credentialField so secrets resolve securely). Verify the session with a protected request (expect NOT 401/403) and capture cookies via browser_get_cookies. Every worker inherits your authenticated browser snapshot, so do this BEFORE fan-out and do NOT have workers re-authenticate. If you cannot authenticate and the objectives require it, call report_error with reason "authentication_failed" instead of fanning out.
682
+ - AUTHENTICATE FIRST if the target/objectives need a logged-in session and no "Existing Authentication Session" is provided: authenticate in YOUR browser during this recon step, following the "Available Credentials" instructions exactly (prefer the credential Context's method; use credentialId/credentialField so secrets resolve securely). Verify the session with a protected request (expect NOT 401/403) and capture cookies via browser_get_cookies. Workers inherit auth only for origins where you established it. Before an authenticated cross-service spawn, establish and verify a session on that member origin too. Do not have workers re-authenticate up front on a verified origin; if access is denied, the worker must follow the system Authentication rules. If you cannot authenticate and the objectives require it, call report_error with reason "authentication_failed" instead of fanning out.
694
683
  4. Call spawn_pentest_agent EXACTLY ONCE PER OBJECTIVE. For every spawn:
695
- - Set \`target\` to the FULL URL from the assignment above (domain + endpoint path) pass it through verbatim. Do not strip the path or rewrite the host. Workers do not perform endpoint discovery; they deeply test the path you hand them.
684
+ - Use the FULL URL from the assignment above (domain + endpoint path) by default; never strip it to a bare domain. A recon-supported sibling endpoint may be used when it belongs to the objective. Rewrite the host only for a cross-service follow-up when the structured System Scope explicitly lists that member host. Always pass a full URL and never invent a host or endpoint outside the authorized session scope.
685
+ - Authentication state is origin-specific. If an authenticated cross-service follow-up changes origins, establish and verify auth on that member origin before spawning. Tell the worker which origin was verified and whether authenticated access is still required.
696
686
  - Pass the matching objective in the \`objectives\` array (a single-element array).
697
687
  - Use the \`context\` field to forward any recon insights specific to that objective. If your earlier browser actions left state the worker should know about (already logged in as X, certain modal already dismissed), call that out in \`context\` — each worker is seeded with a snapshot of YOUR browser's cookies and localStorage at the moment of the spawn call.
698
- 5. After all per-objective workers complete, call spawn_pentest_agent ONE FINAL TIME with a synthesized "chain & explore" objective: summarize what earlier workers confirmed/ruled out, call out unaddressed anomalies, and direct the worker to chain confirmed findings AND probe for additional vulnerabilities outside the original objective list. Send it the same endpoint URL as your assignment unless an earlier worker's confirmed finding on a sibling endpoint is what makes the chain possible.
688
+ 5. After all per-objective workers complete, call spawn_pentest_agent ONE FINAL TIME with a synthesized "chain & explore" objective: summarize what earlier workers confirmed/ruled out, call out unaddressed anomalies, and direct the worker to chain confirmed findings AND probe for additional vulnerabilities outside the original objective list. Send it the same endpoint URL as your assignment unless an earlier worker's confirmed finding on a related sibling endpoint — including an explicitly listed System Scope member — is what makes the chain possible.
699
689
  6. Use add_memory to save reusable learnings from this engagement.
700
690
  7. Call the response tool with your final summary. Compile objectiveResults from worker reports, and populate newObjectives directly from the coverage you orchestrated (worker outcomes, confirmed/ruled-out results, unexplored recon anomalies, technology fingerprints) — a small focused set of objectives for the next run that are not already tested this run or completed in your context. Empty array only if the endpoint is genuinely exhausted.
701
691
 
702
692
  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.
703
693
 
704
- Do NOT call document_vulnerability — that is the workers' job. Do NOT discover or enumerate other endpoints or services beyond the assigned target.`;
694
+ 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.`;
705
695
  const instructions = role === "orchestrator" ? orchestratorInstructions : taskDriven ? taskDrivenInstructions : exfilMode ? `## Goal
706
696
  Your target is a flag with the format FLAG{...}. Locate and extract it.
707
697
 
@@ -726,10 +716,12 @@ Your target is a flag with the format FLAG{...}. Locate and extract it.
726
716
  8. After testing ALL objectives, call the response tool with your final summary
727
717
 
728
718
  Do NOT discover or enumerate other endpoints or services. Focus exclusively on the target and objectives above.`;
719
+ const mobileOtpGuidance = credentialContext?.includes("phoneNumber") ? `
720
+ ${MOBILE_OTP_PROMPT_GUIDANCE}
721
+ ` : "";
729
722
  const credentialSection = credentialContext ? `
730
723
  ## Available Credentials
731
- The operator provided the following credentials and authentication instructions for this engagement. Authenticate by following the instructions in each credential's Context exactly — use the method it describes (for example, a token/API exchange via execute_command or http_request) rather than defaulting to a browser login. Treat the Context as the source of truth for how to authenticate, and how to re-authenticate if a provided session expires. When a tool needs a secret value and supports it (e.g. browser_fill), reference it by credentialId + credentialField so the secret resolves securely at execution time instead of hardcoding it. If you cannot authenticate with these, call report_error with reason "authentication_failed" and a specific message rather than reporting a non-finding.
732
-
724
+ The operator provided the following credentials and authentication instructions for this engagement. Authenticate by following the instructions in each credential's Context exactly — use the method it describes (for example, a token/API exchange via execute_command or http_request) rather than defaulting to a browser login. Treat the Context as the source of truth for how to authenticate, and how to re-authenticate if a provided session expires. When a tool needs a secret value and supports it (e.g. browser_fill), reference it by credentialId + credentialField so the secret resolves securely at execution time instead of hardcoding it. If required authentication cannot be established and blocks the assigned objective or all further testing, call report_error with reason "authentication_failed" and a specific message; otherwise continue reachable testing and report the limitation in your final response.${mobileOtpGuidance}
733
725
  ${credentialContext}
734
726
  ` : "";
735
727
  const contextSection = context ? `
@@ -806,6 +798,7 @@ var SHARED_PENTEST_TOOLS = [
806
798
  "email_search_messages",
807
799
  "email_get_message",
808
800
  "send_email",
801
+ "sms_list_messages",
809
802
  "list_memories",
810
803
  "get_memory",
811
804
  "add_memory",
@@ -840,4 +833,4 @@ function loadFindings(findingsPath) {
840
833
  }
841
834
  }).filter((f) => f !== null);
842
835
  }
843
- export { resolvePentestAgentRole, PentestResponseSchema, TargetedPentestAgent, buildPentestSystemPrompt, buildPentestPrompt, buildPentestActiveTools };
836
+ export { TargetedPentestAgent2, buildPentestSystemPrompt2 };