@pensar/apex 2.3.0-canary.69bfb82f → 2.3.0-canary.7d0ff84a

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 (55) hide show
  1. package/build/{agent-xeze611p.js → agent-en3cf7ks.js} +9 -9
  2. package/build/agent-fg3e80a5.js +19 -0
  3. package/build/{agent-9ck6hcgm.js → agent-xw0emp2e.js} +8 -8
  4. package/build/{apps-z4t1t8vq.js → apps-nb93qqan.js} +17 -17
  5. package/build/{auth-9y0h9cc2.js → auth-3yhq5eh3.js} +35 -17
  6. package/build/authentication-abnrrx5d.js +19 -0
  7. package/build/blackboxAgent-zmwwqnkm.js +19 -0
  8. package/build/{blackboxPentest-byjp9njm.js → blackboxPentest-7desnj4h.js} +14 -14
  9. package/build/{cli-84zf1xh9.js → cli-2jmcpp2j.js} +1 -1
  10. package/build/{cli-x3dp6b1d.js → cli-2sf49904.js} +1 -1
  11. package/build/{cli-6d37md4z.js → cli-5n4q289y.js} +1 -1
  12. package/build/{cli-0nhhne05.js → cli-729r0ms5.js} +1 -1
  13. package/build/{cli-3v63bjde.js → cli-7k9750yn.js} +2 -2
  14. package/build/{cli-x8a6x5qp.js → cli-8jaz2enb.js} +2 -2
  15. package/build/{cli-nz9t18bj.js → cli-8zeepea9.js} +31 -21
  16. package/build/{cli-phg6k6r3.js → cli-af4ntw65.js} +5 -139
  17. package/build/{cli-5kw8aevs.js → cli-fd7k577q.js} +2 -2
  18. package/build/{cli-56zyg4kv.js → cli-gkqya1mj.js} +449 -41
  19. package/build/{cli-b5fgnn98.js → cli-ks3x11h1.js} +24 -8
  20. package/build/{cli-mfsnae61.js → cli-kxsrmx74.js} +2 -1
  21. package/build/{cli-ycdcat4d.js → cli-pf21zymc.js} +1 -1
  22. package/build/{cli-j2xnatde.js → cli-pt68r0a9.js} +206 -33
  23. package/build/{cli-5r9kv574.js → cli-r5htb0jx.js} +3 -3
  24. package/build/{cli-xtr26a9f.js → cli-r8hsdfaf.js} +34 -9
  25. package/build/{cli-t3w55a46.js → cli-s7fwee5f.js} +1 -1
  26. package/build/{cli-yz80qkzn.js → cli-ycj65kyw.js} +6 -0
  27. package/build/cli.js +34 -33
  28. package/build/{config-n46nr9dn.js → config-8gz8d14c.js} +3 -3
  29. package/build/{doctor-pmxj4q08.js → doctor-xxgdq7d0.js} +7 -6
  30. package/build/{fastStrike-wnceneew.js → fastStrike-bckk9gg7.js} +28 -10
  31. package/build/{fixes-ebea8j04.js → fixes-z5hy1mtp.js} +16 -16
  32. package/build/{index-v12mbkx8.js → index-00ncykh1.js} +2 -2
  33. package/build/{index-zgpq7k03.js → index-2xe72r1a.js} +7 -6
  34. package/build/{index-mcav8n18.js → index-b3hekr8b.js} +3 -3
  35. package/build/{index-7wwrt670.js → index-m9ah2094.js} +93 -30
  36. package/build/{index-grtryfy3.js → index-snk4th5h.js} +4 -4
  37. package/build/{index-8nhy408y.js → index-vtr2p8ha.js} +9 -9
  38. package/build/{index-z32wkpxq.js → index-y7dw3s1s.js} +16 -8
  39. package/build/{issues-y41kba23.js → issues-qkvbnstj.js} +16 -16
  40. package/build/{logs-b7h122e9.js → logs-hg5cnn8h.js} +16 -16
  41. package/build/{offesecAgent-fr9fpzzk.js → offesecAgent-c7cnp62j.js} +8 -8
  42. package/build/pentest-wwnc443p.js +29 -0
  43. package/build/{pentests-c6x7t7n4.js → pentests-ek45m23z.js} +16 -16
  44. package/build/{targetedPentest-jyq4azbd.js → targetedPentest-yt5wdr2m.js} +9 -9
  45. package/build/{targets-xdv5m9vq.js → targets-m42h5cry.js} +16 -16
  46. package/build/threatModel-pnamejqd.js +27 -0
  47. package/build/{uninstall-3gat07zn.js → uninstall-mer1kkr8.js} +1 -1
  48. package/build/{upload-9xb2xw55.js → upload-ge7sr8q4.js} +6 -6
  49. package/build/{utils-dwhbr085.js → utils-8hf3yh4y.js} +11 -7
  50. package/package.json +1 -1
  51. package/build/agent-fsm08k4s.js +0 -19
  52. package/build/authentication-ar6t1hah.js +0 -19
  53. package/build/blackboxAgent-z4ps082z.js +0 -19
  54. package/build/pentest-t3d2bpde.js +0 -29
  55. package/build/threatModel-3rmdn2z4.js +0 -27
