@pensar/apex 2.6.1 → 2.7.0-canary.1572d9a4
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.
- package/build/{agent-ayreaj6z.js → agent-3g1b578v.js} +6 -5
- package/build/{agent-yby11zaq.js → agent-p8cezgbb.js} +7 -6
- package/build/{agent-runs-g37vkrjr.js → agent-runs-f86emmgg.js} +23 -20
- package/build/agent-vaq31je6.js +14 -0
- package/build/agent-vvdqga09.js +14 -0
- package/build/{apps-xn6km9yn.js → apps-3stwnmen.js} +16 -13
- package/build/{auth-d105wc64.js → auth-7md9kwda.js} +16 -13
- package/build/blackboxAgent-ct8bejef.js +14 -0
- package/build/{blackboxPentest-ps78v3w7.js → blackboxPentest-w2nr4md3.js} +21 -15
- package/build/{cli-c05y640n.js → cli-1j28cbhy.js} +1 -1
- package/build/{cli-d37a42dc.js → cli-2jz2jz06.js} +206 -90
- package/build/{cli-az3xq70v.js → cli-4a8dsz2k.js} +4 -4
- package/build/{cli-qgz1q9g5.js → cli-58781vcf.js} +1192 -1473
- package/build/{cli-gx71jcke.js → cli-7067zzeb.js} +1 -1
- package/build/{cli-3sp6nd8d.js → cli-81smmd5w.js} +5 -5
- package/build/{cli-k2nwxta0.js → cli-8b25dhky.js} +2 -2
- package/build/{cli-fy6vh2a7.js → cli-8sw5zpqz.js} +1 -1
- package/build/{cli-709rvekb.js → cli-cg3ypx5n.js} +14 -7
- package/build/{cli-dpsw2fe6.js → cli-e9v6zg6h.js} +40941 -40172
- package/build/cli-fjxmphg1.js +36 -0
- package/build/{cli-7eea4e2y.js → cli-gzb6qrzh.js} +31 -60
- package/build/{cli-65g6rcat.js → cli-khnf5xrf.js} +2 -1
- package/build/{cli-1ve18npr.js → cli-mdzt2e8j.js} +4 -2
- package/build/{cli-n2en7j5b.js → cli-n8mmw4c4.js} +1 -1
- package/build/cli-pndb7mh9.js +1193 -0
- package/build/cli-px6ehzqx.js +54 -0
- package/build/{cli-xtc2t6me.js → cli-qs4msn6x.js} +111 -47
- package/build/{cli-kb21qhvm.js → cli-rvybdhgn.js} +4 -3
- package/build/{cli-ae8jqxqr.js → cli-v739h7hb.js} +2 -2
- package/build/{cli-ngq9dr8n.js → cli-wm8ech0x.js} +3 -3
- package/build/cli.js +170 -51
- package/build/{config-zpqkd5cz.js → config-e5v1bkh1.js} +1 -1
- package/build/{fastStrike-mcjdvwez.js → fastStrike-efp0rjs3.js} +74 -17
- package/build/{fixes-kytx5dmj.js → fixes-926cw1ej.js} +16 -13
- package/build/{index-n65z6v7b.js → index-3t41p258.js} +7 -6
- package/build/{index-qv4cc65p.js → index-bv09af6g.js} +19 -15
- package/build/{index-je6hcsqr.js → index-bv6dtwse.js} +1 -1
- package/build/{index-4vqdgb42.js → index-jt52ffgn.js} +1657 -1400
- package/build/{index-ns4m4s01.js → index-np405b9e.js} +11 -7
- package/build/{index-r9yjkfrv.js → index-qys178kp.js} +5 -4
- package/build/{index-wqetp6gq.js → index-tpyzq2wq.js} +42 -11
- package/build/{index-fv64eb32.js → index-vrcdyebh.js} +2 -2
- package/build/{index-dr3tg1w3.js → index-z1g8vbtm.js} +1 -1
- package/build/{issues-eb3q9d3a.js → issues-sncyqh14.js} +16 -13
- package/build/{knowledge-fqsvtx0f.js → knowledge-esgvy5ws.js} +16 -13
- package/build/lance-sacfgs1z.js +232 -0
- package/build/lib/{chunk-9yksqgzr.js → chunk-4aevegnc.js} +77 -45
- package/build/lib/{chunk-9tt2021m.js → chunk-4kf4a15q.js} +13 -13
- package/build/lib/{chunk-fy3bbbqy.js → chunk-5avnedwm.js} +7 -1
- package/build/lib/{chunk-bb0ekhkw.js → chunk-5nz5tk3p.js} +76 -22
- package/build/lib/{chunk-4hwzqthr.js → chunk-7s8e5wrd.js} +3 -2
- package/build/lib/{chunk-yrnrbjes.js → chunk-85kpxwzs.js} +4 -2
- package/build/lib/{chunk-mg03jdmt.js → chunk-9jkzk9nc.js} +1 -1
- package/build/lib/{chunk-r4j8ybn9.js → chunk-9wwts6r6.js} +824 -77
- package/build/lib/{chunk-nhfax4gb.js → chunk-bxznzxdy.js} +5 -1
- package/build/lib/{chunk-r2dkp4tb.js → chunk-cqxm95md.js} +1 -1
- package/build/lib/{chunk-w66ce82a.js → chunk-e3agqspc.js} +12 -4
- package/build/lib/{chunk-ba41jh41.js → chunk-eh5yw385.js} +1137 -333
- package/build/lib/{chunk-1azdancq.js → chunk-ewc9r84m.js} +5 -1
- package/build/lib/{chunk-2njv7wz3.js → chunk-hbyxyxdc.js} +4 -0
- package/build/lib/{chunk-e8yy2k73.js → chunk-jhhwts6w.js} +28 -2
- package/build/lib/{chunk-1jvwqnem.js → chunk-kbxbd1kn.js} +108 -44
- package/build/lib/{chunk-7pwa92rn.js → chunk-mph5fvk7.js} +1 -1
- package/build/lib/chunk-psc23epq.js +107 -0
- package/build/lib/{chunk-acgbyf5h.js → chunk-qxad7qjd.js} +4 -2
- package/build/lib/{chunk-3c00n0cy.js → chunk-r0v3vvgm.js} +54 -33
- package/build/lib/{chunk-1yct6cra.js → chunk-rt13120a.js} +1 -1
- package/build/lib/{chunk-v3dk9j7k.js → chunk-sgya016v.js} +93 -22
- package/build/lib/{chunk-1fy8azee.js → chunk-txef92hq.js} +1 -1
- package/build/lib/{chunk-2qsq76xq.js → chunk-vcd90qrn.js} +189 -90
- package/build/lib/{chunk-7gjdygcx.js → chunk-vwr9w3ab.js} +2 -0
- package/build/lib/{chunk-z137x08b.js → chunk-wf6ak0m3.js} +92 -70
- package/build/lib/{chunk-xhdpgpkm.js → chunk-xft0ms9j.js} +2 -2
- package/build/lib/core/agents/agentRuntime.d.ts +3 -1
- package/build/lib/core/agents/defineAgent.d.ts +3 -2
- package/build/lib/core/agents/lance.d.ts +153 -0
- package/build/lib/core/agents/lanceJudge.d.ts +3 -0
- package/build/lib/core/agents/offSecAgent/index.d.ts +3 -1
- package/build/lib/core/agents/offSecAgent/index.js +16 -14
- package/build/lib/core/agents/offSecAgent/offensiveSecurityAgent.d.ts +4 -0
- package/build/lib/core/agents/offSecAgent/prompt.d.ts +3 -1
- package/build/lib/core/agents/offSecAgent/subagentSpawner.d.ts +18 -2
- package/build/lib/core/agents/offSecAgent/subagentSpawner.js +10 -8
- package/build/lib/core/agents/offSecAgent/toolExecutionContext.d.ts +3 -0
- package/build/lib/core/agents/offSecAgent/toolLifecycle.d.ts +1 -0
- package/build/lib/core/agents/offSecAgent/tools/index.js +10 -6
- package/build/lib/core/agents/offSecAgent/tools/listMemories.d.ts +11 -1
- package/build/lib/core/agents/offSecAgent/tools/reportError.d.ts +2 -1
- package/build/lib/core/agents/offSecAgent/tools/runPentestWorkflow.d.ts +20 -1
- package/build/lib/core/agents/offSecAgent/tools/spawnPentestAgent.d.ts +4 -7
- package/build/lib/core/agents/offSecAgent/tools/spawnPentestSwarm.d.ts +7 -1
- package/build/lib/core/agents/offSecAgent/tools/types.d.ts +6 -3
- package/build/lib/core/agents/offSecAgent/tools/whiteboxCandidates.d.ts +2 -2
- package/build/lib/core/agents/offSecAgent/types.d.ts +19 -3
- package/build/lib/core/agents/specialized/attackSurface/blackboxAgent.js +13 -13
- package/build/lib/core/agents/specialized/attackSurface/schemas.js +12 -12
- package/build/lib/core/agents/specialized/authenticationAgent/index.js +14 -14
- package/build/lib/core/agents/specialized/codeAgent/agent.js +13 -13
- package/build/lib/core/agents/specialized/codeAgent/prompts.d.ts +1 -0
- package/build/lib/core/agents/specialized/cvssScorer/index.d.ts +2 -1
- package/build/lib/core/agents/specialized/findingJudge/agent.js +11 -11
- package/build/lib/core/agents/specialized/findingJudge/index.d.ts +2 -1
- package/build/lib/core/agents/specialized/findingJudge/index.js +4 -4
- package/build/lib/core/agents/specialized/patching/index.js +14 -14
- package/build/lib/core/agents/specialized/pentest/agent.d.ts +18 -4
- package/build/lib/core/agents/specialized/pentest/agent.js +15 -13
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.d.ts +2 -1
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/index.js +13 -13
- package/build/lib/core/ai/ai.d.ts +29 -70
- package/build/lib/core/ai/ai.js +5 -3
- package/build/lib/core/ai/index.d.ts +1 -0
- package/build/lib/core/ai/index.js +16 -4
- package/build/lib/core/ai/models/claude-capabilities.d.ts +3 -2
- package/build/lib/core/ai/models/concentrate.d.ts +1 -0
- package/build/lib/core/ai/models/index.d.ts +1 -1
- package/build/lib/core/ai/providers/concentrate.d.ts +1 -0
- package/build/lib/core/ai/reasoning.d.ts +44 -0
- package/build/lib/core/ai/utils.d.ts +2 -0
- package/build/lib/core/ai/utils.js +5 -3
- package/build/lib/core/api/index.d.ts +6 -0
- package/build/lib/core/api/index.js +32 -23
- package/build/lib/core/api/lance.d.ts +6 -0
- package/build/lib/core/api/offesecAgent.d.ts +1 -0
- package/build/lib/core/api/reasoning.d.ts +12 -0
- package/build/lib/core/api/targetedPentest.d.ts +1 -0
- package/build/lib/core/api/targetedPentest.js +14 -14
- package/build/lib/core/cli/reasoning.d.ts +4 -0
- package/build/lib/core/config/config.d.ts +10 -2
- package/build/lib/core/config/customProviders.d.ts +11 -0
- package/build/lib/core/config/index.js +1 -1
- package/build/lib/core/eventBus.js +1 -1
- package/build/lib/core/findings/registry.d.ts +3 -1
- package/build/lib/core/findings/registry.js +4 -4
- package/build/lib/core/observability/index.js +1 -1
- package/build/lib/core/observability/telemetry.d.ts +4 -0
- package/build/lib/core/session/index.d.ts +47 -0
- package/build/lib/core/session/index.js +6 -4
- package/build/lib/core/session/persistence.d.ts +7 -0
- package/build/lib/core/session/persistence.js +8 -4
- package/build/lib/core/tools/backends/index.js +1 -1
- package/build/lib/core/tools/backends/resolve.d.ts +1 -0
- package/build/lib/core/workflows/fastStrike.d.ts +3 -1
- package/build/lib/core/workflows/pentest.d.ts +12 -2
- package/build/lib/core/workflows/pentest.js +19 -19
- package/build/lib/core/workflows/seams.js +5 -5
- package/build/lib/core/workflows/threatModel.d.ts +1 -0
- package/build/lib/core/workflows/whiteboxAttackSurface.d.ts +6 -4
- package/build/lib/core/workflows/whiteboxAttackSurface.js +15 -15
- package/build/lib/index.js +25 -25
- package/build/{logs-x62b7hk1.js → logs-bcbjpjp6.js} +16 -13
- package/build/{native-rollout-evidence-c9yhfqcs.js → native-rollout-evidence-rph1774m.js} +5 -5
- package/build/offesecAgent-81h1p6ee.js +32 -0
- package/build/pentest-2q20q6n1.js +23 -0
- package/build/{pentests-e0f32aqx.js → pentests-jgw031mc.js} +16 -13
- package/build/recordedRunClient-6axj6fba.js +11 -0
- package/build/subagentSpawner-a861gvt0.js +12 -0
- package/build/targetedPentest-6yxznt7s.js +91 -0
- package/build/{targets-xj9g3q0z.js → targets-bjah19dp.js} +16 -13
- package/build/threatModel-739kpexm.js +24 -0
- package/build/{uninstall-7s784q4a.js → uninstall-yxrn9edt.js} +1 -1
- package/build/{upload-4gvhwmvr.js → upload-34ewrjp5.js} +4 -4
- package/build/{utils-cjrz64pc.js → utils-fzm66efw.js} +5 -5
- package/package.json +2 -1
- package/src/cli/issues.test.ts +17 -1
- package/src/cli/lance-verifier.test.ts +57 -0
- package/src/cli/lance-verifier.ts +73 -0
- package/src/cli/lance.test.ts +71 -0
- package/src/cli/lance.ts +48 -0
- package/src/cli.ts +109 -19
- package/src/core/agents/agentRuntime.test.ts +42 -0
- package/src/core/agents/agentRuntime.ts +7 -2
- package/src/core/agents/defineAgent.ts +3 -1
- package/src/core/agents/lance.test.ts +421 -0
- package/src/core/agents/lance.ts +701 -0
- package/src/core/agents/lanceJudge.test.ts +166 -0
- package/src/core/agents/lanceJudge.ts +115 -0
- package/src/core/agents/offSecAgent/index.ts +3 -0
- package/src/core/agents/offSecAgent/interruptedStepFinalization.test.ts +51 -0
- package/src/core/agents/offSecAgent/lance.test.ts +188 -0
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.test.ts +92 -5
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.ts +244 -41
- package/src/core/agents/offSecAgent/prompt.test.ts +46 -0
- package/src/core/agents/offSecAgent/prompt.ts +52 -8
- package/src/core/agents/offSecAgent/selectiveConstruction.publicPath.test.ts +38 -0
- package/src/core/agents/offSecAgent/selectiveConstruction.test.ts +64 -0
- package/src/core/agents/offSecAgent/subagentSpawner.hooks.test.ts +11 -3
- package/src/core/agents/offSecAgent/subagentSpawner.reasoning.test.ts +167 -0
- package/src/core/agents/offSecAgent/subagentSpawner.ts +82 -28
- package/src/core/agents/offSecAgent/toolExecutionContext.test.ts +230 -0
- package/src/core/agents/offSecAgent/toolExecutionContext.ts +56 -0
- package/src/core/agents/offSecAgent/toolLifecycle.ts +2 -0
- package/src/core/agents/offSecAgent/tools/delegateAuth.ts +4 -2
- package/src/core/agents/offSecAgent/tools/documentFinding.test.ts +9 -4
- package/src/core/agents/offSecAgent/tools/documentFinding.ts +10 -9
- package/src/core/agents/offSecAgent/tools/listMemories.test.ts +230 -0
- package/src/core/agents/offSecAgent/tools/listMemories.ts +73 -6
- package/src/core/agents/offSecAgent/tools/reportError.test.ts +6 -0
- package/src/core/agents/offSecAgent/tools/reportError.ts +10 -2
- package/src/core/agents/offSecAgent/tools/runAttackSurface.ts +7 -4
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.test.ts +57 -0
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.ts +21 -1
- package/src/core/agents/offSecAgent/tools/runWhiteboxScan.ts +5 -2
- package/src/core/agents/offSecAgent/tools/spawnCodingAgent.ts +50 -67
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.test.ts +79 -3
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.ts +36 -16
- package/src/core/agents/offSecAgent/tools/spawnPentestSwarm.ts +28 -5
- package/src/core/agents/offSecAgent/tools/threatModelGenerator.ts +4 -3
- package/src/core/agents/offSecAgent/tools/types.ts +12 -2
- package/src/core/agents/offSecAgent/tools/updateTask.ts +5 -1
- package/src/core/agents/offSecAgent/tools/whiteboxCandidates.ts +11 -4
- package/src/core/agents/offSecAgent/types.ts +22 -1
- package/src/core/agents/specialized/codeAgent/agent.test.ts +7 -0
- package/src/core/agents/specialized/codeAgent/agent.ts +9 -2
- package/src/core/agents/specialized/codeAgent/prompts.ts +6 -0
- package/src/core/agents/specialized/cvssScorer/index.test.ts +2 -1
- package/src/core/agents/specialized/cvssScorer/index.ts +3 -0
- package/src/core/agents/specialized/findingJudge/index.ts +6 -0
- package/src/core/agents/specialized/pentest/agent.test.ts +155 -0
- package/src/core/agents/specialized/pentest/agent.ts +181 -52
- package/src/core/agents/specialized/pentest/results.test.ts +59 -4
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.concurrency.test.ts +59 -2
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.hooks.test.ts +127 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.ts +74 -68
- package/src/core/ai/ai.durability-hooks.test.ts +25 -7
- package/src/core/ai/ai.lance.test.ts +581 -0
- package/src/core/ai/ai.operator-context.bench.test.ts +1390 -0
- package/src/core/ai/ai.recorded-context.test.ts +89 -8
- package/src/core/ai/ai.test.ts +81 -59
- package/src/core/ai/ai.ts +453 -327
- package/src/core/ai/compactionTelemetry.test.ts +69 -17
- package/src/core/ai/index.ts +11 -0
- package/src/core/ai/models/anthropic.ts +6 -0
- package/src/core/ai/models/bedrock.ts +18 -0
- package/src/core/ai/models/claude-capabilities.ts +29 -8
- package/src/core/ai/models/concentrate.ts +52 -0
- package/src/core/ai/models/index.ts +25 -4
- package/src/core/ai/models/models.test.ts +179 -7
- package/src/core/ai/models/openrouter-reasoning.json +219 -0
- package/src/core/ai/models/openrouter.ts +43 -1
- package/src/core/ai/providers/anthropic-models.test.ts +60 -1
- package/src/core/ai/providers/bedrock-models.test.ts +81 -0
- package/src/core/ai/providers/concentrate.test.ts +31 -0
- package/src/core/ai/providers/concentrate.ts +11 -0
- package/src/core/ai/providers/custom.test.ts +74 -0
- package/src/core/ai/providers/custom.ts +3 -1
- package/src/core/ai/providers/gateway-models.test.ts +16 -6
- package/src/core/ai/providers/pensarFormatters.ts +8 -1
- package/src/core/ai/reasoning.test.ts +313 -0
- package/src/core/ai/reasoning.ts +500 -0
- package/src/core/ai/streamIdleTimeout.test.ts +21 -0
- package/src/core/ai/utils.native-rollout-evidence.test.ts +21 -8
- package/src/core/ai/utils.ts +269 -163
- package/src/core/api/attackSurface.ts +1 -0
- package/src/core/api/blackboxPentest.ts +9 -1
- package/src/core/api/index.ts +17 -0
- package/src/core/api/lance.ts +23 -0
- package/src/core/api/offesecAgent.test.ts +51 -0
- package/src/core/api/offesecAgent.ts +15 -1
- package/src/core/api/reasoning.test.ts +213 -0
- package/src/core/api/reasoning.ts +44 -0
- package/src/core/api/recordedRun.loop.test.ts +5 -1
- package/src/core/api/targetedPentest.test.ts +14 -2
- package/src/core/api/targetedPentest.ts +52 -5
- package/src/core/cli/reasoning.test.ts +149 -0
- package/src/core/cli/reasoning.ts +95 -0
- package/src/core/config/config.test.ts +35 -0
- package/src/core/config/config.ts +11 -0
- package/src/core/config/customProviders.ts +21 -2
- package/src/core/eventBus.ts +1 -0
- package/src/core/findings/registry.test.ts +9 -1
- package/src/core/findings/registry.ts +6 -0
- package/src/core/observability/telemetry.test.ts +131 -79
- package/src/core/observability/telemetry.ts +5 -0
- package/src/core/runtime/sqliteRunObservation.test.ts +1 -1
- package/src/core/session/index.ts +38 -0
- package/src/core/session/persistence.test.ts +62 -0
- package/src/core/session/persistence.ts +56 -0
- package/src/core/tools/backends/resolve.ts +7 -0
- package/src/core/tools/backends/whiteboxJobs.test.ts +9 -8
- package/src/core/workflows/fastStrike.seams.test.ts +149 -0
- package/src/core/workflows/fastStrike.test.ts +18 -1
- package/src/core/workflows/fastStrike.ts +106 -11
- package/src/core/workflows/pentest.test.ts +104 -0
- package/src/core/workflows/pentest.ts +128 -7
- package/src/core/workflows/seams.test.ts +13 -0
- package/src/core/workflows/seams.ts +5 -1
- package/src/core/workflows/threatModel.ts +2 -0
- package/src/core/workflows/whiteboxAttackSurface.test.ts +74 -2
- package/src/core/workflows/whiteboxAttackSurface.ts +102 -73
- package/src/tui/command-registry.test.ts +12 -0
- package/src/tui/command-registry.ts +10 -0
- package/src/tui/components/chat/config-view.tsx +6 -10
- package/src/tui/components/chat/home-view.tsx +2 -2
- package/src/tui/components/chat/input-area.tsx +2 -2
- package/src/tui/components/chat/loading-indicator.tsx +20 -4
- package/src/tui/components/chat/message-list.tsx +1 -0
- package/src/tui/components/commands/__tests__/advanced-settings-lifecycle.tsx +164 -0
- package/src/tui/components/commands/advanced-settings.test.ts +34 -0
- package/src/tui/components/commands/advanced-settings.tsx +220 -31
- package/src/tui/components/commands/models-display.tsx +7 -1
- package/src/tui/components/model-picker/ModelPicker.tsx +65 -103
- package/src/tui/components/model-picker/ModelPickerDialog.tsx +8 -14
- package/src/tui/components/model-picker/__tests__/reasoning-control.tsx +162 -0
- package/src/tui/components/model-picker/reasoning-control.test.ts +15 -0
- package/src/tui/components/operator-dashboard/index.tsx +166 -50
- package/src/tui/components/operator-dashboard/logic.test.ts +144 -2
- package/src/tui/components/operator-dashboard/logic.ts +54 -3
- package/src/tui/components/operator-dashboard/run-events.test.ts +3 -1
- package/src/tui/components/shared/__tests__/tool-renderer-lifecycle.tsx +18 -0
- package/src/tui/components/shared/action-label.test.ts +9 -0
- package/src/tui/components/shared/compacting-icon.tsx +18 -0
- package/src/tui/components/shared/index.ts +1 -0
- package/src/tui/components/shared/tool-registry.ts +1 -0
- package/src/tui/components/shared/tool-renderer.tsx +21 -7
- package/src/tui/context/agent.tsx +32 -79
- package/src/tui/context/route.tsx +2 -0
- package/src/tui/index.tsx +1 -0
- package/src/tui/keybindings/registry.ts +2 -0
- package/build/agent-6w7egcf1.js +0 -13
- package/build/agent-9zx75feh.js +0 -13
- package/build/blackboxAgent-s56sgx9b.js +0 -13
- package/build/cli-g06s7edq.js +0 -11
- package/build/lib/chunk-z96pbjhd.js +0 -56
- package/build/offesecAgent-5whnpeta.js +0 -22
- package/build/pentest-e61hc38s.js +0 -22
- package/build/recordedRunClient-dp032c32.js +0 -11
- package/build/targetedPentest-rcbs4nvp.js +0 -57
- package/build/threatModel-jkxfa40s.js +0 -21
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import type { FindingPolicy } from "../agents/offSecAgent";
|
|
4
5
|
import { OffensiveSecurityAgent } from "../agents/offSecAgent";
|
|
5
6
|
import { FindingsRegistry } from "../findings/registry";
|
|
6
7
|
import {
|
|
@@ -32,9 +33,44 @@ const FastStrikeResult = z.object({
|
|
|
32
33
|
),
|
|
33
34
|
});
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
const FastStrikeExternalResult = z.object({
|
|
37
|
+
solved: z.boolean().describe("True if the supplied objective was met."),
|
|
38
|
+
summary: z
|
|
39
|
+
.string()
|
|
40
|
+
.describe(
|
|
41
|
+
"Concise account of security findings and the evidence observed, including any flag or sensitive data extracted for an exfiltration objective.",
|
|
42
|
+
),
|
|
43
|
+
reportedFindings: z
|
|
44
|
+
.array(z.string())
|
|
45
|
+
.describe(
|
|
46
|
+
"One concise evidence-backed description per discovered vulnerability.",
|
|
47
|
+
),
|
|
48
|
+
submissionJson: z
|
|
49
|
+
.string()
|
|
50
|
+
.describe(
|
|
51
|
+
"The exact task-defined JSON submission as a string, or an empty string when no JSON submission was requested. Do not invent fields.",
|
|
52
|
+
),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
type FastStrikeOutcome =
|
|
56
|
+
| z.infer<typeof FastStrikeResult>
|
|
57
|
+
| z.infer<typeof FastStrikeExternalResult>;
|
|
36
58
|
|
|
37
|
-
export
|
|
59
|
+
export function buildFastStrikeSystemPrompt(
|
|
60
|
+
findingPolicy: FindingPolicy = "native",
|
|
61
|
+
): string {
|
|
62
|
+
const external = findingPolicy === "external";
|
|
63
|
+
const objectiveStep = external
|
|
64
|
+
? "5. FOLLOW THE OBJECTIVE — Determine whether the observed behavior establishes a security weakness. For a detection-only objective, stop once the requested evidence is sufficient; develop an exploit or pivot only when the objective requires it."
|
|
65
|
+
: "5. EXPLOIT — When a vulnerability is confirmed, exploit it: capture the flag, extract the sensitive data, and pivot through it if the objective requires more. Preserve viable primitives and build on them. Prefer extending a working script into an end-to-end exploit over rebuilding the chain with repeated one-off tool calls or stopping at the next network or protocol boundary.";
|
|
66
|
+
const finishStep = external
|
|
67
|
+
? "6. REPORT & FINISH — Include each credible finding and its supporting observations in the caller's requested output. If the caller requested a JSON submission, include the exact JSON text in the response tool's submissionJson field as well; otherwise use an empty string. The caller evaluates findings after the run. Once the objective is met or credible leads are exhausted, call the response tool with the correct solved value and a concise summary."
|
|
68
|
+
: "6. DOCUMENT & FINISH — Record each confirmed vulnerability with the document_vulnerability tool as you go. Before concluding that every credible lead is exhausted, account for each viable primitive and pursue any concrete path that could still close the objective. After this check, whether the objective was met or every credible lead was genuinely exhausted, call the response tool with the correct solved value and a concise summary.";
|
|
69
|
+
const evidenceRule = external
|
|
70
|
+
? "- Bias toward the shortest path that satisfies the assigned objective. Distinguish observed evidence from hypotheses, and avoid separate in-run finding review."
|
|
71
|
+
: "- Bias toward the shortest path that proves impact. Speed comes from picking the right lead, not from skipping verification — always confirm a finding before you claim it.";
|
|
72
|
+
|
|
73
|
+
return `You are an elite offensive security operator running a fast strike against a single target. You work ALONE and finish the job yourself — there is no team to hand off to, no swarm to spawn, no plan to file. Your edge is discipline and observation, not volume.
|
|
38
74
|
|
|
39
75
|
Run this loop, tightly:
|
|
40
76
|
|
|
@@ -42,15 +78,18 @@ Run this loop, tightly:
|
|
|
42
78
|
2. HYPOTHESIZE — From that signal and your deep knowledge of web/app vulnerability classes, name the single most likely vulnerability and why the evidence points to it. Rank leads by signal strength and go for the strongest first. A disabled form field, an ID in a URL or JWT, advertised demo creds, an exposed schema — these are tells; read them.
|
|
43
79
|
3. ACT — Test that one hypothesis with the strongest available technique. Use direct tools for quick probes, but treat the shell as a working environment rather than merely a way to issue one-off commands. When the work becomes stateful, repetitive, concurrent, protocol-heavy, or multi-stage, externalize it into an editable script in the session scratchpad directory identified in the workspace instructions. Never create a scratchpad/ directory inside the target repository. Run the script, inspect the results, modify it, and rerun it as the attack develops. For blind/out-of-band testing (SSRF, blind RCE, XSS callbacks), start_callback_listener gives you a nonce-correlated listener that survives intervening commands: embed the returned callback URL (only an address you know the target can reach — never a guessed one) in the payload, then poll_callback_listener for hits. Listener readiness and the tool's own self-test never count as target evidence; stop_callback_listener when done.
|
|
44
80
|
4. PRUNE — If the evidence disproves a lead, drop it and move to the next-strongest. Do NOT re-run a disproven approach or grind a dead end. Do NOT enumerate, brute-force, or run wordlists unless a specific signal demands it — choose techniques from evidence, not from a checklist.
|
|
45
|
-
|
|
46
|
-
|
|
81
|
+
${objectiveStep}
|
|
82
|
+
${finishStep}
|
|
47
83
|
|
|
48
84
|
Rules:
|
|
49
85
|
- You are one operator. Plan in your head and in short text notes — never via planning tools, task lists, or sub-agents.
|
|
50
86
|
- Recon and exploitation are the same loop. Do just enough recon to form the first hypothesis, then start testing. Do not map the entire surface before acting.
|
|
51
87
|
- Spend your reasoning on choosing techniques and interpreting evidence; use scripts for deterministic mechanics, iteration, and chain execution.
|
|
52
|
-
|
|
88
|
+
${evidenceRule}
|
|
53
89
|
- Stay in scope. Only touch the target you were given and hosts it legitimately depends on.`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const FAST_STRIKE_SYSTEM_PROMPT = buildFastStrikeSystemPrompt();
|
|
54
93
|
|
|
55
94
|
/** Single-operator pentest: skips attack-surface/swarm, returns {@link PentestWorkflowResult}. */
|
|
56
95
|
export async function runFastStrike(
|
|
@@ -67,7 +106,9 @@ export async function runFastStrike(
|
|
|
67
106
|
onStepFinish,
|
|
68
107
|
onCacheMetrics,
|
|
69
108
|
enableThinking,
|
|
109
|
+
thinkingEffort,
|
|
70
110
|
openAIReasoningEffort,
|
|
111
|
+
reasoning,
|
|
71
112
|
prompt,
|
|
72
113
|
threatModel,
|
|
73
114
|
seams: inputSeams,
|
|
@@ -82,6 +123,7 @@ export async function runFastStrike(
|
|
|
82
123
|
findings: () =>
|
|
83
124
|
FindingsRegistry.fromDirectory(session.findingsPath, {
|
|
84
125
|
model,
|
|
126
|
+
reasoning,
|
|
85
127
|
authConfig,
|
|
86
128
|
abortSignal,
|
|
87
129
|
sessionId: session.id,
|
|
@@ -116,6 +158,7 @@ export async function runFastStrike(
|
|
|
116
158
|
}
|
|
117
159
|
|
|
118
160
|
const operatorGuidance = session.config?.prompt;
|
|
161
|
+
const findingPolicy = input.hooks?.findingPolicy ?? input.findingPolicy;
|
|
119
162
|
|
|
120
163
|
const mode: "blackbox" | "whitebox" = cwd ? "whitebox" : "blackbox";
|
|
121
164
|
|
|
@@ -136,8 +179,15 @@ export async function runFastStrike(
|
|
|
136
179
|
const promptParts: string[] = [`Target: ${target}`];
|
|
137
180
|
if (operatorGuidance) promptParts.push(operatorGuidance);
|
|
138
181
|
promptParts.push(
|
|
139
|
-
|
|
182
|
+
findingPolicy === "external"
|
|
183
|
+
? "Run the fast strike: investigate the target, identify security weaknesses, and submit the findings in the requested output. Stop when the supplied objective is met."
|
|
184
|
+
: "Run the fast strike: find and exploit the vulnerability, complete the objective, and report what worked.",
|
|
140
185
|
);
|
|
186
|
+
if (findingPolicy === "external" && session.config?.exfilMode) {
|
|
187
|
+
promptParts.push(
|
|
188
|
+
"Exfiltration goal: locate and extract FLAG{...} or the assigned sensitive data through a confirmed weakness. Do not stop at discovery; include the extraction result in the final summary.",
|
|
189
|
+
);
|
|
190
|
+
}
|
|
141
191
|
|
|
142
192
|
const agent = new OffensiveSecurityAgent<FastStrikeOutcome>({
|
|
143
193
|
subagentSpawner: input.subagentSpawner,
|
|
@@ -145,14 +195,18 @@ export async function runFastStrike(
|
|
|
145
195
|
usageRecorder: input.usageRecorder,
|
|
146
196
|
streamIdFactory: input.streamIdFactory,
|
|
147
197
|
...input.hooks,
|
|
148
|
-
system:
|
|
198
|
+
system: buildFastStrikeSystemPrompt(findingPolicy),
|
|
149
199
|
prompt: promptParts.join("\n\n"),
|
|
150
200
|
model,
|
|
151
201
|
session,
|
|
152
202
|
target,
|
|
153
203
|
mode: "fast-strike",
|
|
204
|
+
findingPolicy,
|
|
154
205
|
activeTools: [],
|
|
155
|
-
responseSchema:
|
|
206
|
+
responseSchema:
|
|
207
|
+
findingPolicy === "external"
|
|
208
|
+
? FastStrikeExternalResult
|
|
209
|
+
: FastStrikeResult,
|
|
156
210
|
findingsRegistry,
|
|
157
211
|
subagentId: "fast-strike",
|
|
158
212
|
authConfig,
|
|
@@ -164,7 +218,9 @@ export async function runFastStrike(
|
|
|
164
218
|
onStepFinish,
|
|
165
219
|
onCacheMetrics,
|
|
166
220
|
enableThinking,
|
|
221
|
+
thinkingEffort,
|
|
167
222
|
openAIReasoningEffort,
|
|
223
|
+
reasoning,
|
|
168
224
|
});
|
|
169
225
|
|
|
170
226
|
eventBus?.emit("subagent-spawn", {
|
|
@@ -179,16 +235,32 @@ export async function runFastStrike(
|
|
|
179
235
|
target,
|
|
180
236
|
});
|
|
181
237
|
|
|
182
|
-
let
|
|
238
|
+
let completed:
|
|
239
|
+
| { policy: "native"; outcome: FastStrikeOutcome }
|
|
240
|
+
| {
|
|
241
|
+
policy: "external";
|
|
242
|
+
outcome: z.infer<typeof FastStrikeExternalResult>;
|
|
243
|
+
};
|
|
183
244
|
try {
|
|
184
|
-
strikeResult = await agent.consume();
|
|
245
|
+
const strikeResult = await agent.consume();
|
|
246
|
+
if (findingPolicy === "external") {
|
|
247
|
+
const parsed = FastStrikeExternalResult.safeParse(strikeResult);
|
|
248
|
+
if (!parsed.success) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
"Externally graded Fast Strike ended without a structured findings response",
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
completed = { policy: "external", outcome: parsed.data };
|
|
254
|
+
} else {
|
|
255
|
+
completed = { policy: "native", outcome: strikeResult };
|
|
256
|
+
}
|
|
185
257
|
eventBus?.emit("subagent-complete", {
|
|
186
258
|
subagentId: "fast-strike",
|
|
187
259
|
status: "completed",
|
|
188
260
|
});
|
|
189
261
|
await seams.hooks.onEndpointDone?.(
|
|
190
262
|
{ subagentId: "fast-strike", subagentName: "Fast Strike", target },
|
|
191
|
-
|
|
263
|
+
completed.outcome,
|
|
192
264
|
);
|
|
193
265
|
} catch (e) {
|
|
194
266
|
eventBus?.emit("subagent-complete", {
|
|
@@ -206,8 +278,31 @@ export async function runFastStrike(
|
|
|
206
278
|
throw new DOMException("Pentest aborted by user", "AbortError");
|
|
207
279
|
}
|
|
208
280
|
|
|
281
|
+
if (completed.policy === "external") {
|
|
282
|
+
const strikeResult = completed.outcome;
|
|
283
|
+
eventBus?.emit("workflow-phase-complete", {
|
|
284
|
+
phase: "pentesting",
|
|
285
|
+
summary: {
|
|
286
|
+
findingsCount: strikeResult.reportedFindings.length,
|
|
287
|
+
solved: strikeResult.solved,
|
|
288
|
+
operatorSummary: strikeResult.summary,
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
return {
|
|
292
|
+
findings: [],
|
|
293
|
+
findingsPath: session.findingsPath,
|
|
294
|
+
pocsPath: session.pocsPath,
|
|
295
|
+
reportPath: null,
|
|
296
|
+
reportedFindings: strikeResult.reportedFindings,
|
|
297
|
+
submissionJson: strikeResult.submissionJson,
|
|
298
|
+
solved: strikeResult.solved,
|
|
299
|
+
summary: strikeResult.summary,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
209
303
|
await findingsRegistry.groupByRootCause();
|
|
210
304
|
const findings = [...findingsRegistry.getFindings()];
|
|
305
|
+
const strikeResult = completed.outcome;
|
|
211
306
|
|
|
212
307
|
const report = buildPentestReport(findings, {
|
|
213
308
|
target,
|
|
@@ -573,3 +573,107 @@ describe("runPentestWorkflow — threads seams into the whitebox discovery phase
|
|
|
573
573
|
expect(mocks.whiteboxCalls[0]?.seams).toBe(seams);
|
|
574
574
|
});
|
|
575
575
|
});
|
|
576
|
+
|
|
577
|
+
describe("external pentest workflow", () => {
|
|
578
|
+
it("returns worker findings without native report generation and retains them on resume", async () => {
|
|
579
|
+
const emit = vi.fn();
|
|
580
|
+
mocks.consumeImpl = async () => ({
|
|
581
|
+
findings: [],
|
|
582
|
+
reportedFindings: ["GET /api reveals another tenant's data"],
|
|
583
|
+
objectiveResults: [
|
|
584
|
+
{
|
|
585
|
+
objective: "Test the target",
|
|
586
|
+
completed: true,
|
|
587
|
+
result: "Extracted FLAG{example} through the confirmed weakness",
|
|
588
|
+
},
|
|
589
|
+
],
|
|
590
|
+
findingsPath: session.findingsPath,
|
|
591
|
+
pocsPath: session.pocsPath,
|
|
592
|
+
});
|
|
593
|
+
const input: PentestWorkflowInput = {
|
|
594
|
+
target: "https://example.com",
|
|
595
|
+
model: {} as PentestWorkflowInput["model"],
|
|
596
|
+
session,
|
|
597
|
+
findingPolicy: "external",
|
|
598
|
+
eventBus: { emit } as unknown as NonNullable<
|
|
599
|
+
PentestWorkflowInput["eventBus"]
|
|
600
|
+
>,
|
|
601
|
+
hooks: { findingPolicy: undefined },
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
const first = await runPentestWorkflow(input);
|
|
605
|
+
expect(first).toMatchObject({
|
|
606
|
+
findings: [],
|
|
607
|
+
reportedFindings: ["GET /api reveals another tenant's data"],
|
|
608
|
+
objectiveResults: [
|
|
609
|
+
{
|
|
610
|
+
objective: "Test the target",
|
|
611
|
+
completed: true,
|
|
612
|
+
result: "Extracted FLAG{example} through the confirmed weakness",
|
|
613
|
+
},
|
|
614
|
+
],
|
|
615
|
+
reportPath: null,
|
|
616
|
+
});
|
|
617
|
+
expect(mocks.targetedInputs).toHaveLength(1);
|
|
618
|
+
expect(mocks.targetedInputs[0]?.findingPolicy).toBe("external");
|
|
619
|
+
expect(emit).toHaveBeenCalledWith("workflow-phase-complete", {
|
|
620
|
+
phase: "pentesting",
|
|
621
|
+
summary: { findingsCount: 1 },
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
mocks.consumeImpl = async () => {
|
|
625
|
+
throw new Error("completed worker was rerun");
|
|
626
|
+
};
|
|
627
|
+
const resumed = await runPentestWorkflow(input);
|
|
628
|
+
expect(resumed.reportedFindings).toEqual(first.reportedFindings);
|
|
629
|
+
expect(resumed.objectiveResults).toEqual(first.objectiveResults);
|
|
630
|
+
expect(mocks.targetedInputs).toHaveLength(1);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
it("does not generate a native report when discovery has no targets", async () => {
|
|
634
|
+
mocks.loadAttackSurfaceResults.mockReturnValue({ targets: [] });
|
|
635
|
+
const result = await runPentestWorkflow({
|
|
636
|
+
target: "https://example.com",
|
|
637
|
+
model: {} as PentestWorkflowInput["model"],
|
|
638
|
+
session,
|
|
639
|
+
findingPolicy: "external",
|
|
640
|
+
});
|
|
641
|
+
expect(result).toMatchObject({
|
|
642
|
+
findings: [],
|
|
643
|
+
reportedFindings: [],
|
|
644
|
+
objectiveResults: [],
|
|
645
|
+
reportPath: null,
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
it("rejects an external worker result without objective outcomes", async () => {
|
|
650
|
+
mocks.consumeImpl = async () => ({
|
|
651
|
+
findings: [],
|
|
652
|
+
reportedFindings: ["A finding"],
|
|
653
|
+
findingsPath: session.findingsPath,
|
|
654
|
+
pocsPath: session.pocsPath,
|
|
655
|
+
});
|
|
656
|
+
await expect(
|
|
657
|
+
runPentestWorkflow({
|
|
658
|
+
target: "https://example.com",
|
|
659
|
+
model: {} as PentestWorkflowInput["model"],
|
|
660
|
+
session,
|
|
661
|
+
findingPolicy: "external",
|
|
662
|
+
}),
|
|
663
|
+
).rejects.toThrow("incomplete swarm target");
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it("fails rather than treating an incomplete external worker as no finding", async () => {
|
|
667
|
+
mocks.consumeImpl = async () => {
|
|
668
|
+
throw new Error("worker failed");
|
|
669
|
+
};
|
|
670
|
+
await expect(
|
|
671
|
+
runPentestWorkflow({
|
|
672
|
+
target: "https://example.com",
|
|
673
|
+
model: {} as PentestWorkflowInput["model"],
|
|
674
|
+
session,
|
|
675
|
+
findingPolicy: "external",
|
|
676
|
+
}),
|
|
677
|
+
).rejects.toThrow("incomplete swarm target");
|
|
678
|
+
});
|
|
679
|
+
});
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
ToolSet,
|
|
8
8
|
} from "ai";
|
|
9
9
|
import { hasToolCall } from "ai";
|
|
10
|
-
import type { AgentHooks, Finding } from "../agents/offSecAgent";
|
|
10
|
+
import type { AgentHooks, Finding, FindingPolicy } from "../agents/offSecAgent";
|
|
11
11
|
import {
|
|
12
12
|
OffensiveSecurityAgent,
|
|
13
13
|
PLAN_MODE_TOOL_NAMES,
|
|
@@ -39,6 +39,7 @@ import type {
|
|
|
39
39
|
AIModel,
|
|
40
40
|
CacheMetrics,
|
|
41
41
|
OpenAIReasoningEffort,
|
|
42
|
+
ReasoningSetting,
|
|
42
43
|
ThinkingEffort,
|
|
43
44
|
UsageRecorder,
|
|
44
45
|
} from "../ai";
|
|
@@ -64,6 +65,8 @@ import {
|
|
|
64
65
|
finalizeManifest,
|
|
65
66
|
getCompletedAgentIds,
|
|
66
67
|
loadSubagentMessages,
|
|
68
|
+
loadSubagentObjectiveResults,
|
|
69
|
+
loadSubagentReportedFindings,
|
|
67
70
|
readAgentManifest,
|
|
68
71
|
reconcileManifestOnResume,
|
|
69
72
|
type SwarmTarget,
|
|
@@ -99,6 +102,7 @@ export const DEFAULT_CONCURRENCY = 10;
|
|
|
99
102
|
// ---------------------------------------------------------------------------
|
|
100
103
|
|
|
101
104
|
export interface PentestWorkflowInput {
|
|
105
|
+
findingPolicy?: FindingPolicy;
|
|
102
106
|
/** Live target URL — always required */
|
|
103
107
|
target: string;
|
|
104
108
|
|
|
@@ -125,6 +129,7 @@ export interface PentestWorkflowInput {
|
|
|
125
129
|
|
|
126
130
|
/** OpenAI reasoning effort for GPT/o-series reasoning models. */
|
|
127
131
|
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
132
|
+
reasoning?: ReasoningSetting;
|
|
128
133
|
|
|
129
134
|
/** Optional guidance prompt injected into discovery agent system prompts */
|
|
130
135
|
prompt?: string;
|
|
@@ -170,6 +175,11 @@ export interface PentestWorkflowInput {
|
|
|
170
175
|
|
|
171
176
|
export interface PentestWorkflowResult {
|
|
172
177
|
findings: Finding[];
|
|
178
|
+
reportedFindings?: string[];
|
|
179
|
+
objectiveResults?: PentestResult["objectiveResults"];
|
|
180
|
+
submissionJson?: string;
|
|
181
|
+
solved?: boolean;
|
|
182
|
+
summary?: string;
|
|
173
183
|
findingsPath: string;
|
|
174
184
|
pocsPath: string;
|
|
175
185
|
reportPath: string | null;
|
|
@@ -178,6 +188,7 @@ export interface PentestWorkflowResult {
|
|
|
178
188
|
export type { SwarmTarget } from "../session/persistence";
|
|
179
189
|
|
|
180
190
|
export interface PentestSwarmInput {
|
|
191
|
+
findingPolicy?: FindingPolicy;
|
|
181
192
|
targets: SwarmTarget[];
|
|
182
193
|
model: AIModel;
|
|
183
194
|
session: SessionInfo;
|
|
@@ -192,6 +203,7 @@ export interface PentestSwarmInput {
|
|
|
192
203
|
enableThinking?: boolean;
|
|
193
204
|
thinkingEffort?: ThinkingEffort | null;
|
|
194
205
|
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
206
|
+
reasoning?: ReasoningSetting;
|
|
195
207
|
/**
|
|
196
208
|
* X display (e.g. `":11"`) for every swarm sub-agent's browser, so a swarm
|
|
197
209
|
* launched by an orchestrator on a per-endpoint virtual desktop keeps its
|
|
@@ -243,6 +255,7 @@ export interface PentestSwarmTargetInput {
|
|
|
243
255
|
enableThinking?: boolean;
|
|
244
256
|
thinkingEffort?: ThinkingEffort | null;
|
|
245
257
|
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
258
|
+
reasoning?: ReasoningSetting;
|
|
246
259
|
display?: string;
|
|
247
260
|
onError?: (e: unknown) => void;
|
|
248
261
|
/** The swarm's shared {@link AgentHooks}; merged with `seams.hooksForItem` for this target. */
|
|
@@ -278,6 +291,7 @@ export async function runPentestSwarmTarget(
|
|
|
278
291
|
enableThinking,
|
|
279
292
|
thinkingEffort,
|
|
280
293
|
openAIReasoningEffort,
|
|
294
|
+
reasoning,
|
|
281
295
|
display,
|
|
282
296
|
onError,
|
|
283
297
|
hooks: sharedHooks,
|
|
@@ -290,7 +304,23 @@ export async function runPentestSwarmTarget(
|
|
|
290
304
|
const subagentId = entry.id;
|
|
291
305
|
const subagentName = target.name ?? entry.name;
|
|
292
306
|
|
|
293
|
-
if (completedIds.has(subagentId))
|
|
307
|
+
if (completedIds.has(subagentId)) {
|
|
308
|
+
if (sharedHooks.findingPolicy !== "external") return null;
|
|
309
|
+
const reportedFindings = loadSubagentReportedFindings(session, subagentId);
|
|
310
|
+
const objectiveResults = loadSubagentObjectiveResults(session, subagentId);
|
|
311
|
+
if (!reportedFindings || !objectiveResults) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
`Cannot resume externally graded pentest: findings or objective results for completed agent ${subagentId} are unavailable`,
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
findings: [],
|
|
318
|
+
reportedFindings,
|
|
319
|
+
objectiveResults,
|
|
320
|
+
findingsPath: session.findingsPath,
|
|
321
|
+
pocsPath: session.pocsPath,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
294
324
|
|
|
295
325
|
// Per-target AgentHooks: seams.hooksForItem can give this one target
|
|
296
326
|
// (e.g. its own lease/backends, its own politeness budget) different
|
|
@@ -367,6 +397,7 @@ export async function runPentestSwarmTarget(
|
|
|
367
397
|
enableThinking,
|
|
368
398
|
thinkingEffort,
|
|
369
399
|
openAIReasoningEffort,
|
|
400
|
+
reasoning,
|
|
370
401
|
display,
|
|
371
402
|
...itemHooks,
|
|
372
403
|
abortSignal: childSignal,
|
|
@@ -412,21 +443,44 @@ export async function runPentestSwarmTarget(
|
|
|
412
443
|
enableThinking,
|
|
413
444
|
thinkingEffort,
|
|
414
445
|
openAIReasoningEffort,
|
|
446
|
+
reasoning,
|
|
415
447
|
display,
|
|
416
448
|
...itemHooks,
|
|
417
449
|
abortSignal: childSignal,
|
|
418
450
|
});
|
|
419
451
|
|
|
420
452
|
const result = await agent.consume();
|
|
453
|
+
if (
|
|
454
|
+
itemHooks.findingPolicy === "external" &&
|
|
455
|
+
(!Array.isArray(result.reportedFindings) ||
|
|
456
|
+
!Array.isArray(result.objectiveResults))
|
|
457
|
+
) {
|
|
458
|
+
throw new Error(
|
|
459
|
+
`Externally graded pentest worker ${subagentId} ended without structured findings and objective results`,
|
|
460
|
+
);
|
|
461
|
+
}
|
|
421
462
|
|
|
422
463
|
saveSubagentData(session, {
|
|
423
464
|
agentName: subagentId,
|
|
424
465
|
target: target.target,
|
|
425
466
|
objective: objectiveStr,
|
|
426
467
|
status: "completed",
|
|
427
|
-
findingsCount: result.findings.length,
|
|
468
|
+
findingsCount: result.reportedFindings?.length ?? result.findings.length,
|
|
469
|
+
...(itemHooks.findingPolicy === "external"
|
|
470
|
+
? {
|
|
471
|
+
reportedFindings: result.reportedFindings,
|
|
472
|
+
objectiveResults: result.objectiveResults,
|
|
473
|
+
}
|
|
474
|
+
: {}),
|
|
428
475
|
messages: [...previousMessages, ...lastMessages],
|
|
429
|
-
systemPrompt: buildPentestSystemPrompt(
|
|
476
|
+
systemPrompt: buildPentestSystemPrompt(
|
|
477
|
+
session,
|
|
478
|
+
"orchestrator",
|
|
479
|
+
"default",
|
|
480
|
+
undefined,
|
|
481
|
+
undefined,
|
|
482
|
+
itemHooks.findingPolicy,
|
|
483
|
+
),
|
|
430
484
|
userPrompt: agent.userPrompt,
|
|
431
485
|
});
|
|
432
486
|
updateManifestEntryStatus(session, subagentId, "completed");
|
|
@@ -450,7 +504,14 @@ export async function runPentestSwarmTarget(
|
|
|
450
504
|
status: "failed",
|
|
451
505
|
error: error instanceof Error ? error.message : String(error),
|
|
452
506
|
messages: [...previousMessages, ...lastMessages],
|
|
453
|
-
systemPrompt: buildPentestSystemPrompt(
|
|
507
|
+
systemPrompt: buildPentestSystemPrompt(
|
|
508
|
+
session,
|
|
509
|
+
"orchestrator",
|
|
510
|
+
"default",
|
|
511
|
+
undefined,
|
|
512
|
+
undefined,
|
|
513
|
+
itemHooks.findingPolicy,
|
|
514
|
+
),
|
|
454
515
|
userPrompt: agent?.userPrompt ?? "",
|
|
455
516
|
});
|
|
456
517
|
updateManifestEntryStatus(session, subagentId, "failed");
|
|
@@ -497,6 +558,7 @@ export async function runPentestSwarm(
|
|
|
497
558
|
enableThinking,
|
|
498
559
|
thinkingEffort,
|
|
499
560
|
openAIReasoningEffort,
|
|
561
|
+
reasoning,
|
|
500
562
|
display,
|
|
501
563
|
subagentSpawner,
|
|
502
564
|
languageModelMiddleware,
|
|
@@ -522,6 +584,7 @@ export async function runPentestSwarm(
|
|
|
522
584
|
usageRecorder,
|
|
523
585
|
streamIdFactory,
|
|
524
586
|
...hooks,
|
|
587
|
+
findingPolicy: hooks?.findingPolicy ?? input.findingPolicy,
|
|
525
588
|
};
|
|
526
589
|
|
|
527
590
|
// Ops-typed by the seam; TargetedPentestAgent/OffensiveSecurityAgent only
|
|
@@ -558,6 +621,7 @@ export async function runPentestSwarm(
|
|
|
558
621
|
enableThinking,
|
|
559
622
|
thinkingEffort,
|
|
560
623
|
openAIReasoningEffort,
|
|
624
|
+
reasoning,
|
|
561
625
|
display,
|
|
562
626
|
onError,
|
|
563
627
|
hooks: sharedHooks,
|
|
@@ -574,6 +638,15 @@ export async function runPentestSwarm(
|
|
|
574
638
|
|
|
575
639
|
finalizeManifest(session, manifestEntries, results);
|
|
576
640
|
|
|
641
|
+
if (
|
|
642
|
+
sharedHooks.findingPolicy === "external" &&
|
|
643
|
+
results.some((result) => result === null)
|
|
644
|
+
) {
|
|
645
|
+
throw new Error(
|
|
646
|
+
"Externally graded pentest has an incomplete swarm target; findings cannot be aggregated",
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
|
|
577
650
|
return results;
|
|
578
651
|
}
|
|
579
652
|
|
|
@@ -609,10 +682,12 @@ export async function runPentestWorkflow(
|
|
|
609
682
|
enableThinking,
|
|
610
683
|
thinkingEffort,
|
|
611
684
|
openAIReasoningEffort,
|
|
685
|
+
reasoning,
|
|
612
686
|
prompt,
|
|
613
687
|
threatModel,
|
|
614
688
|
surfaceIntegrationEnabled,
|
|
615
689
|
} = input;
|
|
690
|
+
const findingPolicy = input.hooks?.findingPolicy ?? input.findingPolicy;
|
|
616
691
|
|
|
617
692
|
// Default registries mirror today's `FindingsRegistry.fromDirectory` resume
|
|
618
693
|
// behavior (dedup against on-disk findings, model-backed semantic dedup).
|
|
@@ -626,6 +701,7 @@ export async function runPentestWorkflow(
|
|
|
626
701
|
findings: () =>
|
|
627
702
|
FindingsRegistry.fromDirectory(session.findingsPath, {
|
|
628
703
|
model,
|
|
704
|
+
reasoning,
|
|
629
705
|
authConfig,
|
|
630
706
|
abortSignal,
|
|
631
707
|
sessionId: session.id,
|
|
@@ -698,6 +774,7 @@ export async function runPentestWorkflow(
|
|
|
698
774
|
onStepFinish,
|
|
699
775
|
onCacheMetrics,
|
|
700
776
|
openAIReasoningEffort,
|
|
777
|
+
reasoning,
|
|
701
778
|
surfaceIntegrationEnabled,
|
|
702
779
|
subagentSpawner: input.subagentSpawner,
|
|
703
780
|
hooks: {
|
|
@@ -706,6 +783,7 @@ export async function runPentestWorkflow(
|
|
|
706
783
|
usageRecorder: input.usageRecorder,
|
|
707
784
|
streamIdFactory: input.streamIdFactory,
|
|
708
785
|
...input.hooks,
|
|
786
|
+
findingPolicy,
|
|
709
787
|
},
|
|
710
788
|
seams,
|
|
711
789
|
});
|
|
@@ -720,12 +798,14 @@ export async function runPentestWorkflow(
|
|
|
720
798
|
onStepFinish,
|
|
721
799
|
onCacheMetrics,
|
|
722
800
|
openAIReasoningEffort,
|
|
801
|
+
reasoning,
|
|
723
802
|
hooks: {
|
|
724
803
|
subagentSpawner: input.subagentSpawner,
|
|
725
804
|
languageModelMiddleware: input.languageModelMiddleware,
|
|
726
805
|
usageRecorder: input.usageRecorder,
|
|
727
806
|
streamIdFactory: input.streamIdFactory,
|
|
728
807
|
...input.hooks,
|
|
808
|
+
findingPolicy,
|
|
729
809
|
},
|
|
730
810
|
});
|
|
731
811
|
}
|
|
@@ -744,6 +824,16 @@ export async function runPentestWorkflow(
|
|
|
744
824
|
}
|
|
745
825
|
|
|
746
826
|
if (swarmTargets.length === 0) {
|
|
827
|
+
if (findingPolicy === "external") {
|
|
828
|
+
return {
|
|
829
|
+
findings: [],
|
|
830
|
+
reportedFindings: [],
|
|
831
|
+
objectiveResults: [],
|
|
832
|
+
findingsPath: session.findingsPath,
|
|
833
|
+
pocsPath: session.pocsPath,
|
|
834
|
+
reportPath: null,
|
|
835
|
+
};
|
|
836
|
+
}
|
|
747
837
|
const report = buildPentestReport([], {
|
|
748
838
|
target,
|
|
749
839
|
model,
|
|
@@ -778,10 +868,15 @@ export async function runPentestWorkflow(
|
|
|
778
868
|
const findingsRegistry = seams.registries.findings() as FindingsRegistry;
|
|
779
869
|
|
|
780
870
|
const completedCount = getCompletedAgentIds(session).size;
|
|
871
|
+
let externalReportedFindings: string[] = [];
|
|
872
|
+
let externalObjectiveResults: NonNullable<
|
|
873
|
+
PentestResult["objectiveResults"]
|
|
874
|
+
> = [];
|
|
781
875
|
|
|
782
|
-
if (completedCount < swarmTargets.length) {
|
|
783
|
-
await runPentestSwarm({
|
|
876
|
+
if (findingPolicy === "external" || completedCount < swarmTargets.length) {
|
|
877
|
+
const swarmResults = await runPentestSwarm({
|
|
784
878
|
targets: swarmTargets,
|
|
879
|
+
findingPolicy,
|
|
785
880
|
model,
|
|
786
881
|
session,
|
|
787
882
|
authConfig,
|
|
@@ -793,6 +888,7 @@ export async function runPentestWorkflow(
|
|
|
793
888
|
enableThinking,
|
|
794
889
|
thinkingEffort,
|
|
795
890
|
openAIReasoningEffort,
|
|
891
|
+
reasoning,
|
|
796
892
|
subagentSpawner: input.subagentSpawner,
|
|
797
893
|
languageModelMiddleware: input.languageModelMiddleware,
|
|
798
894
|
usageRecorder: input.usageRecorder,
|
|
@@ -800,12 +896,33 @@ export async function runPentestWorkflow(
|
|
|
800
896
|
hooks: input.hooks,
|
|
801
897
|
seams,
|
|
802
898
|
});
|
|
899
|
+
externalReportedFindings = swarmResults.flatMap(
|
|
900
|
+
(result) => result?.reportedFindings ?? [],
|
|
901
|
+
);
|
|
902
|
+
externalObjectiveResults = swarmResults.flatMap(
|
|
903
|
+
(result) => result?.objectiveResults ?? [],
|
|
904
|
+
);
|
|
803
905
|
}
|
|
804
906
|
|
|
805
907
|
if (abortSignal?.aborted) {
|
|
806
908
|
throw new DOMException("Pentest aborted by user", "AbortError");
|
|
807
909
|
}
|
|
808
910
|
|
|
911
|
+
if (findingPolicy === "external") {
|
|
912
|
+
eventBus?.emit("workflow-phase-complete", {
|
|
913
|
+
phase: "pentesting",
|
|
914
|
+
summary: { findingsCount: externalReportedFindings.length },
|
|
915
|
+
});
|
|
916
|
+
return {
|
|
917
|
+
findings: [],
|
|
918
|
+
reportedFindings: externalReportedFindings,
|
|
919
|
+
objectiveResults: externalObjectiveResults,
|
|
920
|
+
findingsPath: session.findingsPath,
|
|
921
|
+
pocsPath: session.pocsPath,
|
|
922
|
+
reportPath: null,
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
|
|
809
926
|
// =========================================================================
|
|
810
927
|
// Phase 3: Aggregate results
|
|
811
928
|
// =========================================================================
|
|
@@ -881,6 +998,7 @@ async function runWhiteboxPhase(opts: {
|
|
|
881
998
|
onStepFinish?: StreamTextOnStepFinishCallback<ToolSet>;
|
|
882
999
|
onCacheMetrics?: (metrics: CacheMetrics) => void;
|
|
883
1000
|
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
1001
|
+
reasoning?: ReasoningSetting;
|
|
884
1002
|
surfaceIntegrationEnabled?: boolean;
|
|
885
1003
|
subagentSpawner?: SubagentSpawner;
|
|
886
1004
|
hooks?: AgentHooks;
|
|
@@ -896,6 +1014,7 @@ async function runWhiteboxPhase(opts: {
|
|
|
896
1014
|
onStepFinish: opts.onStepFinish,
|
|
897
1015
|
onCacheMetrics: opts.onCacheMetrics,
|
|
898
1016
|
openAIReasoningEffort: opts.openAIReasoningEffort,
|
|
1017
|
+
reasoning: opts.reasoning,
|
|
899
1018
|
surfaceIntegrationEnabled: opts.surfaceIntegrationEnabled,
|
|
900
1019
|
subagentSpawner: opts.subagentSpawner,
|
|
901
1020
|
hooks: opts.hooks,
|
|
@@ -931,6 +1050,7 @@ async function runBlackboxPhase(opts: {
|
|
|
931
1050
|
onStepFinish?: StreamTextOnStepFinishCallback<ToolSet>;
|
|
932
1051
|
onCacheMetrics?: (metrics: CacheMetrics) => void;
|
|
933
1052
|
openAIReasoningEffort?: OpenAIReasoningEffort | null;
|
|
1053
|
+
reasoning?: ReasoningSetting;
|
|
934
1054
|
}): Promise<SwarmTarget[]> {
|
|
935
1055
|
let lastMessages: ModelMessage[] = [];
|
|
936
1056
|
|
|
@@ -954,6 +1074,7 @@ async function runBlackboxPhase(opts: {
|
|
|
954
1074
|
},
|
|
955
1075
|
onCacheMetrics: opts.onCacheMetrics,
|
|
956
1076
|
openAIReasoningEffort: opts.openAIReasoningEffort,
|
|
1077
|
+
reasoning: opts.reasoning,
|
|
957
1078
|
};
|
|
958
1079
|
|
|
959
1080
|
const agent = new BlackboxAttackSurfaceAgent(agentInput);
|