security-mcp 1.1.3 → 1.3.1

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 (133) hide show
  1. package/README.md +164 -185
  2. package/defaults/checklists/ai.json +20 -1
  3. package/defaults/checklists/api.json +35 -1
  4. package/defaults/checklists/infra.json +34 -1
  5. package/defaults/checklists/mobile.json +23 -1
  6. package/defaults/checklists/payments.json +15 -1
  7. package/defaults/checklists/web.json +11 -1
  8. package/defaults/control-catalog.json +200 -0
  9. package/defaults/security-policy.json +2 -2
  10. package/dist/cli/index.js +82 -5
  11. package/dist/cli/install.js +36 -6
  12. package/dist/cli/onboarding.js +6 -0
  13. package/dist/gate/baseline.js +82 -7
  14. package/dist/gate/catalog.js +10 -2
  15. package/dist/gate/checks/ai.js +757 -39
  16. package/dist/gate/checks/auth-deep.js +935 -0
  17. package/dist/gate/checks/business-logic.js +751 -0
  18. package/dist/gate/checks/ci-pipeline.js +399 -4
  19. package/dist/gate/checks/crypto.js +423 -2
  20. package/dist/gate/checks/dependencies.js +571 -15
  21. package/dist/gate/checks/graphql.js +201 -19
  22. package/dist/gate/checks/infra.js +246 -1
  23. package/dist/gate/checks/injection-deep.js +848 -0
  24. package/dist/gate/checks/k8s.js +114 -1
  25. package/dist/gate/checks/mobile-android.js +917 -3
  26. package/dist/gate/checks/mobile-ios.js +797 -5
  27. package/dist/gate/checks/required-artifacts.js +194 -0
  28. package/dist/gate/checks/runtime.js +178 -0
  29. package/dist/gate/checks/secrets.js +244 -13
  30. package/dist/gate/checks/supply-chain-deep.js +787 -0
  31. package/dist/gate/checks/web-nextjs.js +572 -48
  32. package/dist/gate/diff.js +17 -5
  33. package/dist/gate/evidence.js +8 -1
  34. package/dist/gate/exceptions.js +131 -9
  35. package/dist/gate/policy.js +282 -129
  36. package/dist/mcp/audit-chain.js +122 -28
  37. package/dist/mcp/auth.js +169 -0
  38. package/dist/mcp/learning.js +129 -4
  39. package/dist/mcp/model-router.js +158 -21
  40. package/dist/mcp/orchestration.js +186 -51
  41. package/dist/mcp/server.js +608 -94
  42. package/dist/repo/fs.js +24 -1
  43. package/dist/repo/search.js +31 -6
  44. package/dist/review/store.js +52 -1
  45. package/package.json +7 -7
  46. package/prompts/SECURITY_PROMPT.md +73 -0
  47. package/skills/_TEMPLATE/SKILL.md +99 -0
  48. package/skills/advanced-dos-tester/SKILL.md +109 -0
  49. package/skills/agentic-loop-exploiter/SKILL.md +368 -0
  50. package/skills/ai-llm-redteam/SKILL.md +104 -0
  51. package/skills/ai-model-supply-chain-agent/SKILL.md +103 -0
  52. package/skills/algorithm-implementation-reviewer/SKILL.md +98 -0
  53. package/skills/android-penetration-tester/SKILL.md +455 -46
  54. package/skills/anti-replay-tester/SKILL.md +106 -0
  55. package/skills/appsec-code-auditor/SKILL.md +120 -0
  56. package/skills/artifact-integrity-analyst/SKILL.md +441 -0
  57. package/skills/attack-navigator/SKILL.md +467 -8
  58. package/skills/auth-session-hacker/SKILL.md +128 -0
  59. package/skills/aws-penetration-tester/SKILL.md +456 -0
  60. package/skills/azure-penetration-tester/SKILL.md +490 -3
  61. package/skills/binary-auth-validator/SKILL.md +111 -0
  62. package/skills/bot-detection-specialist/SKILL.md +109 -0
  63. package/skills/business-logic-attacker/SKILL.md +231 -0
  64. package/skills/capec-code-mapper/SKILL.md +84 -0
  65. package/skills/cert-pin-rotation-specialist/SKILL.md +112 -0
  66. package/skills/cicd-pipeline-hijacker/SKILL.md +405 -0
  67. package/skills/ciso-orchestrator/SKILL.md +454 -43
  68. package/skills/cloud-infra-specialist/SKILL.md +118 -0
  69. package/skills/compliance-gap-analyst/SKILL.md +422 -0
  70. package/skills/compliance-grc/SKILL.md +85 -0
  71. package/skills/compliance-lifecycle-tracker/SKILL.md +84 -0
  72. package/skills/credential-stuffing-specialist/SKILL.md +102 -0
  73. package/skills/crypto-pki-specialist/SKILL.md +87 -0
  74. package/skills/csa-ccm-mapper/SKILL.md +84 -0
  75. package/skills/csf2-governance-mapper/SKILL.md +84 -0
  76. package/skills/deep-link-fuzzer/SKILL.md +109 -0
  77. package/skills/dependency-confusion-attacker/SKILL.md +415 -0
  78. package/skills/device-integrity-aggregator/SKILL.md +108 -0
  79. package/skills/dos-resilience-tester/SKILL.md +97 -0
  80. package/skills/dread-scorer/SKILL.md +84 -0
  81. package/skills/egress-policy-enforcer/SKILL.md +99 -0
  82. package/skills/evidence-collector/SKILL.md +98 -0
  83. package/skills/file-upload-attacker/SKILL.md +109 -0
  84. package/skills/gcp-penetration-tester/SKILL.md +459 -2
  85. package/skills/git-history-secret-scanner/SKILL.md +106 -0
  86. package/skills/iam-privesc-graph-builder/SKILL.md +152 -0
  87. package/skills/incident-responder/SKILL.md +111 -0
  88. package/skills/injection-specialist/SKILL.md +131 -0
  89. package/skills/ios-security-auditor/SKILL.md +282 -0
  90. package/skills/json-ambiguity-tester/SKILL.md +0 -0
  91. package/skills/k8s-container-escaper/SKILL.md +384 -0
  92. package/skills/key-management-lifecycle-analyst/SKILL.md +98 -0
  93. package/skills/kill-switch-engineer/SKILL.md +102 -0
  94. package/skills/linddun-privacy-analyst/SKILL.md +102 -0
  95. package/skills/logic-race-fuzzer/SKILL.md +443 -0
  96. package/skills/mobile-api-network-attacker/SKILL.md +421 -0
  97. package/skills/mobile-binary-hardener/SKILL.md +102 -0
  98. package/skills/mobile-security-specialist/SKILL.md +85 -0
  99. package/skills/mobile-webview-auditor/SKILL.md +96 -0
  100. package/skills/model-extraction-attacker/SKILL.md +219 -0
  101. package/skills/multipart-abuse-tester/SKILL.md +84 -0
  102. package/skills/oauth-pkce-specialist/SKILL.md +104 -0
  103. package/skills/parser-exhaustion-tester/SKILL.md +142 -0
  104. package/skills/pentest-infra/SKILL.md +141 -0
  105. package/skills/pentest-social/SKILL.md +201 -0
  106. package/skills/pentest-team/SKILL.md +134 -0
  107. package/skills/pentest-web-api/SKILL.md +151 -0
  108. package/skills/privacy-flow-analyst/SKILL.md +234 -0
  109. package/skills/prompt-injection-specialist/SKILL.md +394 -0
  110. package/skills/quantum-migration-planner/SKILL.md +96 -0
  111. package/skills/rag-poisoning-specialist/SKILL.md +358 -0
  112. package/skills/registry-mirror-enforcer/SKILL.md +84 -0
  113. package/skills/rotation-validation-agent/SKILL.md +112 -0
  114. package/skills/samm-assessor/SKILL.md +85 -0
  115. package/skills/secrets-mask-bypass-tester/SKILL.md +100 -0
  116. package/skills/senior-security-engineer/SKILL.md +370 -2
  117. package/skills/serialization-memory-attacker/SKILL.md +332 -0
  118. package/skills/session-timeout-tester/SKILL.md +161 -0
  119. package/skills/slsa-level3-enforcer/SKILL.md +112 -0
  120. package/skills/slsa-provenance-enforcer/SKILL.md +102 -0
  121. package/skills/ssrf-detection-validator/SKILL.md +108 -0
  122. package/skills/step-up-auth-enforcer/SKILL.md +84 -0
  123. package/skills/stride-pasta-analyst/SKILL.md +420 -0
  124. package/skills/supply-chain-devsecops/SKILL.md +98 -0
  125. package/skills/threat-infrastructure-analyst/SKILL.md +84 -0
  126. package/skills/threat-modeler/SKILL.md +85 -0
  127. package/skills/tls-certificate-auditor/SKILL.md +573 -18
  128. package/skills/token-reuse-detector/SKILL.md +95 -0
  129. package/skills/trike-risk-modeler/SKILL.md +84 -0
  130. package/skills/unicode-homograph-tester/SKILL.md +84 -0
  131. package/skills/waf-rule-lifecycle-agent/SKILL.md +97 -0
  132. package/skills/webhook-security-tester/SKILL.md +102 -0
  133. package/skills/zero-trust-architect/SKILL.md +109 -0