@@ -4,19 +4,19 @@ import {
4
4
  buildPentestActiveTools,
5
5
  buildPentestPrompt,
6
6
  buildPentestSystemPrompt
7
- } from "./cli-nz9t18bj.js";
7
+ } from "./cli-8zeepea9.js";
8
8
  import"./cli-9fsre5pt.js";
9
- import"./cli-84zf1xh9.js";
10
- import"./cli-56zyg4kv.js";
11
- import"./cli-6d37md4z.js";
9
+ import"./cli-2jmcpp2j.js";
10
+ import"./cli-gkqya1mj.js";
11
+ import"./cli-5n4q289y.js";
12
12
  import"./cli-c8131c4q.js";
13
- import"./cli-j2xnatde.js";
14
- import"./cli-t3w55a46.js";
13
+ import"./cli-pt68r0a9.js";
14
+ import"./cli-s7fwee5f.js";
15
15
  import"./cli-3k1x5rn3.js";
16
16
  import"./cli-gpnb45ck.js";
17
- import"./cli-0nhhne05.js";
18
- import"./cli-mfsnae61.js";
19
- import"./cli-x3dp6b1d.js";
17
+ import"./cli-729r0ms5.js";
18
+ import"./cli-kxsrmx74.js";
19
+ import"./cli-2sf49904.js";
20
20
  import"./cli-8rxa073f.js";
21
21
  export {
22
22
  buildPentestSystemPrompt,
@@ -0,0 +1,19 @@
1
+ import {
2
+ CodeAgent
3
+ } from "./cli-7k9750yn.js";
4
+ import"./cli-9fsre5pt.js";
5
+ import"./cli-2jmcpp2j.js";
6
+ import"./cli-gkqya1mj.js";
7
+ import"./cli-5n4q289y.js";
8
+ import"./cli-c8131c4q.js";
9
+ import"./cli-pt68r0a9.js";
10
+ import"./cli-s7fwee5f.js";
11
+ import"./cli-3k1x5rn3.js";
12
+ import"./cli-gpnb45ck.js";
13
+ import"./cli-729r0ms5.js";
14
+ import"./cli-kxsrmx74.js";
15
+ import"./cli-2sf49904.js";
16
+ import"./cli-8rxa073f.js";
17
+ export {
18
+ CodeAgent
19
+ };
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  OffensiveSecurityAgent
3
- } from "./cli-56zyg4kv.js";
3
+ } from "./cli-gkqya1mj.js";
4
4
  import {
5
5
  detectOSAndEnhancePrompt
6
- } from "./cli-6d37md4z.js";
6
+ } from "./cli-5n4q289y.js";
7
7
  import"./cli-c8131c4q.js";
8
8
  import {
9
9
  init_dist,
10
10
  stepCountIs
11
- } from "./cli-j2xnatde.js";
12
- import"./cli-t3w55a46.js";
11
+ } from "./cli-pt68r0a9.js";
12
+ import"./cli-s7fwee5f.js";
13
13
  import {
14
14
  exports_external,
15
15
  init_zod
16
16
  } from "./cli-3k1x5rn3.js";
17
17
  import"./cli-gpnb45ck.js";
18
- import"./cli-0nhhne05.js";
19
- import"./cli-mfsnae61.js";
20
- import"./cli-x3dp6b1d.js";
18
+ import"./cli-729r0ms5.js";
19
+ import"./cli-kxsrmx74.js";
20
+ import"./cli-2sf49904.js";
21
21
  import"./cli-8rxa073f.js";
22
22
 
