From c33132b0ab56070e0e8f7db3a112b57019d9fb7a Mon Sep 17 00:00:00 2001 From: ajmallesh Date: Wed, 26 Aug 2026 19:37:20 -0700 Subject: [PATCH] feat(worker): deduplicate static and runtime findings before exploitation Parse Agentic SAST SARIF into typed observations, enrich and route those observations, and reconcile them with pentest findings before exploitation. Publish deterministic exploitation queues with stable lineage, exact-path Git commits, retry-safe manifests, named drop reasons, and confined task formation. Reject duplicate producer IDs before commit and adopt either legal provenance shape after a lost acknowledgement. --- apps/worker/prompts/sast-enrichment-auth.txt | 13 + apps/worker/prompts/sast-enrichment-authz.txt | 12 + .../prompts/sast-enrichment-injection.txt | 16 + .../prompts/sast-enrichment-miscellaneous.txt | 14 + apps/worker/prompts/sast-enrichment-ssrf.txt | 11 + apps/worker/prompts/sast-enrichment-xss.txt | 11 + .../_sast-enrichment-procedure.txt | 7 + .../_task-formation-procedure.txt | 29 + apps/worker/prompts/task-formation-auth.txt | 11 + apps/worker/prompts/task-formation-authz.txt | 11 + .../prompts/task-formation-injection.txt | 11 + .../prompts/task-formation-miscellaneous.txt | 11 + apps/worker/prompts/task-formation-ssrf.txt | 11 + apps/worker/prompts/task-formation-xss.txt | 11 + apps/worker/src/ai/pi/source-jail.ts | 279 +++++++ .../worker/src/ai/pi/structured-generation.ts | 31 +- .../src/ai/pi/task-formation-executor.ts | 786 ++++++++++++++++++ apps/worker/src/ai/queue-schemas.ts | 198 ++++- .../src/ai/reconciliation/artifact-store.ts | 518 ++++++++++++ .../worker/src/ai/reconciliation/contracts.ts | 131 +++ apps/worker/src/ai/reconciliation/enrich.ts | 415 +++++++++ apps/worker/src/ai/reconciliation/form.ts | 432 ++++++++++ apps/worker/src/ai/reconciliation/labels.ts | 47 ++ apps/worker/src/ai/reconciliation/manifest.ts | 230 +++++ .../src/ai/reconciliation/materialize-core.ts | 179 ++++ .../src/ai/reconciliation/materialize.ts | 213 +++++ .../src/ai/reconciliation/observation-view.ts | 109 +++ .../src/ai/reconciliation/observations.ts | 20 + apps/worker/src/ai/reconciliation/prepare.ts | 379 +++++++++ apps/worker/src/ai/reconciliation/publish.ts | 647 ++++++++++++++ apps/worker/src/ai/reconciliation/refs.ts | 50 ++ .../reconciliation/sast/context-extractor.ts | 82 ++ .../src/ai/reconciliation/sast/cwe-mapper.ts | 103 +++ .../reconciliation/sast/enrichment/batch.ts | 86 ++ .../reconciliation/sast/enrichment/policy.ts | 53 ++ .../reconciliation/sast/enrichment/schema.ts | 61 ++ .../sast/enrichment/validate.ts | 205 +++++ .../src/ai/reconciliation/sast/intake.ts | 132 +++ .../ai/reconciliation/sast/sarif-parser.ts | 270 ++++++ .../src/ai/reconciliation/sast/types.ts | 132 +++ .../src/ai/reconciliation/schema-version.ts | 7 + .../ai/reconciliation/seed-miscellaneous.ts | 205 +++++ .../src/ai/reconciliation/stage-contracts.ts | 160 ++++ .../ai/reconciliation/submit-validation.ts | 118 +++ .../reconciliation/task-formation-schema.ts | 209 +++++ .../src/collectors/exploit-collector.ts | 85 +- apps/worker/src/services/exploit-renderer.ts | 9 +- apps/worker/src/services/git-manager.ts | 299 ++++++- apps/worker/src/services/queue-validation.ts | 124 ++- .../src/temporal/reconcile-activities.ts | 542 ++++++++++++ .../src/temporal/reconcile-activity-types.ts | 246 ++++++ apps/worker/src/types/reconciliation.ts | 27 + 52 files changed, 7914 insertions(+), 84 deletions(-) create mode 100644 apps/worker/prompts/sast-enrichment-auth.txt create mode 100644 apps/worker/prompts/sast-enrichment-authz.txt create mode 100644 apps/worker/prompts/sast-enrichment-injection.txt create mode 100644 apps/worker/prompts/sast-enrichment-miscellaneous.txt create mode 100644 apps/worker/prompts/sast-enrichment-ssrf.txt create mode 100644 apps/worker/prompts/sast-enrichment-xss.txt create mode 100644 apps/worker/prompts/shared/exploitation/_sast-enrichment-procedure.txt create mode 100644 apps/worker/prompts/shared/exploitation/_task-formation-procedure.txt create mode 100644 apps/worker/prompts/task-formation-auth.txt create mode 100644 apps/worker/prompts/task-formation-authz.txt create mode 100644 apps/worker/prompts/task-formation-injection.txt create mode 100644 apps/worker/prompts/task-formation-miscellaneous.txt create mode 100644 apps/worker/prompts/task-formation-ssrf.txt create mode 100644 apps/worker/prompts/task-formation-xss.txt create mode 100644 apps/worker/src/ai/pi/source-jail.ts create mode 100644 apps/worker/src/ai/pi/task-formation-executor.ts create mode 100644 apps/worker/src/ai/reconciliation/artifact-store.ts create mode 100644 apps/worker/src/ai/reconciliation/contracts.ts create mode 100644 apps/worker/src/ai/reconciliation/enrich.ts create mode 100644 apps/worker/src/ai/reconciliation/form.ts create mode 100644 apps/worker/src/ai/reconciliation/labels.ts create mode 100644 apps/worker/src/ai/reconciliation/manifest.ts create mode 100644 apps/worker/src/ai/reconciliation/materialize-core.ts create mode 100644 apps/worker/src/ai/reconciliation/materialize.ts create mode 100644 apps/worker/src/ai/reconciliation/observation-view.ts create mode 100644 apps/worker/src/ai/reconciliation/observations.ts create mode 100644 apps/worker/src/ai/reconciliation/prepare.ts create mode 100644 apps/worker/src/ai/reconciliation/publish.ts create mode 100644 apps/worker/src/ai/reconciliation/refs.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/context-extractor.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/cwe-mapper.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/enrichment/batch.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/enrichment/policy.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/enrichment/schema.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/enrichment/validate.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/intake.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/sarif-parser.ts create mode 100644 apps/worker/src/ai/reconciliation/sast/types.ts create mode 100644 apps/worker/src/ai/reconciliation/schema-version.ts create mode 100644 apps/worker/src/ai/reconciliation/seed-miscellaneous.ts create mode 100644 apps/worker/src/ai/reconciliation/stage-contracts.ts create mode 100644 apps/worker/src/ai/reconciliation/submit-validation.ts create mode 100644 apps/worker/src/ai/reconciliation/task-formation-schema.ts create mode 100644 apps/worker/src/temporal/reconcile-activities.ts create mode 100644 apps/worker/src/temporal/reconcile-activity-types.ts create mode 100644 apps/worker/src/types/reconciliation.ts diff --git a/apps/worker/prompts/sast-enrichment-auth.txt b/apps/worker/prompts/sast-enrichment-auth.txt new file mode 100644 index 00000000..ece5df4b --- /dev/null +++ b/apps/worker/prompts/sast-enrichment-auth.txt @@ -0,0 +1,13 @@ +@include(shared/exploitation/_sast-enrichment-procedure.txt) + +These findings are authentication vulnerabilities. + +CRITICAL RULES: +- exploitation_hypothesis must describe what an attacker ACHIEVES, not just confirm the vulnerability exists. +- suggested_exploit_technique must be an actionable attack the exploitation agent can execute against a live application. +- source_endpoint: infer the HTTP method and path from the code context (route definitions, handler functions). +- For hard-coded credentials (CWE-798): exploitation_hypothesis should specify using the found credentials. +- For CSRF (CWE-352): include the state-changing action that can be forged. +- _sastId MUST be copied exactly from the input finding. It is the join key — never invent, renumber, or omit it. + +SAST FINDINGS: diff --git a/apps/worker/prompts/sast-enrichment-authz.txt b/apps/worker/prompts/sast-enrichment-authz.txt new file mode 100644 index 00000000..7618f1aa --- /dev/null +++ b/apps/worker/prompts/sast-enrichment-authz.txt @@ -0,0 +1,12 @@ +@include(shared/exploitation/_sast-enrichment-procedure.txt) + +These findings are authorization vulnerabilities. + +CRITICAL RULES: +- Horizontal: same role accessing another user's data. Vertical: lower role accessing higher role's functions. Context_Workflow: bypassing a required step/state. Mass_Assignment: adding privileged fields (role, isAdmin, permissions) to request body that the server binds without filtering. +- If a proof-of-concept exists in the SAST data, use its inputs to craft a specific minimal_witness. +- guard_evidence must describe what's MISSING, not what exists. +- side_effect must be a concrete unauthorized action (e.g., "read other user's medical records"), not vague ("unauthorized access"). +- _sastId MUST be copied exactly from the input finding. It is the join key — never invent, renumber, or omit it. + +SAST FINDINGS: diff --git a/apps/worker/prompts/sast-enrichment-injection.txt b/apps/worker/prompts/sast-enrichment-injection.txt new file mode 100644 index 00000000..511ac4f0 --- /dev/null +++ b/apps/worker/prompts/sast-enrichment-injection.txt @@ -0,0 +1,16 @@ +@include(shared/exploitation/_sast-enrichment-procedure.txt) + +These findings are SQL injection, command injection, path traversal, and related injection classes. Each finding must be transformed into a vulnerability object matching the schema. + +CRITICAL RULES: +- witness_payload MUST be tailored to the actual sink code. If the sink is `db.query("SELECT * FROM users WHERE name LIKE '%" + input + "%'")`, use `%' OR '%'='` not a generic `' OR 1=1--`. +- slot_type MUST reflect the actual SQL/command/file context from the code snippet. +- If dataflow path is provided, use it to build an accurate `path` field. +- If sanitization functions appear in the path, list them in `sanitization_observed` and explain in `mismatch_reason` why they're insufficient. +- Set externally_exploitable=true only if the source is user-controlled input (HTTP params, headers, request body, cookies). +- _sastId MUST be copied exactly from the input finding. It is the join key — never invent, renumber, or omit it. +- For XML injection (CWE-91): slot_type is XML-element or XML-attribute depending on where user input lands in the XML structure. +- For prompt injection (CWE-1427): slot_type is PROMPT-instruction. witness_payload should demonstrate instruction override, not generic text. +- For prototype pollution (CWE-1321): slot_type is PROTO-property. witness_payload should use __proto__ or constructor.prototype paths specific to the sink. + +SAST FINDINGS: diff --git a/apps/worker/prompts/sast-enrichment-miscellaneous.txt b/apps/worker/prompts/sast-enrichment-miscellaneous.txt new file mode 100644 index 00000000..7b92b157 --- /dev/null +++ b/apps/worker/prompts/sast-enrichment-miscellaneous.txt @@ -0,0 +1,14 @@ +@include(shared/exploitation/_sast-enrichment-procedure.txt) + +These findings are weaknesses that fall outside the injection, XSS, authentication, authorization and SSRF classes. They share no family: session lifetime, error-message disclosure, sensitive logging, cleartext storage, request forgery, redirection, framing, algorithmic complexity, race conditions. + +CRITICAL RULES: +- vulnerability_type is the weakness's own name, taken from the CWE on the finding (e.g. 'Insecure Randomness', 'Use of Hard-coded Cryptographic Key'). There is no fixed list to pick from, and it must not be forced into another class's vocabulary. +- proof_criterion is the field the exploitation agent works from: state the concrete observation that would settle whether this specific weakness is real. These findings carry no per-class proof ladder, so an unusable criterion leaves the agent nothing to aim at. +- observable_signal must be something visible from outside the application, not a restatement of the source code. +- exploitation_hypothesis must describe what an attacker ACHIEVES, not just confirm the weakness exists. +- suggested_exploit_technique must be an actionable attack the exploitation agent can execute against a live application. +- cwe carries the id from the finding, e.g. CWE-330. +- _sastId MUST be copied exactly from the input finding. It is the join key — never invent, renumber, or omit it. + +SAST FINDINGS: diff --git a/apps/worker/prompts/sast-enrichment-ssrf.txt b/apps/worker/prompts/sast-enrichment-ssrf.txt new file mode 100644 index 00000000..77b9f193 --- /dev/null +++ b/apps/worker/prompts/sast-enrichment-ssrf.txt @@ -0,0 +1,11 @@ +@include(shared/exploitation/_sast-enrichment-procedure.txt) + +These findings are Server-Side Request Forgery vulnerabilities. + +CRITICAL RULES: +- vulnerability_type must match the sink pattern: HTTP client → URL_Manipulation, redirect function → Redirect_Abuse, webhook registration → Webhook_Injection. +- exploitation_hypothesis should reference likely internal targets (cloud metadata, internal APIs, admin panels) based on code context. +- suggested_exploit_technique must be actionable — the exploitation agent will actually attempt this against the live app. +- _sastId MUST be copied exactly from the input finding. It is the join key — never invent, renumber, or omit it. + +SAST FINDINGS: diff --git a/apps/worker/prompts/sast-enrichment-xss.txt b/apps/worker/prompts/sast-enrichment-xss.txt new file mode 100644 index 00000000..99dc5440 --- /dev/null +++ b/apps/worker/prompts/sast-enrichment-xss.txt @@ -0,0 +1,11 @@ +@include(shared/exploitation/_sast-enrichment-procedure.txt) + +These findings are Cross-Site Scripting vulnerabilities. + +CRITICAL RULES: +- Determine vulnerability_type from the source: HTTP request param → Reflected, database read → Stored, client-side only → DOM-based. +- render_context MUST be inferred from the actual sink code. `innerHTML` → HTML_BODY, `setAttribute('href', ...)` → HTML_ATTRIBUTE, template literal in