@@ -193,3 +193,112 @@ func handleDeepLink(_ url: URL) {
193
193
  - `requiredActions`: ordered action list
194
194
  - `complianceImpact`: framework mappings
195
195
  - `beyondSkillMd`: true if finding goes beyond the SKILL.md mandate
196
+
197
+ Every findings JSON MUST include `intelligenceForOtherAgents`:
198
+ ```json
199
+ {
200
+ "intelligenceForOtherAgents": {
201
+ "forPentestTeam": [{ "type": "HIGH_VALUE_TARGET", "description": "Custom-scheme OAuth callback — register competing app to intercept tokens", "exploitHint": "Side-load APK declaring identical myapp:// scheme on Android < 12; no disambiguation dialog on older APIs" }],
202
+ "forCryptoSpecialist": [{ "type": "CRYPTO_WEAKNESS_REFERENCE", "algorithm": "HMAC-SHA256 deep-link token signing absent", "location": "deep link token parameter — verify signing is present and key rotation policy exists" }],
203
+ "forCloudSpecialist": [{ "type": "SSRF_TO_CLOUD_CHAIN", "ssrfLocation": "Deep link `url=` parameter forwarded to server-side fetch", "escalationPath": "Inject file:// or http://169.254.169.254 to reach cloud IMDS and exfiltrate IAM credentials" }],
204
+ "forComplianceGrc": [{ "type": "COMPLIANCE_BLOCKER", "frameworks": ["PCI DSS Req 6.2.4", "OWASP M4:2024", "NIST SP 800-53 SI-10"], "releaseBlock": true }]
205
+ }
206
+ }
207
+ ```
208
+
209
+ ---
210
+
211
+ ## BEYOND SKILL.MD — MANDATORY EXPANSIONS
212
+
213
+ - **Android Intent Scheme Hijacking for OAuth Token Interception (CVE-2014-8962 class / ATT&CK T1406):** Malicious apps targeting Android < 12 register the same custom URI scheme (e.g., `myapp://`) as the victim app. When the OS presents an app-disambiguation dialog — or on older APIs silently routes to the attacker — OAuth `code` parameters in the callback deep link are intercepted and replayed. Test by: sideload a second APK declaring `<data android:scheme="myapp"/>` in a BROWSABLE intent filter; trigger a real OAuth flow and confirm the system routes the callback exclusively to the legitimate app (requires App Links with `assetlinks.json` SHA-256 pinning). Finding threshold: any app using a custom scheme for OAuth callbacks rather than `https://` Universal Links / App Links is CRITICAL regardless of Android version.
214
+
215
+ - **AI-Generated APK Scheme Squatting (Emerging Supply Chain Risk, 2025–2027):** LLM-assisted toolkits (e.g., Frida-based APK mutation + LLM manifest rewriter) can enumerate thousands of published app schemes from public `AndroidManifest.xml` files in APK mirrors and auto-generate competing apps at scale. This is a supply chain threat to any app distributed outside official stores. Test by: query `apkcombo.com` / `apkpure.com` programmatically for any APK that declares the same scheme as the target; flag if a competing package exists. Detection: integrate `adb shell pm query-intent-activities -a android.intent.action.VIEW -d "myapp://"` into the CI regression gate to alert on multiple handlers.
216
+
217
+ - **javascript: URI Percent-Encoding Bypass in WebView Deep Links (CWE-116 / OWASP M4:2024):** Deep link handlers that validate against a literal `javascript:` blocklist are bypassed by `%6Aavascript:`, `java%0dscript:`, or `&#106;avascript:` variants, which Android WebView decodes before execution. Researchers demonstrated this class of bypass against major banking apps (disclosed 2023 via HackerOne program reports). Test by: send `myapp://open?url=java%0Ascript%3Aalert%28document.cookie%29` — confirm the WebView does NOT execute script and rejects the URL after decoding. Finding threshold: any `WebView.loadUrl()` or `evaluateJavascript()` called with a deep-link-derived string that is not allowlist-validated post-decode is CRITICAL.
218
+
219
+ - **Post-Quantum MITM of apple-app-site-association / assetlinks.json (NIST PQC Transition, 2028–2030):** Universal Links and App Links depend on TLS integrity of the `/.well-known/` domain-association files fetched at app install. A cryptographically relevant quantum computer (CRQC) breaking classical ECDH/RSA TLS would allow silent substitution of these files, redirecting all deep link traffic to an attacker-controlled app. Prepare now by: (1) ensure HSTS with `max-age >= 31536000; includeSubDomains; preload` is set on the serving domain; (2) add CAA DNS records limiting issuance to one CA; (3) monitor for any `sha256_cert_fingerprints` or `appID` change via external polling every 15 minutes and alert on deviation. Finding threshold: absence of HSTS preloading or CAA records on the domain serving association files is HIGH in the current window and will be CRITICAL by 2028.
220
+
221
+ - **Deep Link Fragment Injection into SPA Router (Research: "URL Fragment Security" — Barth et al., Browser Security Handbook):** The URI fragment (`#...`) is stripped by native iOS/Android deep link handlers before the URL is passed to the OS, but single-page-app WebViews receive the raw URL including fragment. Client-side routers (React Navigation web fallback, Next.js App Router) that parse `window.location.hash` for navigation can be manipulated via `myapp://app/dashboard#/admin/users?impersonate=victim`. This class is invisible in server logs and missed by all server-side WAFs. Test by: construct a deep link with `#/admin` fragment and confirm the SPA router does not elevate privilege; verify that the native handler strips or normalises the fragment before passing the URL to any WebView. Finding threshold: any SPA router path elevation via fragment content is HIGH; privilege escalation to admin routes is CRITICAL.
222
+
223
+ - **EU Cyber Resilience Act (CRA) Article 13 — Deep Links as External Interfaces Requiring Documented Security Testing (Regulatory, effective 2027):** The CRA classifies mobile app deep-link entry points as "remote network interfaces" requiring manufacturers to document threat models and supply evidence of security testing before CE marking. Apps shipping to EU markets without documented deep-link fuzz results and a published vulnerability disclosure policy will face market withdrawal orders. Test by: generate a CRA Article 13 evidence package — enumerate all deep-link entry points, attach the `coverageManifest` from this agent's output, and confirm a Coordinated Vulnerability Disclosure (CVD) policy is published at `/.well-known/security.txt`. Finding threshold: absence of a security.txt or any undocumented deep-link entry point is a COMPLIANCE BLOCKER for EU distribution beginning 2027.
224
+
225
+ ---
226
+
227
+ ## §EDGE-CASE-MATRIX
228
+
229
+ The 5 deep-link attack cases that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
230
+
231
+ | # | Edge Case | Why Scanners Miss It | Concrete Test |
232
+ |---|-----------|----------------------|---------------|
233
+ | 1 | Intent redirect chain — deep link launches Intent B which launches Intent C | Scanner validates only the first-hop handler; the terminal Activity may be exported and unprotected | Trace all `startActivity`/`startActivityForResult` calls reachable from each deep link handler; verify terminal Activity is not `exported="true"` without a permission check |
234
+ | 2 | Percent-encoded `javascript:` bypass in WebView deep link | Validation regex matches raw `javascript:` but not `%6aavascript:` or `java%0ascript:` | Send `myapp://open?url=java%0dscript:alert(1)` and `%6Aavascript:alert(1)` — confirm WebView rejects both after decoding |
235
+ | 3 | Universal Link fallback to custom scheme on AASA fetch failure | When `apple-app-site-association` is unreachable (CDN outage, misconfigured server), iOS falls back to the custom-scheme handler which lacks the same host validation | Simulate AASA 404 by mocking the `.well-known` endpoint; confirm the fallback custom scheme handler applies identical host/path validation |
236
+ | 4 | Deep link parameter smuggled via fragment (`#`) into single-page app router | Server-side and native handlers only inspect path and query string; the fragment is handed directly to client-side JS router | Send `myapp://app/screen#/admin?token=attacker` — verify the native handler strips or ignores the fragment before routing, and the SPA router does not elevate privilege based on fragment content |
237
+ | 5 | Clone-and-replay OAuth deep link token across user sessions | Deep link OAuth tokens with long or no expiry can be reused by a different authenticated user by intercepting the callback URI | Record a legitimate `myapp://oauth/callback?code=XXX` invocation; replay it from a second device/session — confirm the token is single-use and bound to the originating session state |
238
+
239
+ ---
240
+
241
+ ## §TEMPORAL-THREATS
242
+
243
+ Threats materialising in the 2025–2030 window that deep-link defences designed today must account for.
244
+
245
+ | Threat | Est. Timeline | Relevance to Deep Links | Prepare Now By |
246
+ |--------|--------------|--------------------------|----------------|
247
+ | Android 15+ Intent resolution changes | 2025–2026 (active) | Google tightened implicit Intent resolution; apps targeting older `targetSdkVersion` may silently regress to insecure scheme matching | Pin `targetSdkVersion` to the current stable API level in CI; run deep-link intent resolution tests against API 35 emulator |
248
+ | AI-assisted scheme-hijacking toolkits | 2025–2027 (active) | LLM-generated APKs that enumerate and register known app schemes from public manifests are already feasible; custom-scheme OAuth callbacks are primary target | Migrate all OAuth callbacks to Universal Links / App Links now; treat any remaining custom-scheme OAuth as CRITICAL |
249
+ | EU Cyber Resilience Act (CRA) mobile requirements | 2026–2027 | Deep link input handling is in-scope as an "external interface" requiring documented security testing before CE marking | Document deep-link threat model and test evidence per CRA Article 13 requirements |
250
+ | Post-quantum TLS — AASA / assetlinks.json fetch integrity | 2028–2030 | Universal Link / App Link domain association files fetched over TLS; classical TLS broken by CRQC would allow MITM substitution of association files | Ensure `assetlinks.json` and `apple-app-site-association` are served with HSTS + CAA DNS records to limit mis-issuance window |
251
+ | WebView V8 sandbox escapes targeting deep-link-fed content | 2025–2028 | As renderer sandboxes tighten, deep-link-injected `javascript:` URIs that survive validation become higher-value exploitation primitives | Enforce `WebView.loadUrl` allowlist server-side, not just client-side; treat any client-only validation as insufficient |
252
+
253
+ ---
254
+
255
+ ## §DETECTION-GAP
256
+
257
+ What current mobile security monitoring CANNOT detect in the deep-link domain, and what to build to close each gap.
258
+
259
+ - **Scheme-hijacking by side-loaded app**: Play Protect / App Store review may miss a competing app registering the same custom URI scheme. No runtime event is emitted when Android resolves the intent to the wrong app. Need: instrument the app's OAuth callback to include a per-session `state` parameter validated server-side — a hijacked callback can intercept the code but cannot forge the server-side state check; alert on all state mismatches.
260
+ - **Fragment-based SPA router injection**: Native deep-link handlers and most WAFs do not log or inspect the URI fragment. The attack is invisible in server logs. Need: client-side CSP reporting + SPA router audit logging — emit a structured log event every time the client-side router evaluates a fragment-provided route, including the raw fragment value.
261
+ - **Universal Link AASA tampering via CDN misconfiguration**: If the `/.well-known/apple-app-site-association` file is served from a CDN with public write access, an attacker can substitute it. iOS caches the AASA; exploitation may not be detected for hours. Need: continuous external monitoring — poll the AASA and assetlinks.json endpoints every 15 minutes and alert on any change to the `appID` or `sha256_cert_fingerprints` fields.
262
+ - **Percent-encoded bypass surviving logs**: Most log pipelines store the raw encoded URI, not the decoded form. Security analysts searching for `javascript:` will miss `%6Aavascript:`. Need: decode URI parameters before writing to SIEM; add detection rule that flags any decoded parameter value starting with `javascript:`, `file:`, `data:text/html`, or `vbscript:`.
263
+ - **Cross-agent deep-link + SSRF chain**: A deep-link `url=` parameter that reaches a server-side fetch endpoint creates an SSRF chain invisible to either the deep-link-fuzzer or the SSRF agent alone. Need: CISO orchestrator Phase 1 synthesis — correlate deep-link open-redirect findings with ssrf-probe findings on the same parameter names before Phase 2.
264
+
265
+ ---
266
+
267
+ ## §ZERO-MISS-MANDATE
268
+
269
+ This agent CANNOT declare any attack class clean without explicit evidence of checking. For each item, output one of:
270
+ - `CHECKED: [N files] | [patterns used] | CLEAN`
271
+ - `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
272
+ - `SKIPPED: [reason — must be "not applicable: [evidence]"]`
273
+
274
+ **Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
275
+
276
+ Attack classes that MUST be accounted for:
277
+
278
+ | Attack Class | Minimum Pattern Search |
279
+ |---|---|
280
+ | Custom-scheme OAuth callback hijacking | `android:scheme` in manifests, `CFBundleURLTypes` in plists — confirm scheme is NOT used for OAuth; if it is, flag CRITICAL |
281
+ | `javascript:` / `data:` URI injection into WebView | `loadUrl`, `evaluateJavascript`, `stringByEvaluatingJavaScriptFromString` called with deep-link-derived string |
282
+ | Open redirect via `url=` / `redirect=` / `next=` parameter | All deep-link query parameter names forwarded to navigation or `loadUrl` |
283
+ | Unauthenticated deep link to protected screen | Handler code that skips authentication check when launched from Intent/URL |
284
+ | Missing / misconfigured AASA or assetlinks.json | Presence and correctness of `.well-known/apple-app-site-association` and `.well-known/assetlinks.json` |
285
+ | Exported Activity / BroadcastReceiver without permission | `exported="true"` without `android:permission` on any component in the deep-link intent filter |
286
+ | Fragment injection into SPA router | URL fragment (`#`) passed to client-side router without stripping |
287
+ | OAuth token replay across sessions | `state` parameter absent or not validated server-side in OAuth callback deep links |
288
+
289
+ The output findings JSON MUST include a `coverageManifest` key:
290
+ ```json
291
+ {
292
+ "coverageManifest": {
293
+ "attackClassesCovered": [
294
+ { "class": "Custom-scheme OAuth hijacking", "filesReviewed": 3, "patterns": ["android:scheme", "CFBundleURLTypes"], "result": "CLEAN" },
295
+ { "class": "WebView javascript: injection", "filesReviewed": 12, "patterns": ["loadUrl", "evaluateJavascript"], "result": "2 findings, both fixed" }
296
+ ],
297
+ "filesReviewed": 27,
298
+ "negativeAssertions": [
299
+ "Open redirect: no `url=`/`redirect=`/`next=` parameter forwarded to loadUrl across 27 files — 0 matches"
300
+ ],
301
+ "uncoveredReason": {}
302
+ }
303
+ }
304
+ ```
@@ -76,3 +76,418 @@ If internet permitted:
76
76
  - Package name, current version, vulnerability ID, CVSSv4, EPSS, CISA KEV status, fix version
77
77
  - Whether fix has been applied to lockfile
78
78
  SBOM written to `.mcp/agent-runs/{agentRunId}/sbom.cyclonedx.json`
79
+
80
+ Every findings JSON MUST include `intelligenceForOtherAgents`:
81
+ ```json
82
+ {
83
+ "intelligenceForOtherAgents": {
84
+ "forPentestTeam": [{ "type": "HIGH_VALUE_TARGET", "description": "...", "exploitHint": "..." }],
85
+ "forCryptoSpecialist": [{ "type": "CRYPTO_WEAKNESS_REFERENCE", "algorithm": "...", "location": "..." }],
86
+ "forCloudSpecialist": [{ "type": "SSRF_TO_CLOUD_CHAIN", "ssrfLocation": "...", "escalationPath": "..." }],
87
+ "forComplianceGrc": [{ "type": "COMPLIANCE_BLOCKER", "frameworks": ["..."], "releaseBlock": true }]
88
+ }
89
+ }
90
+ ```
91
+
92
+ ---
93
+
94
+ ## BEYOND SKILL.MD — MANDATORY EXPANSIONS
95
+
96
+ These six domain-specific expansions go beyond the base mandate. Each must be executed on
97
+ every run — they are not optional enrichment.
98
+
99
+ ### 1. Manifest Confusion Attack (CVE-2023-35116 class)
100
+
101
+ **Technique:** Attackers craft packages where the `package.json` presented to the registry
102
+ differs from the one extracted by npm install. The registry reads a top-level `package.json`
103
+ while npm resolves a nested or overridden one inside a tarball's subdirectory. This allows
104
+ hiding malicious `postinstall` scripts or dependency overrides from registry-level scanners.
105
+
106
+ **Detection:** For every package tarball in the lockfile, verify that the `_id` and `scripts`
107
+ fields in the registry's published metadata match what is extracted to `node_modules/<pkg>/package.json`
108
+ on disk after install. Run:
109
+ ```bash
110
+ npm pack <package>@<version> --dry-run 2>&1 | grep -E "package.json"
111
+ tar -tzf $(npm pack <package>@<version> 2>/dev/null) | grep package.json
112
+ ```
113
+ Finding: more than one `package.json` in the tarball root, or a `package.json` that is not
114
+ at the tarball root, is a manifest confusion candidate.
115
+
116
+ ### 2. GitHub Actions Supply Chain Injection (SLSA Level 0 Gap)
117
+
118
+ **Technique:** CI pipelines that reference actions via floating tags (`uses: actions/checkout@v3`)
119
+ rather than pinned SHA commits are vulnerable to tag-moving attacks. Maintainer account
120
+ compromise, typosquatted action names (`actions/chekout`), or malicious forks pushed under
121
+ a hijacked org all achieve arbitrary code execution in the CI build environment — where
122
+ secrets, tokens, and cloud credentials are present.
123
+
124
+ **Detection:** Grep all `.github/workflows/*.yml` for `uses:` lines not pinned to a full
125
+ 40-character SHA:
126
+ ```bash
127
+ grep -rn "uses:" .github/workflows/ | grep -v "@[0-9a-f]\{40\}"
128
+ ```
129
+ Every non-SHA pin is a finding. Cross-reference action names against the `step-security/harden-runner`
130
+ known-bad-actions list. Finding: any floating-tag action reference = HIGH. Any action name
131
+ with Levenshtein distance ≤ 1 from a known legitimate action = CRITICAL.
132
+
133
+ ### 3. Dependency Confusion via Internal Package Registry Priority Inversion
134
+
135
+ **Technique:** Private registries configured with `registry=https://private.registry/` in
136
+ `.npmrc` alongside `@scope:registry=https://private.registry/` can still resolve unscoped
137
+ packages from the public registry if the private registry returns a 404 for those names.
138
+ An attacker who discovers an internal unscoped package name (via job listings, error messages,
139
+ open-source leaks, or OSINT) can publish a higher-versioned package to public npm, causing
140
+ npm to prefer it via semver resolution even when a private copy exists.
141
+
142
+ **Detection:**
143
+ ```bash
144
+ # Extract all unscoped dependencies
145
+ node -e "const p=require('./package.json'); console.log(Object.keys({...p.dependencies,...p.devDependencies}).filter(n=>!n.startsWith('@')))"
146
+ # For each, check if it exists on public npm
147
+ for pkg in <unscoped-list>; do curl -sf "https://registry.npmjs.org/$pkg" | jq '.name' ; done
148
+ ```
149
+ Finding: any unscoped private package name that resolves successfully on public npm = CRITICAL
150
+ dependency confusion surface.
151
+
152
+ ### 4. PyPI Dependency Confusion and Wheel Filename Spoofing
153
+
154
+ **Technique:** PyPI package names are normalised (hyphens and underscores are interchangeable,
155
+ case-insensitive). A private package named `my_internal_lib` can be confused with
156
+ `my-internal-lib` or `My_Internal_Lib` published to PyPI. Additionally, malicious wheel
157
+ files can be crafted with platform tags that cause pip to prefer them on specific OS/arch
158
+ combinations while the safe version is served on the CI platform.
159
+
160
+ **Detection:**
161
+ ```bash
162
+ # Normalise all requirement names and check PyPI
163
+ pip index versions <package> 2>/dev/null | head -1
164
+ # Check for wheel platform confusion
165
+ pip download <package> --no-deps --dest /tmp/wheels/ && ls /tmp/wheels/
166
+ ```
167
+ Finding: any `requirements.txt` package resolvable on PyPI whose PyPI maintainer differs from
168
+ the expected internal team = HIGH. Wheel files with unexpected platform tags in lockfiles = MEDIUM.
169
+
170
+ ### 5. AI-Assisted Dependency Hallucination Attack (Emerging — Post-2024)
171
+
172
+ **Technique:** LLM coding assistants (GitHub Copilot, Cursor, Claude, GPT-4) hallucinate
173
+ package names that do not exist on public registries. Attackers monitor common hallucination
174
+ patterns (e.g., `express-validator-middleware`, `react-auth-helper`) and pre-register those
175
+ names on npm/PyPI. When a developer installs the hallucinated name based on an AI suggestion,
176
+ they install the attacker's package. This attack class requires no typosquatting — the package
177
+ name is invented from scratch by the AI.
178
+
179
+ **Detection:** For every dependency added in the last 6 months (check git log on package.json),
180
+ verify the package existed on the public registry before the date it was added to package.json:
181
+ ```bash
182
+ git log --follow -p package.json | grep '^\+' | grep '"name-to-check"'
183
+ # Cross with npm publish date: curl https://registry.npmjs.org/<pkg> | jq '.time.created'
184
+ ```
185
+ Finding: a package whose first publish date on the public registry is within 30 days of
186
+ its addition to the project's package.json, and which has <100 weekly downloads = HIGH
187
+ AI-hallucination-squatting candidate.
188
+
189
+ ### 6. SLSA Provenance and Build Attestation Gaps (US EO 14028 / EU CRA)
190
+
191
+ **Technique:** Without SLSA build provenance attestations, the build artifact cannot be
192
+ cryptographically linked to the source commit that produced it. An attacker who compromises
193
+ a build server can substitute a malicious artifact after the source checkout step, and
194
+ downstream consumers have no way to detect the substitution. This applies to npm packages,
195
+ container images, and Go modules alike.
196
+
197
+ **Detection:** For each published package or container in this project:
198
+ ```bash
199
+ # Check for SLSA provenance attestation
200
+ gh attestation verify <artifact> --owner <org>
201
+ # Check npm package for provenance
202
+ npm audit signatures <package>@<version>
203
+ # Check for sigstore signatures
204
+ cosign verify <image>:<tag> --certificate-oidc-issuer https://token.actions.githubusercontent.com
205
+ ```
206
+ Finding: any artifact published from CI without a verifiable SLSA L2+ provenance attestation
207
+ = HIGH. Any container image without a cosign signature from a trusted OIDC issuer = HIGH.
208
+ For projects subject to US EO 14028 or EU CRA: unsigned artifacts = CRITICAL compliance blocker.
209
+
210
+ ### 7. Go Module Proxy Cache Poisoning and Replace Directive Abuse
211
+
212
+ **Technique:** Go's module proxy (proxy.golang.org) caches module zip files. If an attacker
213
+ publishes a malicious module before the legitimate maintainer has claimed the module path,
214
+ the proxy serves the malicious version to all subsequent downloads. Additionally, `replace`
215
+ directives in `go.mod` that point to relative local paths or unverified GitHub forks
216
+ introduce dependency substitution that is invisible to standard SCA tools.
217
+
218
+ **Detection:**
219
+ ```bash
220
+ grep -n "replace" go.mod
221
+ # For each replace directive, verify the target
222
+ # Local path replaces: acceptable only in development, NEVER in published modules
223
+ grep -A1 "^replace" go.mod | grep -v "=>" | grep -v "^--$"
224
+ # Check GOPROXY for each dependency
225
+ GOPROXY=direct go mod download -json ./... 2>&1 | jq '.Path,.Version,.Dir'
226
+ ```
227
+ Finding: any `replace` directive pointing to a local path in a production go.mod = HIGH.
228
+ Any `replace` directive pointing to a GitHub fork without a `go.sum` entry = CRITICAL.
229
+
230
+ ### 8. Transitive Dependency Shadow and Phantom Dependency Exploitation
231
+
232
+ **Technique:** Build tools that hoist transitive dependencies to the root `node_modules`
233
+ (npm v3+, Yarn v1 hoisting) allow application code to `require()` packages that are not
234
+ declared in the project's own `package.json`. These "phantom dependencies" can be exploited
235
+ by introducing a malicious package that has the same name as a hoisted transitive dependency
236
+ at a higher version — causing the malicious version to be resolved first. pnpm's strict
237
+ mode prevents hoisting but is frequently disabled via `public-hoist-pattern=*`.
238
+
239
+ **Detection:**
240
+ ```bash
241
+ # Find phantom dependencies (imported but not declared)
242
+ node -e "
243
+ const declared = new Set(Object.keys(require('./package.json').dependencies || {}));
244
+ const fs = require('fs');
245
+ // grep all source imports
246
+ "
247
+ # Check pnpm config for disabled strict mode
248
+ grep "public-hoist-pattern" .npmrc pnpm-workspace.yaml 2>/dev/null
249
+ ```
250
+ Finding: any `require()` or `import` of a package not in `dependencies` or `devDependencies` = MEDIUM.
251
+ `public-hoist-pattern=*` in a pnpm project = HIGH (eliminates pnpm's primary confusion defence).
252
+
253
+ ---
254
+
255
+ ## §DEPENDENCY_CONFUSION_ATTACKER-CHECKLIST
256
+
257
+ Perform each item in order. Record the result inline before moving to the next.
258
+
259
+ 1. **Unscoped private package name collision** — For every unscoped package in `dependencies`
260
+ and `devDependencies`, query `https://registry.npmjs.org/<name>` and confirm the response
261
+ is 404 or is controlled by the organisation. Any 200 response where the maintainer is not
262
+ the internal team = CRITICAL. Grep: `jq '.dependencies, .devDependencies | keys[]' package.json | grep -v '^@'`
263
+
264
+ 2. **Registry priority order in `.npmrc`** — Confirm that `.npmrc` specifies the private
265
+ registry as the default (`registry=`) and that scoped packages are pinned to the private
266
+ registry with `@scope:registry=`. Absence of scope-pinning with a private registry configured
267
+ = HIGH. Grep: `cat .npmrc | grep -E "registry|scope"`
268
+
269
+ 3. **Lockfile integrity hash coverage** — Every entry in `package-lock.json` must have an
270
+ `integrity` field with a `sha512-` prefix. Missing or `sha1-` prefixed integrity values
271
+ indicate an old or tampered lockfile. Finding: `jq '.. | .integrity? | select(. != null) | select(startswith("sha1"))' package-lock.json`
272
+
273
+ 4. **Postinstall and lifecycle script network calls** — For every package with a `scripts.postinstall`,
274
+ `scripts.install`, `scripts.prepare`, or `scripts.preinstall` field, confirm the script
275
+ does not contain `curl`, `wget`, `fetch`, `http`, `https`, or `require('http')`. Any
276
+ network call in a lifecycle script = HIGH. Grep: `find node_modules -name package.json -maxdepth 3 | xargs grep -l "postinstall\|install\|prepare" | xargs grep -l "curl\|wget\|http"`
277
+
278
+ 5. **GitHub Actions floating tag pins** — All `uses:` references in `.github/workflows/` must
279
+ be pinned to a 40-character SHA. Floating tags (`@v1`, `@main`, `@latest`) = HIGH per
280
+ reference. Finding threshold: any unresolved floating tag. Grep: `grep -rn "uses:" .github/workflows/ | grep -v "@[0-9a-f]\{40\}"`
281
+
282
+ 6. **Go module replace directive audit** — Every `replace` directive in `go.mod` must reference
283
+ a published, version-tagged module or a workspace-local path that is explicitly declared
284
+ in `go.work`. Replace directives pointing to arbitrary GitHub branches = CRITICAL.
285
+ Grep: `grep -n "replace" go.mod`
286
+
287
+ 7. **Python hash pinning** — Every `requirements.txt` and `Pipfile.lock` must include SHA-256
288
+ hashes for each package. Absence of `--hash=sha256:` in requirements files = HIGH.
289
+ Finding: `grep -rL "hash" requirements*.txt 2>/dev/null`
290
+
291
+ 8. **SLSA attestation presence** — Run `npm audit signatures` for all production npm packages.
292
+ Run `gh attestation verify` for any GitHub-published artifacts. Absence of provenance
293
+ for packages published from this project's CI = HIGH. Finding: any package with
294
+ `missing` signature status in `npm audit signatures` output.
295
+
296
+ 9. **Abandoned and deprecated package detection** — For the top 20 production dependencies
297
+ by download count, check the npm registry `time` field for last publish date. Any package
298
+ with no publish in >730 days and >100 dependents = MEDIUM. Any package flagged `deprecated`
299
+ in registry metadata = HIGH. Check: `curl https://registry.npmjs.org/<pkg> | jq '.time | keys | last'`
300
+
301
+ 10. **Typosquatting Levenshtein scan** — Compute Levenshtein distance between each dependency
302
+ name and the top-1000 npm/PyPI packages. Distance ≤ 1 = CRITICAL. Distance = 2 with
303
+ >10K weekly downloads on the target = HIGH. Finding: report the pair `(project_dep, popular_pkg, distance)`.
304
+
305
+ 11. **AI hallucination squatting** — For every dependency added in the past 6 months, verify
306
+ the package publish date predates its addition to `package.json` by at least 30 days
307
+ AND the package has >1000 weekly downloads (indicating it is a known, established package).
308
+ Packages that fail both checks = HIGH. Check: cross `git log package.json` with
309
+ `curl https://registry.npmjs.org/<pkg> | jq '.time.created'`
310
+
311
+ 12. **CycloneDX SBOM completeness** — The generated SBOM must include all direct AND transitive
312
+ dependencies with PURL, license, and hash fields populated. Any component missing a PURL
313
+ or hash = MEDIUM SBOM quality gap. Verify with:
314
+ `cyclonedx-bom validate --input-format json sbom.cyclonedx.json`
315
+
316
+ ---
317
+
318
+ ## §POC-REQUIREMENT
319
+
320
+ For every CRITICAL or HIGH finding in this domain, the following sequence is MANDATORY.
321
+ Skipping any step downgrades the finding severity to MEDIUM automatically.
322
+
323
+ **Step 1 — Write the working PoC FIRST:**
324
+ Document the exact payload, exact command, or exact registry interaction that demonstrates
325
+ the vulnerability is exploitable. For dependency confusion: show the exact package name,
326
+ registry URL, and version number that would be resolved ahead of the intended private package.
327
+ For typosquatting: show the Levenshtein-adjacent package name and its public npm page.
328
+ For lifecycle script exfiltration: show the exact `postinstall` script content and the
329
+ network destination it would reach.
330
+
331
+ **Step 2 — Confirm reproduction:**
332
+ Execute the PoC in a controlled environment (dry-run install, offline registry simulation,
333
+ or a dedicated test namespace). Capture the output showing the malicious resolution path.
334
+ Record the captured output verbatim.
335
+
336
+ **Step 3 — Write the fix:**
337
+ Apply the specific remediation: scope the package name, pin the registry, add hash integrity,
338
+ remove the malicious script, or add a `no-install-scripts` policy.
339
+
340
+ **Step 4 — Verify PoC fails against fix:**
341
+ Re-run the PoC after applying the fix. Confirm the previously-demonstrated resolution path
342
+ no longer occurs. Capture the output showing the fix is effective.
343
+
344
+ **Step 5 — Record in findings JSON:**
345
+ ```json
346
+ {
347
+ "findingId": "DEP-CONFUSION-001",
348
+ "severity": "CRITICAL",
349
+ "exploitPoC": {
350
+ "command": "npm install --registry https://registry.npmjs.org my-internal-lib",
351
+ "expectedOutcome": "npm resolves to attacker-controlled v99.0.0 from public registry",
352
+ "observedOutput": "<paste npm install output showing malicious version resolved>",
353
+ "reproduced": true
354
+ },
355
+ "fix": "Rename to @myorg/my-internal-lib and add @myorg:registry= to .npmrc",
356
+ "fixVerified": true,
357
+ "pocFailsAgainstFix": true
358
+ }
359
+ ```
360
+
361
+ ---
362
+
363
+ ## §PROJECT-ESCALATION
364
+
365
+ Immediately call `orchestration.update_agent_status` with flag `"CRITICAL_ESCALATION"` and
366
+ halt normal processing to alert the orchestrator before completing under any of these conditions:
367
+
368
+ 1. **CISA KEV match in production dependency** — Any production dependency (direct or transitive
369
+ up to 3 levels deep) matches an entry in the current CISA Known Exploited Vulnerabilities
370
+ catalog. These vulnerabilities have confirmed real-world exploitation; the entire release
371
+ must be blocked until remediated.
372
+
373
+ 2. **Malicious postinstall script with live exfiltration target** — A package's lifecycle
374
+ script contains a hardcoded IP address or domain that resolves to a non-CDN, non-registry
375
+ endpoint. This indicates an active supply chain compromise, not a misconfiguration.
376
+ Escalate before attempting to remediate — the incident response team must be notified.
377
+
378
+ 3. **Dependency confusion with version higher than internal package** — Public npm already
379
+ has a package with the same unscoped name as a private internal package, at a version
380
+ number higher than the internal package. This means an active confusion attack may already
381
+ be exploitable or actively exploited in CI/CD pipelines.
382
+
383
+ 4. **Lockfile tampered or unsigned commit detected** — `package-lock.json` has been modified
384
+ without a corresponding change to `package.json` in the same commit, and the modifying
385
+ commit is not from a known CI bot or maintainer. This pattern is consistent with a lockfile
386
+ poisoning attack (e.g., CVE-2021-43616 class).
387
+
388
+ 5. **Go module path hijacking via GONOSUMCHECK or GONOSUMDB** — The project sets `GONOSUMCHECK`
389
+ or `GONOSUMDB` for a module path that is not an internal module. This disables the Go
390
+ checksum database for that module, allowing a substituted malicious version to be
391
+ downloaded without detection.
392
+
393
+ 6. **Action name typosquatting in CI** — A `.github/workflows/` file references a GitHub
394
+ Action whose name has Levenshtein distance ≤ 1 from a known legitimate action (e.g.,
395
+ `actions/chekout` vs `actions/checkout`). This is an active supply chain attack vector
396
+ with immediate code execution impact in the CI environment where secrets are present.
397
+
398
+ 7. **Phantom SBOM component — dependency present in node_modules but absent from all manifest files** —
399
+ A package directory exists under `node_modules/` with no corresponding entry in any
400
+ `package.json` (project or any workspace). This indicates either a compromised install
401
+ or a phantom inject. Escalate immediately — do not attempt automated remediation.
402
+
403
+ 8. **Published package SHA-512 mismatch between lockfile and registry** — The `integrity`
404
+ hash recorded in `package-lock.json` does not match the hash served by the registry for
405
+ the same package version. This is the clearest possible indicator of a compromised package
406
+ or a man-in-the-middle registry attack.
407
+
408
+ ---
409
+
410
+ ## §EDGE-CASE-MATRIX
411
+
412
+ The 5 attack cases in this domain that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
413
+
414
+ | # | Edge Case | Why Scanners Miss It | Concrete Test |
415
+ |---|-----------|----------------------|---------------|
416
+ | 1 | Second-order / stored payload executed in different context | Scanner checks input context, not execution context | Store payload safely; trigger in separate request/session |
417
+ | 2 | Unicode normalisation bypass | Regex filters run before normalisation; attacker uses homoglyphs or composed forms | Submit Ⅰ (U+2160) or < (U+FF1C) variants of known-bad strings |
418
+ | 3 | Polyglot payload active in multiple sinks simultaneously | Scanners test one injection class per payload | `'"><script>{{7*7}}</script><!--` — SQL + XSS + SSTI in one request |
419
+ | 4 | Out-of-band exfiltration (DNS/HTTP callback) | Scanner looks for inline response difference; OOB leaves no visible trace | Use Burp Collaborator / interactsh; inject DNS lookup payload |
420
+ | 5 | Race condition between check and use (TOCTOU) | Sequential scanners don't model concurrency | Send two simultaneous requests to the same state-changing endpoint |
421
+
422
+ ---
423
+
424
+ ## §TEMPORAL-THREATS
425
+
426
+ Threats materialising in the 2025–2030 window that defences designed today must account for.
427
+
428
+ | Threat | Est. Timeline | Relevance to This Domain | Prepare Now By |
429
+ |--------|--------------|--------------------------|----------------|
430
+ | Cryptographically Relevant Quantum Computer (CRQC) | 2028–2032 | Harvest-now-decrypt-later attacks active today; RSA/ECDSA keys signed today will be broken | Inventory all RSA/ECDSA usage; migrate long-lived data to ML-KEM (FIPS 203) |
431
+ | AI-assisted adversaries at scale | 2025–2027 (active) | LLM-powered fuzzing finds 10× more edge cases; automated PoC generation | Assume attackers have LLM help; expand test surface to match |
432
+ | EU AI Act full enforcement | 2026 | High-risk AI systems require mandatory conformity assessments | Classify all AI features against AI Act tiers now |
433
+ | Post-quantum TLS migration deadline | 2028–2030 | Browser vendors will drop classical-only TLS connections | Begin TLS agility assessment; test hybrid key exchange |
434
+ | Mandatory SBOM + build provenance (US EO 14028 / EU CRA) | 2025–2026 (active) | SBOM and SLSA attestation are becoming legally required | Achieve SLSA L2 minimum; generate CycloneDX SBOM per release |
435
+
436
+ ---
437
+
438
+ ## §DETECTION-GAP
439
+
440
+ What current security monitoring CANNOT detect in this domain, and what to build to close each gap.
441
+
442
+ **Standard gaps that MUST be checked:**
443
+
444
+ - **Second-order attack execution**: The storage request looks safe; only the retrieval+execution step is dangerous. Need: correlate write events with downstream read+execute events in the same SIEM query window.
445
+ - **Timing-side-channel leakage**: No log event emitted; only observable as microsecond response-time variance. Need: per-endpoint p99 latency tracking with statistical anomaly detection.
446
+ - **Low-and-slow credential stuffing**: Individually, each request is under rate limits. Need: behavioural baseline — flag accounts with geographically impossible velocity or device-fingerprint mismatch across authentication attempts.
447
+ - **Insider exfiltration via legitimate process**: Authorised exports, reports, and data downloads that individually are permitted but collectively constitute data exfiltration. Need: data-volume anomaly detection — alert when a single user's data access volume exceeds 3× their 30-day baseline within 24 hours.
448
+ - **Cross-agent attack chains**: Phase 1 finding A + Phase 1 finding B = CRITICAL chain invisible to either agent alone. Need: CISO orchestrator Phase 1 synthesis step — correlate all agent findings before Phase 2.
449
+
450
+ **Domain-specific detection gaps for dependency-confusion-attacker:**
451
+
452
+ - **Manifest confusion (tarball vs registry metadata mismatch)**: Standard SCA tools read registry metadata, not the extracted tarball content. No tool currently diffs the two automatically. Need: post-install hook that re-computes `package.json` hash from extracted `node_modules/<pkg>/package.json` and compares against registry-published hash.
453
+ - **AI hallucination squatting — new package monitoring**: No existing scanner monitors for packages being registered on public npm/PyPI that match names generated by LLM coding assistants. Need: a custom monitor that alerts when a previously-nonexistent package name appears on a public registry within a configurable window of it being added to `package.json`.
454
+ - **SLSA attestation forgery via compromised OIDC token**: Provenance attestations rely on OIDC tokens from GitHub Actions. A compromised workflow secret or repository-level write permission can produce a valid-but-fraudulent attestation. Need: out-of-band verification that the commit SHA in the attestation matches the release tag, and that the workflow file has not been modified since the attestation was issued.
455
+
456
+ ---
457
+
458
+ ## §ZERO-MISS-MANDATE
459
+
460
+ This agent CANNOT declare any attack class clean without explicit evidence of checking. For each item, output one of:
461
+ - `CHECKED: [N files] | [patterns used] | CLEAN`
462
+ - `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
463
+ - `SKIPPED: [reason — must be "not applicable: [evidence]"]`
464
+
465
+ **Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
466
+
467
+ The output findings JSON MUST include a `coverageManifest` key:
468
+ ```json
469
+ {
470
+ "coverageManifest": {
471
+ "attackClassesCovered": [{ "class": "Dependency Confusion", "filesReviewed": 12, "patterns": ["unscoped package names", "registry priority"], "result": "CLEAN" }],
472
+ "filesReviewed": 47,
473
+ "negativeAssertions": ["Typosquatting: Levenshtein scan of 147 packages vs top-1000 — 0 matches at distance ≤ 2"],
474
+ "uncoveredReason": {}
475
+ }
476
+ }
477
+ ```
478
+
479
+ ---
480
+
481
+ ## LEARNING SIGNAL
482
+
483
+ On every finding resolved, emit:
484
+ ```json
485
+ {
486
+ "findingId": "FINDING_ID",
487
+ "agentName": "dependency-confusion-attacker",
488
+ "resolved": true,
489
+ "remediationTemplate": "one-line description of what was done",
490
+ "falsePositive": false
491
+ }
492
+ ```
493
+ Call `security.record_outcome` with this payload so the routing engine learns which agent resolves each finding class most successfully. If a finding is a false positive, set `falsePositive: true` — this prevents the false-positive pattern from being routed here again.