23
23
  // src/core/agents/specialized/findingJudge/agent.ts
@@ -68,7 +68,7 @@ You are the last line of defense against false positives, hallucinated findings,
68
68
  - Authorization / access-control boundary bypass (RSC/prefetch/redirect-body leaks, missing per-route checks): the evidence must establish the access-model delta — which identity/role was used, and proof that the returned data is genuinely out of scope for that identity (cross-tenant, another user's, or admin-only data a member should not see). A 200 response, a leaked RSC payload, or a skipped redirect alone does NOT prove sensitive exposure. If the bypass is real but the returned data is non-sensitive or plausibly same-tenant/expected-visible, classify as a valid lower-impact finding and require the claim's impact/severity to match — do NOT accept it as high-confidence sensitive/cross-tenant exposure.
69
69
  - Authentication bypass: output should show protected access without valid credentials.
70
70
  - Email/HTML injection: ideally verify delivery and rendering. If only server acceptance is shown, confidence must stay below 0.7 and limitations must state rendering was not independently verified.
71
- - Missing rate limiting / anti-automation: fewer than 50 requests is insufficient. Evidence must state exact request count, timing/distribution, and observed statuses.
71
+ - Missing rate limiting / anti-automation: a modest burst (~20 requests) with no observed throttling, delays, or 429s is sufficient to demonstrate the gap. For endpoints with real-world side effects (sending email/SMS/push, creating tickets/notifications, contact/support/feedback forms, payments), as few as 2–3 attempts plus the observed response is sufficient — do NOT require volume-testing that would spam real recipients. Evidence must state exact request count, timing/distribution, and observed statuses.
72
72
 
73
73
  ### Common Low-Signal Patterns
74
74
  Reject these unless the submitted evidence demonstrates concrete harm:
@@ -1,4 +1,14 @@
1
1
  #!/usr/bin/env bun
2
+ import"./cli-af4ntw65.js";
3
+ import"./cli-ks3x11h1.js";
4
+ import"./cli-r5htb0jx.js";
5
+ import"./cli-fd7k577q.js";
6
+ import"./cli-8zeepea9.js";
7
+ import"./cli-r8hsdfaf.js";
8
+ import"./cli-7k9750yn.js";
9
+ import"./cli-8jaz2enb.js";
10
+ import"./cli-9fsre5pt.js";
11
+ import"./cli-2jmcpp2j.js";
2
12
  import {
3
13
  createApp,
4
14
  createEndpoint,
@@ -12,27 +22,17 @@ import {
12
22
  searchEndpoints,
13
23
  updateApp,
14
24
  updateEndpoint
15
- } from "./cli-phg6k6r3.js";
16
- import"./cli-b5fgnn98.js";
17
- import"./cli-5r9kv574.js";
18
- import"./cli-5kw8aevs.js";
19
- import"./cli-nz9t18bj.js";
20
- import"./cli-xtr26a9f.js";
21
- import"./cli-3v63bjde.js";
22
- import"./cli-x8a6x5qp.js";
23
- import"./cli-9fsre5pt.js";
24
- import"./cli-84zf1xh9.js";
25
- import"./cli-56zyg4kv.js";
26
- import"./cli-6d37md4z.js";
25
+ } from "./cli-gkqya1mj.js";
26
+ import"./cli-5n4q289y.js";
27
27
  import"./cli-fw5r7pfj.js";
28
28
  import"./cli-c8131c4q.js";
29
- import"./cli-j2xnatde.js";
30
- import"./cli-t3w55a46.js";
29
+ import"./cli-pt68r0a9.js";
30
+ import"./cli-s7fwee5f.js";
31
31
  import"./cli-3k1x5rn3.js";
32
32
  import"./cli-gpnb45ck.js";
33
- import"./cli-0nhhne05.js";
34
- import"./cli-mfsnae61.js";
35
- import"./cli-x3dp6b1d.js";
33
+ import"./cli-729r0ms5.js";
34
+ import"./cli-kxsrmx74.js";
35
+ import"./cli-2sf49904.js";
36
36
  import"./cli-8rxa073f.js";
37
37
 
38
38
  // src/cli/apps.ts
@@ -1,22 +1,23 @@
1
1
  #!/usr/bin/env bun
2
- import"./cli-phg6k6r3.js";
3
- import"./cli-b5fgnn98.js";
4
- import"./cli-5r9kv574.js";
5
- import"./cli-5kw8aevs.js";
6
- import"./cli-nz9t18bj.js";
7
- import"./cli-xtr26a9f.js";
8
- import"./cli-3v63bjde.js";
9
- import"./cli-x8a6x5qp.js";
2
+ import"./cli-af4ntw65.js";
3
+ import"./cli-ks3x11h1.js";
4
+ import"./cli-r5htb0jx.js";
5
+ import"./cli-fd7k577q.js";
6
+ import"./cli-8zeepea9.js";
7
+ import"./cli-r8hsdfaf.js";
8
+ import"./cli-7k9750yn.js";
9
+ import"./cli-8jaz2enb.js";
10
10
  import"./cli-9fsre5pt.js";
11
- import"./cli-84zf1xh9.js";
12
- import"./cli-56zyg4kv.js";
13
- import"./cli-6d37md4z.js";
11
+ import"./cli-2jmcpp2j.js";
12
+ import"./cli-gkqya1mj.js";
13
+ import"./cli-5n4q289y.js";
14
14
  import"./cli-fw5r7pfj.js";
15
15
  import"./cli-c8131c4q.js";
16
- import"./cli-j2xnatde.js";
16
+ import"./cli-pt68r0a9.js";
17
17
  import {
18
18
  createWorkspaceSelection,
19
19
  disconnect,
20
+ ensureValidToken,
20
21
  fetchWorkspaces,
21
22
  getPensarApiUrl,
22
23
  getPensarConsoleUrl,
@@ -28,15 +29,15 @@ import {
28
29
  pollWorkspaceSelection,
29
30
  selectWorkspace,
30
31
  startDeviceFlow
31
- } from "./cli-t3w55a46.js";
32
+ } from "./cli-s7fwee5f.js";
32
33
  import"./cli-3k1x5rn3.js";
33
34
  import"./cli-gpnb45ck.js";
34
35
  import {
35
36
  config,
36
37
  init_config
37
- } from "./cli-0nhhne05.js";
38
- import"./cli-mfsnae61.js";
39
- import"./cli-x3dp6b1d.js";
38
+ } from "./cli-729r0ms5.js";
39
+ import"./cli-kxsrmx74.js";
40
+ import"./cli-2sf49904.js";
40
41
  import {
41
42
  __require
42
43
  } from "./cli-8rxa073f.js";
@@ -85,7 +86,13 @@ Waiting for workspace selection...`);
85
86
  }
86
87
  async function login() {
87
88
  const appConfig = await config.get();
88
- if (isConnected(appConfig)) {
89
+ const hasStoredCredentials = isConnected(appConfig);
90
+ const validToken = hasStoredCredentials ? await ensureValidToken({
91
+ accessToken: appConfig.accessToken,
92
+ refreshToken: appConfig.refreshToken,
93
+ pensarAPIKey: appConfig.pensarAPIKey
94
+ }) : null;
95
+ if (validToken) {
89
96
  console.log("Already connected to Pensar Console.");
90
97
  if (appConfig.workspaceSlug) {
91
98
  console.log(` Workspace: ${appConfig.workspaceSlug}`);
@@ -95,6 +102,8 @@ Reconnect? (y/N): `);
95
102
  if (answer.toLowerCase() !== "y") {
96
103
  return;
97
104
  }
105
+ } else if (hasStoredCredentials) {
106
+ console.log("Your saved Pensar Console session has expired. Reconnecting.");
98
107
  }
99
108
  console.log(`
100
109
  Pensar Console — Managed Inference
@@ -228,6 +237,15 @@ async function status() {
228
237
  console.log("Not connected to Pensar Console.\n\nRun `pensar login` to connect.");
229
238
  return;
230
239
  }
240
+ const validToken = await ensureValidToken({
241
+ accessToken: appConfig.accessToken,
242
+ refreshToken: appConfig.refreshToken,
243
+ pensarAPIKey: appConfig.pensarAPIKey
244
+ });
245
+ if (!validToken) {
246
+ console.log("Your Pensar Console session has expired.\n\nRun `pensar login` to reconnect.");
247
+ return;
248
+ }
231
249
  if (!appConfig.accessToken && appConfig.pensarAPIKey && !appConfig.workspaceSlug) {
232
250
  try {
233
251
  const apiUrl = getPensarApiUrl();
@@ -0,0 +1,19 @@
1
+ import {
2
+ runAuthenticationAgent
3
+ } from "./cli-r8hsdfaf.js";
4
+ import"./cli-9fsre5pt.js";
5
+ import"./cli-2jmcpp2j.js";
6
+ import"./cli-gkqya1mj.js";
7
+ import"./cli-5n4q289y.js";
8
+ import"./cli-c8131c4q.js";
9
+ import"./cli-pt68r0a9.js";
10
+ import"./cli-s7fwee5f.js";
11
+ import"./cli-3k1x5rn3.js";
12
+ import"./cli-gpnb45ck.js";
13
+ import"./cli-729r0ms5.js";
14
+ import"./cli-kxsrmx74.js";
15
+ import"./cli-2sf49904.js";
16
+ import"./cli-8rxa073f.js";
17
+ export {
18
+ runAuthenticationAgent
19
+ };
@@ -0,0 +1,19 @@
1
+ import {
2
+ BlackboxAttackSurfaceAgent
3
+ } from "./cli-r5htb0jx.js";
4
+ import"./cli-9fsre5pt.js";
5
+ import"./cli-2jmcpp2j.js";
6
+ import"./cli-gkqya1mj.js";
7
+ import"./cli-5n4q289y.js";
8
+ import"./cli-c8131c4q.js";
9
+ import"./cli-pt68r0a9.js";
10
+ import"./cli-s7fwee5f.js";
11
+ import"./cli-3k1x5rn3.js";
12
+ import"./cli-gpnb45ck.js";
13
+ import"./cli-729r0ms5.js";
14
+ import"./cli-kxsrmx74.js";
15
+ import"./cli-2sf49904.js";
16
+ import"./cli-8rxa073f.js";
17
+ export {
18
+ BlackboxAttackSurfaceAgent
19
+ };
@@ -1,24 +1,24 @@
1
1
  import {
2
2
  runPentestWorkflow
3
- } from "./cli-b5fgnn98.js";
4
- import"./cli-5r9kv574.js";
5
- import"./cli-5kw8aevs.js";
6
- import"./cli-nz9t18bj.js";
7
- import"./cli-3v63bjde.js";
8
- import"./cli-x8a6x5qp.js";
3
+ } from "./cli-ks3x11h1.js";
4
+ import"./cli-r5htb0jx.js";
5
+ import"./cli-fd7k577q.js";
6
+ import"./cli-8zeepea9.js";
7
+ import"./cli-7k9750yn.js";
8
+ import"./cli-8jaz2enb.js";
9
9
  import"./cli-9fsre5pt.js";
10
- import"./cli-84zf1xh9.js";
11
- import"./cli-56zyg4kv.js";
12
- import"./cli-6d37md4z.js";
10
+ import"./cli-2jmcpp2j.js";
11
+ import"./cli-gkqya1mj.js";
12
+ import"./cli-5n4q289y.js";
13
13
  import"./cli-fw5r7pfj.js";
14
14
  import"./cli-c8131c4q.js";
15
- import"./cli-j2xnatde.js";
16
- import"./cli-t3w55a46.js";
15
+ import"./cli-pt68r0a9.js";
16
+ import"./cli-s7fwee5f.js";
17
17
  import"./cli-3k1x5rn3.js";
18
18
  import"./cli-gpnb45ck.js";
19
- import"./cli-0nhhne05.js";
20
- import"./cli-mfsnae61.js";
21
- import"./cli-x3dp6b1d.js";
19
+ import"./cli-729r0ms5.js";
20
+ import"./cli-kxsrmx74.js";
21
+ import"./cli-2sf49904.js";
22
22
  import"./cli-8rxa073f.js";
23
23
 
24
24
  // src/core/api/blackboxPentest.ts
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CweEntrySchema,
3
3
  ValidatedCweEntrySchema
4
- } from "./cli-56zyg4kv.js";
4
+ } from "./cli-gkqya1mj.js";
5
5
  import {
6
6
  exports_external,
7
7
  init_zod
@@ -120,7 +120,7 @@ var init_package = __esm(() => {
120
120
  tsc: "tsc --noEmit"
121
121
  },
122
122
  type: "module",
123
- version: "2.3.0-canary.69bfb82f"
123
+ version: "2.3.0-canary.7d0ff84a"
124
124
  };
125
125
  });
126
126
 
@@ -3,7 +3,7 @@ import {
3
3
  init_lazyLogger,
4
4
  init_structured,
5
5
  scopedLogger
6
- } from "./cli-j2xnatde.js";
6
+ } from "./cli-pt68r0a9.js";
7
7
 
8
8
  // src/core/agents/specialized/utils.ts
9
9
  import { execSync } from "node:child_process";
@@ -3,7 +3,7 @@ import {
3
3
  init,
4
4
  init_config,
5
5
  update
6
- } from "./cli-mfsnae61.js";
6
+ } from "./cli-kxsrmx74.js";
7
7
  import {
8
8
  __esm
9
9
  } from "./cli-8rxa073f.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  OffensiveSecurityAgent
3
- } from "./cli-56zyg4kv.js";
3
+ } from "./cli-gkqya1mj.js";
4
4
  import {
5
5
  init_dist,
6
6
  stepCountIs
7
- } from "./cli-j2xnatde.js";
7
+ } from "./cli-pt68r0a9.js";
8
8
 
9
9
  // src/core/agents/specialized/codeAgent/agent.ts
10
10
  init_dist();
@@ -2,11 +2,11 @@ import {
2
2
  EndpointTransportEnum,
3
3
  GrpcEndpointMetadataSchema,
4
4
  OffensiveSecurityAgent
5
- } from "./cli-56zyg4kv.js";
5
+ } from "./cli-gkqya1mj.js";
6
6
  import {
7
7
  hasToolCall,
8
8
  init_dist
9
- } from "./cli-j2xnatde.js";
9
+ } from "./cli-pt68r0a9.js";
10
10
  import {
11
11
  exports_external,
12
12
  init_zod,
@@ -5,7 +5,7 @@ import {
5
5
  createReportErrorTool,
6
6
  isMemoryEnabled,
7
7
  readPlan
8
- } from "./cli-56zyg4kv.js";
8
+ } from "./cli-gkqya1mj.js";
9
9
  import {
10
10
  createLogger,
11
11
  hasToolCall,
@@ -13,7 +13,7 @@ import {
13
13
  init_lazyLogger,
14
14
  init_structured,
15
15
  scopedLogger
16
- } from "./cli-j2xnatde.js";
16
+ } from "./cli-pt68r0a9.js";
17
17
  import {
18
18
  exports_external,
19
19
  init_zod
@@ -161,12 +161,21 @@ var SECTION_RATE_LIMITING = `Rate Limiting:
161
161
  - If you encounter rate limiting (HTTP 429), use exponential backoff before retrying
162
162
  - Use execute_command with "sleep N" where N increases: 5 seconds, then 30 seconds, then 120 seconds
163
163
  - After sleeping, retry the request. If rate limiting persists after 3 attempts, note it in your summary and move on to other objectives`;
164
- var SECTION_RATE_LIMITING_TESTING = `Testing for Rate Limiting Deficiencies:
165
- - When an objective involves testing for missing rate limiting or anti-automation controls, send a MINIMUM of 50 requests in rapid succession before concluding that no rate limiting exists. Fewer than 50 requests is not sufficient — rate limiting mechanisms may use sliding windows, IP quotas, or progressive delays that only trigger at higher volumes.
166
- - In your finding evidence, always state the EXACT number of requests sent, their distribution (e.g. "50 requests to /api/login over 10 seconds, all from a single IP"), and all HTTP status codes observed. Vague claims like "multiple requests" or "rapid requests" are insufficient.
167
- - Frame findings as "Insufficient Anti-Automation Controls" rather than definitively "No Rate Limiting" unless you sent 100+ requests without encountering any throttling, delays, or 429 responses. Even with no rate limiting, a throttled bot can bypass simple rate limits — the absence of CAPTCHA, device fingerprinting, or behavioral analysis is the broader concern.
164
+ var SECTION_RATE_LIMITING_TESTING_ALLOWED = `Testing for Rate Limiting Deficiencies (AUTHORIZED):
165
+ - The client has authorized rate-limit / anti-automation testing for this engagement. When an objective involves missing rate limiting or anti-automation controls, send a modest burst — on the order of 20 requests — in rapid succession, and stop as soon as you observe throttling, delays, or 429s. A handful is not enough to rule out rate limiting (sliding windows, IP quotas, and progressive delays only trigger above a few requests), but there is no need to send dozens or hundreds: ~20 requests without any throttling already demonstrates the gap.
166
+ - In your finding evidence, always state the EXACT number of requests sent, their distribution (e.g. "20 requests to /api/login over 5 seconds, all from a single IP"), and all HTTP status codes observed. Vague claims like "multiple requests" or "rapid requests" are insufficient.
167
+ - Frame findings as "Insufficient Anti-Automation Controls" rather than definitively "No Rate Limiting": even with no rate limiting, a throttled bot can bypass simple rate limits — the absence of CAPTCHA, device fingerprinting, or behavioral analysis is the broader concern.
168
168
  - Always note existing mitigations and their impact on exploitability. For example, if the target has account lockout after 5 failed attempts, this significantly limits credential stuffing even without IP-based rate limiting. Document what protections DO exist, not just what is missing.
169
- - When documenting rate limiting findings, clearly state what was tested (authentication endpoint, API endpoint, password reset, etc.) and how the test was conducted (sequential vs concurrent, single IP vs distributed, single account vs multiple accounts).`;
169
+ - When documenting rate limiting findings, clearly state what was tested (authentication endpoint, API endpoint, password reset, etc.) and how the test was conducted (sequential vs concurrent, single IP vs distributed, single account vs multiple accounts).
170
+ - The real-world side-effect rule below still applies: even when authorized, do not volume-test endpoints that deliver to real people.`;
171
+ var SECTION_RATE_LIMITING_TESTING_BLOCKED = `Rate-Limit / Anti-Automation Testing (OUT OF SCOPE):
172
+ - The client has NOT authorized rate-limit, anti-automation, or volumetric (light-DoS) testing for this engagement. Do NOT send request bursts, floods, or high-volume loops to probe for missing rate limiting, and do NOT script them (curl/loop scripts, concurrent request fans, etc.).
173
+ - If you notice a likely-missing throttle in the course of normal testing, you may note it briefly from what you already observed — but do not generate additional load to prove it, and do not open a dedicated rate-limiting task. Absence of rate limiting is out of scope here.`;
174
+ var SECTION_SIDE_EFFECT_SAFETY = `Real-World Side Effects — Prove Once, Never Loop:
175
+ - Some endpoints cause a real-world side effect every time they succeed: sending email/SMS/push, creating tickets or notifications delivered to real people, submitting "contact"/support/feedback forms to a monitored inbox, or triggering payments. This rule applies REGARDLESS of whether rate-limit or destructive testing is authorized.
176
+ - Prove any finding on such an endpoint with the fewest interactions possible — ideally ONE, and never more than 2-3. A single accepted/delivered submission plus the observed response is sufficient evidence.
177
+ - NEVER loop, burst, fuzz at volume, or repeatedly submit to a live delivery endpoint — not to "confirm" a finding, and not to test anti-automation. Repeating it adds no confidence and spams real recipients.
178
+ - If demonstrating a control gap would require volume against a live-delivery endpoint, describe the gap from the single observation instead of generating the volume.`;
170
179
  var SECTION_POC_PORTABILITY = `POC Script Portability Requirements:
171
180
  - POC scripts MUST be POSIX-compatible to ensure they work across different environments (macOS, Linux, Alpine, BusyBox)
172
181
  - Use grep -E (extended regex) or grep -o. NEVER use grep -P or grep -oP (Perl regex is not portable and will fail on macOS and BusyBox)
@@ -295,12 +304,10 @@ Guidelines:
295
304
  - When you have finished testing ALL objectives, call the response tool with a summary of your results. Do NOT call response until you have completed all testing.
296
305
  - In your response, include objectiveResults for EVERY objective: mark each as completed (true) if you thoroughly tested it and either found and documented a vulnerability OR conclusively determined the endpoint is not vulnerable to that attack. Mark as incomplete (false) if you were unable to fully test it (e.g., rate limited, timed out, need different approach). Also add NEW objectives you discovered during testing that should be tested in future runs (mark these as completed=false).
297
306
  - Do NOT write report files to scratchpad/ (no executive summaries, comprehensive reports, finding compilations, or vulnerability rollups). Reports are generated automatically from findings/. Use the response tool for your final summary.
298
- - Email Injection: For email injection findings, confirm the email was actually delivered and rendered as HTML. If you have email inbox access (email_get_message tool), retrieve the sent email to verify HTML rendering. If inbox access is unavailable, explicitly note in your evidence that rendering was not independently verified.
307
+ - Email Injection: For email injection findings, confirm the email was actually delivered and rendered as HTML. If you have email inbox access (email_get_message tool), retrieve the sent email to verify HTML rendering. If inbox access is unavailable, explicitly note in your evidence that rendering was not independently verified. Send at most one or two test emails to confirm the flaw — a single delivered payload is sufficient proof. Do NOT repeatedly submit to a live "contact"/support/notification endpoint that delivers to a real inbox; one confirmation is enough.
299
308
 
300
309
  ${SECTION_RATE_LIMITING}
301
310
 
302
- ${SECTION_RATE_LIMITING_TESTING}
303
-
304
311
  ${SECTION_DOCUMENT_VULNERABILITY_RULES}
305
312
 
306
313
  ${SECTION_MATERIALITY_GUIDANCE}
@@ -355,8 +362,6 @@ ${SECTION_MATERIALITY_GUIDANCE}
355
362
 
356
363
  ${SECTION_RATE_LIMITING}
357
364
 
358
- ${SECTION_RATE_LIMITING_TESTING}
359
-
360
365
  ${SECTION_CREDENTIAL_DISCOVERY}
361
366
 
362
367
  ${SECTION_SECURITY_HEADERS_CORS}
@@ -391,8 +396,6 @@ ${SECTION_POC_PORTABILITY}
391
396
 
392
397
  ${SECTION_RATE_LIMITING}
393
398
 
394
- ${SECTION_RATE_LIMITING_TESTING}
395
-
396
399
  ${SECTION_BROWSER_INTERACTION}
397
400
 
398
401
  ${SECTION_AUTHENTICATION}
@@ -431,8 +434,6 @@ ${SECTION_POC_PORTABILITY}
431
434
 
432
435
  ${SECTION_RATE_LIMITING}
433
436
 
434
- ${SECTION_RATE_LIMITING_TESTING}
435
-
436
437
  ${SECTION_BROWSER_INTERACTION}
437
438
 
438
439
  ${SECTION_AUTHENTICATION}
@@ -447,22 +448,31 @@ ${SECTION_STATE_CHECKPOINTING}`;
447
448
  function destructiveSection(allow) {
448
449
  return allow ? SECTION_DESTRUCTIVE_ALLOWED : SECTION_DESTRUCTIVE_BLOCKED;
449
450
  }
451
+ function rateLimitTestingSection(allow) {
452
+ return allow ? SECTION_RATE_LIMITING_TESTING_ALLOWED : SECTION_RATE_LIMITING_TESTING_BLOCKED;
453
+ }
450
454
  function buildPentestSystemPrompt(session, role = "orchestrator") {
451
455
  const destructive = destructiveSection(session.config?.allowDestructiveActions);
456
+ const rateLimitTesting = rateLimitTestingSection(session.config?.allowRateLimitTesting);
457
+ const guardrails = `${destructive}
458
+
459
+ ${rateLimitTesting}
460
+
461
+ ${SECTION_SIDE_EFFECT_SAFETY}`;
452
462
  if (role === "orchestrator") {
453
463
  return `${PENTEST_SYSTEM_PROMPT_ORCHESTRATOR}
454
464
 
455
- ${destructive}`;
465
+ ${guardrails}`;
456
466
  }
457
467
  const taskDriven = session.config?.taskDriven ?? false;
458
468
  const exfilMode = session.config?.exfilMode ?? false;
459
469
  const base = taskDriven ? exfilMode ? PENTEST_SYSTEM_PROMPT_TASK_DRIVEN_EXFIL : PENTEST_SYSTEM_PROMPT_TASK_DRIVEN : exfilMode ? PENTEST_SYSTEM_PROMPT_EXFIL : PENTEST_SYSTEM_PROMPT_BASE;
460
- const withDestructive = `${base}
470
+ const withGuardrails = `${base}
461
471
 
462
- ${destructive}`;
463
- return session.config?.promptInjectionLibrarySource ? `${withDestructive}
472
+ ${guardrails}`;
473
+ return session.config?.promptInjectionLibrarySource ? `${withGuardrails}
464
474
 
465
- ${SECTION_PROMPT_INJECTION}` : withDestructive;
475
+ ${SECTION_PROMPT_INJECTION}` : withGuardrails;
466
476
  }
467
477
  var SECTION_ORCHESTRATOR_DELEGATION = `Sub-Agent Delegation Rules:
468
478
  - You DO NOT call document_vulnerability directly. Findings are documented by the workers you spawn.