security-mcp 1.1.4 → 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.
- package/README.md +116 -264
- package/defaults/checklists/ai.json +20 -1
- package/defaults/checklists/api.json +35 -1
- package/defaults/checklists/infra.json +34 -1
- package/defaults/checklists/mobile.json +23 -1
- package/defaults/checklists/payments.json +15 -1
- package/defaults/checklists/web.json +11 -1
- package/defaults/security-policy.json +2 -2
- package/dist/cli/index.js +0 -0
- package/dist/gate/baseline.js +82 -7
- package/dist/gate/catalog.js +10 -2
- package/dist/gate/checks/ai.js +757 -39
- package/dist/gate/checks/auth-deep.js +920 -216
- package/dist/gate/checks/business-logic.js +751 -0
- package/dist/gate/checks/ci-pipeline.js +399 -4
- package/dist/gate/checks/crypto.js +423 -2
- package/dist/gate/checks/dependencies.js +571 -15
- package/dist/gate/checks/graphql.js +201 -19
- package/dist/gate/checks/infra.js +246 -1
- package/dist/gate/checks/injection-deep.js +827 -184
- package/dist/gate/checks/k8s.js +114 -1
- package/dist/gate/checks/mobile-android.js +917 -3
- package/dist/gate/checks/mobile-ios.js +797 -5
- package/dist/gate/checks/required-artifacts.js +194 -0
- package/dist/gate/checks/runtime.js +178 -0
- package/dist/gate/checks/secrets.js +244 -13
- package/dist/gate/checks/supply-chain-deep.js +787 -0
- package/dist/gate/checks/web-nextjs.js +572 -48
- package/dist/gate/diff.js +17 -5
- package/dist/gate/evidence.js +8 -1
- package/dist/gate/exceptions.js +131 -9
- package/dist/gate/policy.js +280 -131
- package/dist/mcp/audit-chain.js +122 -28
- package/dist/mcp/auth.js +169 -0
- package/dist/mcp/learning.js +129 -4
- package/dist/mcp/model-router.js +158 -21
- package/dist/mcp/orchestration.js +186 -51
- package/dist/mcp/server.js +337 -53
- package/dist/repo/fs.js +24 -1
- package/dist/repo/search.js +31 -6
- package/dist/review/store.js +52 -1
- package/package.json +7 -7
- package/skills/_TEMPLATE/SKILL.md +99 -0
- package/skills/advanced-dos-tester/SKILL.md +109 -0
- package/skills/agentic-loop-exploiter/SKILL.md +368 -0
- package/skills/ai-llm-redteam/SKILL.md +104 -0
- package/skills/ai-model-supply-chain-agent/SKILL.md +103 -0
- package/skills/algorithm-implementation-reviewer/SKILL.md +98 -0
- package/skills/android-penetration-tester/SKILL.md +455 -46
- package/skills/anti-replay-tester/SKILL.md +106 -0
- package/skills/appsec-code-auditor/SKILL.md +85 -0
- package/skills/artifact-integrity-analyst/SKILL.md +441 -0
- package/skills/attack-navigator/SKILL.md +467 -8
- package/skills/auth-session-hacker/SKILL.md +102 -0
- package/skills/aws-penetration-tester/SKILL.md +456 -0
- package/skills/azure-penetration-tester/SKILL.md +490 -3
- package/skills/binary-auth-validator/SKILL.md +111 -0
- package/skills/bot-detection-specialist/SKILL.md +109 -0
- package/skills/business-logic-attacker/SKILL.md +231 -0
- package/skills/capec-code-mapper/SKILL.md +84 -0
- package/skills/cert-pin-rotation-specialist/SKILL.md +112 -0
- package/skills/cicd-pipeline-hijacker/SKILL.md +405 -0
- package/skills/ciso-orchestrator/SKILL.md +454 -43
- package/skills/cloud-infra-specialist/SKILL.md +118 -0
- package/skills/compliance-gap-analyst/SKILL.md +422 -0
- package/skills/compliance-grc/SKILL.md +85 -0
- package/skills/compliance-lifecycle-tracker/SKILL.md +84 -0
- package/skills/credential-stuffing-specialist/SKILL.md +102 -0
- package/skills/crypto-pki-specialist/SKILL.md +87 -0
- package/skills/csa-ccm-mapper/SKILL.md +84 -0
- package/skills/csf2-governance-mapper/SKILL.md +84 -0
- package/skills/deep-link-fuzzer/SKILL.md +109 -0
- package/skills/dependency-confusion-attacker/SKILL.md +415 -0
- package/skills/device-integrity-aggregator/SKILL.md +108 -0
- package/skills/dos-resilience-tester/SKILL.md +97 -0
- package/skills/dread-scorer/SKILL.md +84 -0
- package/skills/egress-policy-enforcer/SKILL.md +99 -0
- package/skills/evidence-collector/SKILL.md +98 -0
- package/skills/file-upload-attacker/SKILL.md +109 -0
- package/skills/gcp-penetration-tester/SKILL.md +459 -2
- package/skills/git-history-secret-scanner/SKILL.md +106 -0
- package/skills/iam-privesc-graph-builder/SKILL.md +152 -0
- package/skills/incident-responder/SKILL.md +111 -0
- package/skills/injection-specialist/SKILL.md +102 -0
- package/skills/ios-security-auditor/SKILL.md +282 -0
- package/skills/json-ambiguity-tester/SKILL.md +0 -0
- package/skills/k8s-container-escaper/SKILL.md +384 -0
- package/skills/key-management-lifecycle-analyst/SKILL.md +98 -0
- package/skills/kill-switch-engineer/SKILL.md +102 -0
- package/skills/linddun-privacy-analyst/SKILL.md +102 -0
- package/skills/logic-race-fuzzer/SKILL.md +443 -0
- package/skills/mobile-api-network-attacker/SKILL.md +421 -0
- package/skills/mobile-binary-hardener/SKILL.md +102 -0
- package/skills/mobile-security-specialist/SKILL.md +85 -0
- package/skills/mobile-webview-auditor/SKILL.md +96 -0
- package/skills/model-extraction-attacker/SKILL.md +219 -0
- package/skills/multipart-abuse-tester/SKILL.md +84 -0
- package/skills/oauth-pkce-specialist/SKILL.md +104 -0
- package/skills/parser-exhaustion-tester/SKILL.md +142 -0
- package/skills/pentest-infra/SKILL.md +98 -0
- package/skills/pentest-social/SKILL.md +201 -0
- package/skills/pentest-team/SKILL.md +87 -0
- package/skills/pentest-web-api/SKILL.md +98 -0
- package/skills/privacy-flow-analyst/SKILL.md +234 -0
- package/skills/prompt-injection-specialist/SKILL.md +394 -0
- package/skills/quantum-migration-planner/SKILL.md +96 -0
- package/skills/rag-poisoning-specialist/SKILL.md +358 -0
- package/skills/registry-mirror-enforcer/SKILL.md +84 -0
- package/skills/rotation-validation-agent/SKILL.md +112 -0
- package/skills/samm-assessor/SKILL.md +85 -0
- package/skills/secrets-mask-bypass-tester/SKILL.md +100 -0
- package/skills/senior-security-engineer/SKILL.md +167 -0
- package/skills/serialization-memory-attacker/SKILL.md +332 -0
- package/skills/session-timeout-tester/SKILL.md +161 -0
- package/skills/slsa-level3-enforcer/SKILL.md +112 -0
- package/skills/slsa-provenance-enforcer/SKILL.md +102 -0
- package/skills/ssrf-detection-validator/SKILL.md +108 -0
- package/skills/step-up-auth-enforcer/SKILL.md +84 -0
- package/skills/stride-pasta-analyst/SKILL.md +420 -0
- package/skills/supply-chain-devsecops/SKILL.md +98 -0
- package/skills/threat-infrastructure-analyst/SKILL.md +84 -0
- package/skills/threat-modeler/SKILL.md +85 -0
- package/skills/tls-certificate-auditor/SKILL.md +573 -18
- package/skills/token-reuse-detector/SKILL.md +95 -0
- package/skills/trike-risk-modeler/SKILL.md +84 -0
- package/skills/unicode-homograph-tester/SKILL.md +84 -0
- package/skills/waf-rule-lifecycle-agent/SKILL.md +97 -0
- package/skills/webhook-security-tester/SKILL.md +102 -0
- package/skills/zero-trust-architect/SKILL.md +109 -0
|
@@ -193,3 +193,109 @@ const paymentIntent = await stripe.paymentIntents.create(
|
|
|
193
193
|
- `requiredActions`: ordered action list
|
|
194
194
|
- `complianceImpact`: framework mappings
|
|
195
195
|
- `beyondSkillMd`: true if finding goes beyond the SKILL.md mandate
|
|
196
|
+
- `intelligenceForOtherAgents`: structured hints for downstream agents (see schema below)
|
|
197
|
+
|
|
198
|
+
Every findings JSON MUST include `intelligenceForOtherAgents`:
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"intelligenceForOtherAgents": {
|
|
202
|
+
"forPentestTeam": [{ "type": "HIGH_VALUE_TARGET", "description": "JWT with no jti and 24h expiry — stolen token has full replay window", "exploitHint": "Capture token from network log; replay raw Authorization header until expiry" }],
|
|
203
|
+
"forCryptoSpecialist": [{ "type": "CRYPTO_WEAKNESS_REFERENCE", "algorithm": "HMAC-SHA256 webhook signature without timestamp binding", "location": "src/webhooks/handler.ts" }],
|
|
204
|
+
"forCloudSpecialist": [{ "type": "SSRF_TO_CLOUD_CHAIN", "ssrfLocation": "Replay of signed S3 presigned URL beyond expiry window via missing server-side nonce check", "escalationPath": "Replayed presigned URL → S3 read of other-tenant objects if bucket policy is broad" }],
|
|
205
|
+
"forComplianceGrc": [{ "type": "COMPLIANCE_BLOCKER", "frameworks": ["PCI-DSS Req 8.3.9", "SOC2 CC6.1"], "releaseBlock": true }]
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## §EDGE-CASE-MATRIX
|
|
211
|
+
|
|
212
|
+
The 5 anti-replay attack cases that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
|
|
213
|
+
|
|
214
|
+
| # | Edge Case | Why Scanners Miss It | Concrete Test |
|
|
215
|
+
|---|-----------|----------------------|---------------|
|
|
216
|
+
| 1 | JWT replay after logout via a second session | Revocation check is scoped to the session that issued the token; a token captured before logout on device A remains valid on device B until natural expiry | Issue JWT on session A; log out session A; replay raw `Authorization: Bearer <token>` from a fresh client — should reject with 401 |
|
|
217
|
+
| 2 | Webhook event ID collision across environments | Dev and staging share the same event-ID namespace; seen-nonce table is not environment-scoped, so a prod event ID replayed in staging is silently dropped (or vice-versa) | Send a webhook with `id=evt_prod_123` to the staging endpoint; verify the nonce store is keyed as `env:eventId`, not bare `eventId` |
|
|
218
|
+
| 3 | OAuth authorization code reuse on clock-skew boundary | Code was issued at T; validator uses server clock T+6s; 5-minute code window has expired but the off-by-one in `<=` vs `<` accepts it; a second use 1 ms later also succeeds | Replay the same authorization code twice in rapid succession from different IPs — both should succeed if the comparison is `exp >= now` instead of `exp > now` |
|
|
219
|
+
| 4 | SAML assertion replay via XML signature wrapping | The signature is valid on the outer element; a scanner checks signature validity, not that the signed element and the processed element are the same node | Use a signature-wrapping tool (e.g., saml-raider) to duplicate the assertion node; submit; verify the IdP or SP rejects a duplicate `InResponseTo` or missing `jti`/`ID` tracking |
|
|
220
|
+
| 5 | Idempotency key fixation by attacker-controlled client | Attacker knows the key pattern (`userId_orderId_timestamp`); they pre-send a request with the same predicted key and a lower amount; the legitimate retry is deduplicated against the fraudulent first request | Generate the idempotency key server-side using a cryptographically random component the client cannot predict; confirm client-supplied keys are rejected or ignored |
|
|
221
|
+
|
|
222
|
+
## §TEMPORAL-THREATS
|
|
223
|
+
|
|
224
|
+
Threats materialising in the 2025–2030 window that anti-replay defences designed today must account for.
|
|
225
|
+
|
|
226
|
+
| Threat | Est. Timeline | Relevance to Anti-Replay | Prepare Now By |
|
|
227
|
+
|--------|--------------|--------------------------|----------------|
|
|
228
|
+
| Cryptographically Relevant Quantum Computer (CRQC) | 2028–2032 | HMAC-SHA256 webhook signatures and JWT HMAC-HS256 are not broken by Shor's algorithm, but RSA/ECDSA-signed JWTs (RS256, ES256) will be; captured tokens signed today can be forged in the post-CRQC window | Inventory all RS256/ES256 JWTs; migrate long-lived signing keys to ML-DSA (FIPS 204); prefer short-expiry tokens to minimise the harvest-now-replay-later window |
|
|
229
|
+
| AI-assisted token capture and replay at scale | 2025–2027 (active) | LLM-assisted attack tooling automates intercepting tokens from mobile app traffic, browser storage, and log files at scale — then bulk-replays them | Enforce jti tracking in Redis with per-token revocation; rotate signing keys on a 90-day schedule; alert on >3 concurrent sessions per user |
|
|
230
|
+
| WebAuthn / Passkey widespread adoption | 2025–2026 | As passkeys replace passwords, the replay attack surface shifts to the challenge-response nonce in the WebAuthn assertion; implementations that reuse challenges are trivially exploited | Validate `challenge` in every WebAuthn assertion against a server-side nonce store with 60-second TTL; never accept a challenge not issued by your server |
|
|
231
|
+
| EU AI Act full enforcement | 2026 | Auth systems powering high-risk AI features must demonstrate replay protection as part of conformity assessment | Document anti-replay controls in system-security plan; map to AI Act Article 9 risk management requirements |
|
|
232
|
+
| Mandatory SBOM + build provenance (US EO 14028 / EU CRA) | 2025–2026 (active) | Replay protection libraries (jose, jsonwebtoken) must appear in SBOM with pinned versions; outdated versions with CVEs become compliance blockers | Generate CycloneDX SBOM per release; track CVE status for all JWT/crypto dependencies; auto-alert on new CVEs in jose, jsonwebtoken, passport-jwt |
|
|
233
|
+
|
|
234
|
+
## §DETECTION-GAP
|
|
235
|
+
|
|
236
|
+
What current security monitoring CANNOT detect in anti-replay attacks, and what to build to close each gap.
|
|
237
|
+
|
|
238
|
+
**Gaps that MUST be checked:**
|
|
239
|
+
|
|
240
|
+
- **jti reuse across microservices with separate Redis clusters**: Each service validates the JWT signature but checks jti in its own local cache; a token can be replayed once per service. Standard SIEM only sees individual service auth events, not cross-service jti fan-out. Need: centralised jti revocation store (shared Redis Sentinel or distributed cache) with a cross-service read; SIEM query correlating the same `jti` value appearing in auth logs for more than one distinct service within the token's validity window.
|
|
241
|
+
|
|
242
|
+
- **Webhook replay within the timestamp tolerance window**: A 5-minute tolerance window is standard (Stripe uses 300 s). An attacker who captures a signed webhook can replay it up to 299 seconds later and pass all checks if the event-ID nonce store is not consulted. Standard WAF and signature-validation logs show "signature valid" — they do not log nonce-store hits. Need: explicit log event `webhook.nonce_check` (pass/fail) emitted after the nonce lookup, separate from the signature-validation log event; alert on any `nonce_check=fail` that is not preceded by a `signature=fail`.
|
|
243
|
+
|
|
244
|
+
- **OAuth PKCE code_verifier brute-force**: The authorization code is captured (e.g., via redirect-URI mismatch); the attacker then brute-forces short `code_verifier` values. No rate limiting exists on the token endpoint in many implementations. Standard auth logs show token endpoint 400s but not the pattern of repeated attempts per `code`. Need: rate limit the token endpoint per `code` value (max 3 attempts); alert on >1 failed token exchange for the same `code`.
|
|
245
|
+
|
|
246
|
+
- **Idempotency key exhaustion / collision DoS**: Attacker sends many requests with the same idempotency key but varying payloads to fill the deduplication store and force legitimate retries to be silently dropped. No log event emitted for dropped-as-duplicate requests in most payment libraries. Need: log every idempotency deduplication event with original request hash vs current request hash; alert when a key is reused with a *different* payload (indicates either a bug or an attack).
|
|
247
|
+
|
|
248
|
+
- **Cross-agent finding chains invisible to single-agent review**: A missing `jti` finding (anti-replay-tester) combined with a SSRF finding (ssrf-scanner) could allow an attacker to obtain a valid JWT from an internal metadata service and replay it externally. Neither agent alone sees this chain. Need: CISO orchestrator Phase 1 synthesis step — correlate anti-replay findings with credential-exposure findings before Phase 2 penetration testing.
|
|
249
|
+
|
|
250
|
+
## §ZERO-MISS-MANDATE
|
|
251
|
+
|
|
252
|
+
This agent CANNOT declare any anti-replay attack class clean without explicit evidence of checking. For each item, output one of:
|
|
253
|
+
- `CHECKED: [N files] | [patterns used] | CLEAN`
|
|
254
|
+
- `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
|
|
255
|
+
- `SKIPPED: [reason — must be "not applicable: [evidence]"]`
|
|
256
|
+
|
|
257
|
+
**Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
|
|
258
|
+
|
|
259
|
+
Attack classes that MUST be covered:
|
|
260
|
+
|
|
261
|
+
| Class | Grep Patterns | Expected Finding ID if Vulnerable |
|
|
262
|
+
|-------|--------------|-----------------------------------|
|
|
263
|
+
| JWT jti tracking | `jti`, `jwt:jti:`, `seenTokens`, `usedJtis` | `ANTI_REPLAY_JWT_NO_JTI` |
|
|
264
|
+
| JWT logout revocation | `revokeToken`, `blacklist`, `redis.*jti`, `signOut` | `ANTI_REPLAY_JWT_NO_REVOCATION` |
|
|
265
|
+
| Webhook timestamp window | `WEBHOOK_TOLERANCE`, `timestamp.*300`, `t=.*,v1=` | `ANTI_REPLAY_WEBHOOK_NO_TIMESTAMP` |
|
|
266
|
+
| Webhook event-ID nonce | `seenNonces`, `processedEvents`, `eventId.*exists` | `ANTI_REPLAY_WEBHOOK_NO_NONCE` |
|
|
267
|
+
| OAuth nonce / PKCE | `nonce`, `code_verifier`, `code_challenge`, `PKCE` | `ANTI_REPLAY_OAUTH_NO_NONCE` |
|
|
268
|
+
| Payment idempotency key | `idempotencyKey`, `Idempotency-Key`, `idem` | `ANTI_REPLAY_PAYMENT_NO_IDEMPOTENCY` |
|
|
269
|
+
| SAML assertion ID tracking | `InResponseTo`, `assertionId`, `saml.*replay` | `ANTI_REPLAY_SAML_NO_ASSERTION_TRACKING` |
|
|
270
|
+
|
|
271
|
+
The output findings JSON MUST include a `coverageManifest` key:
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"coverageManifest": {
|
|
275
|
+
"attackClassesCovered": [
|
|
276
|
+
{ "class": "JWT jti tracking", "filesReviewed": 12, "patterns": ["jti", "jwt:jti:", "seenTokens"], "result": "CLEAN" },
|
|
277
|
+
{ "class": "Webhook timestamp window", "filesReviewed": 4, "patterns": ["WEBHOOK_TOLERANCE", "t=.*,v1="], "result": "1 finding, fixed" }
|
|
278
|
+
],
|
|
279
|
+
"filesReviewed": 47,
|
|
280
|
+
"negativeAssertions": [
|
|
281
|
+
"JWT jti tracking: pattern 'jti' searched across 12 auth files — present in all token-issuance paths",
|
|
282
|
+
"Payment idempotency: 'idempotencyKey' found in all 3 payment creation call sites"
|
|
283
|
+
],
|
|
284
|
+
"uncoveredReason": {}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## BEYOND SKILL.MD — MANDATORY EXPANSIONS
|
|
290
|
+
|
|
291
|
+
- **JWT Replay via Leaked Refresh Tokens in CI Logs (CVE-2023-49803 / ATT&CK T1552.001):** Long-lived refresh tokens for OAuth2 flows (e.g., GitHub Actions OIDC tokens) are inadvertently printed to CI stdout and harvested from public build logs. The refresh token is replayed hours or days later to mint new access tokens. Test by: grep CI pipeline logs for `refresh_token=`, `Bearer ey`, and `authorization_code=` patterns using `truffleHog` or `gitleaks`; then attempt to exchange a captured refresh token against the token endpoint — a finding is confirmed if the exchange succeeds after the issuing job has completed and the token has not been revoked.
|
|
292
|
+
|
|
293
|
+
- **AI-Assisted Mass JWT Replay via LLM-Powered Traffic Analysis (ATT&CK T1550.001):** Attacker uses an LLM (e.g., via the Burp AI assistant or a custom GPT-4 script) to parse gigabytes of captured HAR files, extract every `Authorization: Bearer` header, deduplicate by expiry, and queue valid tokens for parallel replay across target endpoints. The attack requires no MITM — only access to exported browser traffic or CDN access logs. Test by: export a browser HAR file containing 50+ authenticated requests; run `python jwt_harvester.py <file.har>` (open-source tool); confirm that at least one replayed token returns HTTP 200 on a state-changing endpoint rather than 401. Finding threshold: any token accepted more than once on a non-idempotent endpoint.
|
|
294
|
+
|
|
295
|
+
- **SAML Assertion Replay via XML Signature Wrapping (CVE-2017-11427 / ATT&CK T1606.002):** The SP validates the HMAC/RSA signature on the outer `<samlp:Response>` element but processes a cloned `<saml:Assertion>` node injected as a sibling. The signed element and the evaluated element are different DOM nodes — signature is valid, assertion is attacker-controlled. Affects SimpleSAMLphp, OneLogin, and custom SP implementations. Test by: use `saml-raider` (Burp extension) to perform a signature-wrapping mutation on a captured SAML response; inject a second `<saml:Assertion>` with elevated `<saml:Attribute>` values; replay to the SP's ACS endpoint — finding confirmed if the SP accepts the wrapped response and grants elevated privileges. Also verify the SP tracks `InResponseTo` and assertion `ID` attributes against a nonce store.
|
|
296
|
+
|
|
297
|
+
- **Post-Quantum Harvest-Now-Replay-Later on RS256/ES256 JWTs (NIST IR 8413 / ATT&CK T1040):** Adversaries with access to encrypted traffic archives (nation-state interceptors, long-term PCAP storage) are collecting RS256/ES256-signed JWTs today with intent to forge signatures once a Cryptographically Relevant Quantum Computer (CRQC) breaks RSA/ECDSA (~2028–2032 per NIST). A forged JWT bearing a valid-looking signature can be replayed long after the original user session — especially against services that do not enforce `jti` revocation or tight expiry windows. Test by: audit all JWT-issuing code for `algorithm: RS256` or `algorithm: ES256`; inventory key lengths (`openssl rsa -text -noout -in jwt.pem`); confirm no JWT has expiry >15 minutes. Finding threshold: any RS256/ES256 JWT with `exp - iat > 900` seconds or any service without per-token `jti` revocation is a confirmed post-quantum harvest risk.
|
|
298
|
+
|
|
299
|
+
- **WebAuthn Challenge Reuse Enabling Credential Replay (CVE-2021-41183 pattern / ATT&CK T1550.002):** Implementations that generate the WebAuthn `challenge` once per user (stored in a persistent session) rather than per-authentication ceremony allow an intercepted `authenticatorAssertionResponse` to be replayed in a new session. The server accepts the response because the stored challenge matches, even though the response was captured from a different browser context. Affects custom WebAuthn RP implementations that skip per-ceremony nonce rotation. Test by: capture a valid `authenticatorAssertionResponse` JSON blob using a MITM proxy; open a second incognito browser session; replay the captured response to the `/api/auth/webauthn/authenticate` endpoint — if the server stores the challenge in a database row (not a one-time Redis key with 60 s TTL), the replay succeeds. Finding threshold: server accepts a replayed `authenticatorAssertionResponse` more than once, or challenge TTL exceeds 120 seconds.
|
|
300
|
+
|
|
301
|
+
- **Supply Chain Replay via Compromised Idempotency Key Generation in Stripe SDK Fork (CVE-2022-24434 pattern / ATT&CK T1195.001):** A malicious or backdoored fork of `stripe-node` (or `stripe-php`) generates predictable idempotency keys based on `userId + orderId + Math.floor(Date.now() / 1000)` — a pattern that an insider or supply-chain attacker can pre-compute and pre-register with a lower payment amount. When the legitimate payment fires, Stripe deduplicates it against the attacker's pre-registered fraudulent request. Test by: run `npm audit signatures` and `npm ls stripe` to verify the installed package matches the published registry checksum; inspect the idempotency key generation function for entropy — keys must include `crypto.randomBytes(16).toString('hex')`; attempt to pre-register a Stripe `PaymentIntent` with a predicted key and then trigger the legitimate checkout flow — finding confirmed if Stripe returns the fraudulent pre-registered intent.
|
|
@@ -119,3 +119,88 @@ You cannot call `orchestration.update_agent_status("completed")` while any HIGH/
|
|
|
119
119
|
Write `.mcp/agent-runs/{agentRunId}/appsec-findings.json` following the AgentFindingsFile schema.
|
|
120
120
|
Each finding MUST include `exploitChain[]` showing step-by-step reproduction.
|
|
121
121
|
Each remediated finding MUST reference the exact file + line number changed.
|
|
122
|
+
|
|
123
|
+
Every findings JSON MUST include `intelligenceForOtherAgents`:
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"intelligenceForOtherAgents": {
|
|
127
|
+
"forPentestTeam": [{ "type": "HIGH_VALUE_TARGET", "description": "...", "exploitHint": "..." }],
|
|
128
|
+
"forCryptoSpecialist": [{ "type": "CRYPTO_WEAKNESS_REFERENCE", "algorithm": "...", "location": "..." }],
|
|
129
|
+
"forCloudSpecialist": [{ "type": "SSRF_TO_CLOUD_CHAIN", "ssrfLocation": "...", "escalationPath": "..." }],
|
|
130
|
+
"forComplianceGrc": [{ "type": "COMPLIANCE_BLOCKER", "frameworks": ["..."], "releaseBlock": true }]
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## LEARNING SIGNAL
|
|
136
|
+
|
|
137
|
+
On every finding resolved, emit:
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"findingId": "FINDING_ID",
|
|
141
|
+
"agentName": "AGENT_NAME",
|
|
142
|
+
"resolved": true,
|
|
143
|
+
"remediationTemplate": "one-line description of what was done",
|
|
144
|
+
"falsePositive": false
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
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.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## §EDGE-CASE-MATRIX
|
|
152
|
+
|
|
153
|
+
The 5 attack cases in this domain that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
|
|
154
|
+
|
|
155
|
+
| # | Edge Case | Why Scanners Miss It | Concrete Test |
|
|
156
|
+
|---|-----------|----------------------|---------------|
|
|
157
|
+
| 1 | Second-order / stored payload executed in different context | Scanner checks input context, not execution context | Store payload safely; trigger in separate request/session |
|
|
158
|
+
| 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 |
|
|
159
|
+
| 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 |
|
|
160
|
+
| 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 |
|
|
161
|
+
| 5 | Race condition between check and use (TOCTOU) | Sequential scanners don't model concurrency | Send two simultaneous requests to the same state-changing endpoint |
|
|
162
|
+
|
|
163
|
+
## §TEMPORAL-THREATS
|
|
164
|
+
|
|
165
|
+
Threats materialising in the 2025–2030 window that defences designed today must account for.
|
|
166
|
+
|
|
167
|
+
| Threat | Est. Timeline | Relevance to This Domain | Prepare Now By |
|
|
168
|
+
|--------|--------------|--------------------------|----------------|
|
|
169
|
+
| 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) |
|
|
170
|
+
| 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 |
|
|
171
|
+
| EU AI Act full enforcement | 2026 | High-risk AI systems require mandatory conformity assessments | Classify all AI features against AI Act tiers now |
|
|
172
|
+
| Post-quantum TLS migration deadline | 2028–2030 | Browser vendors will drop classical-only TLS connections | Begin TLS agility assessment; test hybrid key exchange |
|
|
173
|
+
| 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 |
|
|
174
|
+
|
|
175
|
+
## §DETECTION-GAP
|
|
176
|
+
|
|
177
|
+
What current security monitoring CANNOT detect in this domain, and what to build to close each gap.
|
|
178
|
+
|
|
179
|
+
**Standard gaps that MUST be checked:**
|
|
180
|
+
|
|
181
|
+
- **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.
|
|
182
|
+
- **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.
|
|
183
|
+
- **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.
|
|
184
|
+
- **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.
|
|
185
|
+
- **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.
|
|
186
|
+
|
|
187
|
+
## §ZERO-MISS-MANDATE
|
|
188
|
+
|
|
189
|
+
This agent CANNOT declare any attack class clean without explicit evidence of checking. For each item, output one of:
|
|
190
|
+
- `CHECKED: [N files] | [patterns used] | CLEAN`
|
|
191
|
+
- `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
|
|
192
|
+
- `SKIPPED: [reason — must be "not applicable: [evidence]"]`
|
|
193
|
+
|
|
194
|
+
**Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
|
|
195
|
+
|
|
196
|
+
The output findings JSON MUST include a `coverageManifest` key:
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"coverageManifest": {
|
|
200
|
+
"attackClassesCovered": [{ "class": "SQL Injection", "filesReviewed": 47, "patterns": ["queryRaw", "string concat"], "result": "CLEAN" }],
|
|
201
|
+
"filesReviewed": 47,
|
|
202
|
+
"negativeAssertions": ["SQL Injection: queryRaw pattern searched across 47 files — 0 matches"],
|
|
203
|
+
"uncoveredReason": {}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
@@ -66,3 +66,444 @@ and provenance. Covers §5 Supply Chain Security fully.
|
|
|
66
66
|
- Missing signing, provenance, or SBOM controls
|
|
67
67
|
- CI workflow additions to implement the missing control
|
|
68
68
|
- §5 SLSA control reference per finding
|
|
69
|
+
|
|
70
|
+
Every findings JSON MUST include `intelligenceForOtherAgents`:
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"intelligenceForOtherAgents": {
|
|
74
|
+
"forPentestTeam": [{ "type": "HIGH_VALUE_TARGET", "description": "...", "exploitHint": "..." }],
|
|
75
|
+
"forCryptoSpecialist": [{ "type": "CRYPTO_WEAKNESS_REFERENCE", "algorithm": "...", "location": "..." }],
|
|
76
|
+
"forCloudSpecialist": [{ "type": "SSRF_TO_CLOUD_CHAIN", "ssrfLocation": "...", "escalationPath": "..." }],
|
|
77
|
+
"forComplianceGrc": [{ "type": "COMPLIANCE_BLOCKER", "frameworks": ["..."], "releaseBlock": true }]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## BEYOND SKILL.MD — MANDATORY EXPANSIONS
|
|
85
|
+
|
|
86
|
+
### 1. Typosquatting & Dependency Confusion (CVE-class: supply chain namespace collision)
|
|
87
|
+
|
|
88
|
+
**Attack:** An attacker publishes a malicious package to a public registry (npm, PyPI) with a
|
|
89
|
+
name that matches an internal private package. When the build system resolves dependencies, it
|
|
90
|
+
preferentially pulls the public (malicious) version if the public version number exceeds the
|
|
91
|
+
private registry's version — the dependency confusion attack (Alex Birsan, 2021, HackerOne).
|
|
92
|
+
|
|
93
|
+
**Detection method:**
|
|
94
|
+
```bash
|
|
95
|
+
# List all package names in package.json / requirements.txt
|
|
96
|
+
# Check whether each name exists in the public registry
|
|
97
|
+
npm info <internal-package-name> --json 2>/dev/null | jq '.name'
|
|
98
|
+
# If a result is returned for an internal-only name, this is a confirmed dependency confusion risk
|
|
99
|
+
# Also check: .npmrc / pip.conf — is `--index-url` or `registry` scoped to private registry ONLY?
|
|
100
|
+
grep -r "registry" .npmrc .yarnrc .yarnrc.yml pip.conf pyproject.toml 2>/dev/null
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Finding:** Any internal package name resolvable from the public registry without explicit
|
|
104
|
+
`@scope` namespace enforcement or a registry-precedence lock constitutes a HIGH finding.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### 2. Build-Time Code Injection via Malicious CI Action (SLSA Build Integrity)
|
|
109
|
+
|
|
110
|
+
**Attack:** A referenced GitHub Actions action (`uses: org/action@v2`) resolves to a mutable
|
|
111
|
+
tag. If the action maintainer's account is compromised, a malicious commit can be pushed to
|
|
112
|
+
the same `v2` tag, causing every downstream build to execute attacker-controlled code inside
|
|
113
|
+
the trusted CI environment — identical to the SolarWinds build-time injection pattern.
|
|
114
|
+
|
|
115
|
+
**Detection method:**
|
|
116
|
+
```bash
|
|
117
|
+
# Find all GitHub Actions workflow files
|
|
118
|
+
find . -path "./.github/workflows/*.yml" -o -path "./.github/workflows/*.yaml" | \
|
|
119
|
+
xargs grep -n "uses:" | grep -v "@[0-9a-f]\{40\}"
|
|
120
|
+
# Any 'uses:' line not pinned to a full 40-character SHA is a finding
|
|
121
|
+
# Example of finding: uses: actions/checkout@v4 (mutable)
|
|
122
|
+
# Expected: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 (pinned)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Finding:** Any `uses:` reference not pinned to a full commit SHA is HIGH.
|
|
126
|
+
Reference: SLSA L2+ requires pinned, versioned action references.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
### 3. Rekor Transparency Log Tampering Detection
|
|
131
|
+
|
|
132
|
+
**Attack:** An adversary with access to a CI signing key signs a backdoored artifact and
|
|
133
|
+
publishes the signature to Sigstore's Rekor transparency log. Because the artifact is signed,
|
|
134
|
+
admission controllers approve it. The key compromise may go undetected if the log is not
|
|
135
|
+
monitored for unexpected entries against a known-good policy.
|
|
136
|
+
|
|
137
|
+
**Detection method:**
|
|
138
|
+
```bash
|
|
139
|
+
# Verify a container image's Rekor log entry matches expected workflow
|
|
140
|
+
cosign verify \
|
|
141
|
+
--certificate-identity-regexp="https://github.com/<org>/<repo>/.github/workflows/release.yml" \
|
|
142
|
+
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
|
|
143
|
+
<image>@<digest>
|
|
144
|
+
|
|
145
|
+
# Enumerate all Rekor entries for a given artifact hash
|
|
146
|
+
rekor-cli search --sha "$(sha256sum artifact.tar.gz | cut -d' ' -f1)"
|
|
147
|
+
# Unexpected entries from a non-CI identity = compromised signing key
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Finding:** Cosign identity mismatch between expected workflow URL and actual certificate
|
|
151
|
+
subject is a CRITICAL finding. Trigger §PROJECT-ESCALATION immediately.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### 4. AI-Assisted Malicious Package Detection (Emerging Threat — 2025+)
|
|
156
|
+
|
|
157
|
+
**Attack:** LLM-assisted adversaries generate syntactically legitimate but semantically
|
|
158
|
+
malicious packages that evade keyword-based scanners. Packages contain delayed-execution
|
|
159
|
+
payloads (e.g., triggered after 30 days or after N installs), encrypted C2 channels inside
|
|
160
|
+
seemingly benign HTTP requests, or steganographic payloads in bundled assets. This technique
|
|
161
|
+
was observed in the `xz-utils` backdoor (CVE-2024-3094) — a years-long social-engineering
|
|
162
|
+
and code-poisoning campaign.
|
|
163
|
+
|
|
164
|
+
**Detection method:**
|
|
165
|
+
```bash
|
|
166
|
+
# Static entropy analysis of bundled files — high entropy = potential encrypted payload
|
|
167
|
+
python3 -c "
|
|
168
|
+
import math, sys
|
|
169
|
+
data = open(sys.argv[1],'rb').read()
|
|
170
|
+
freq = {}
|
|
171
|
+
for b in data: freq[b] = freq.get(b,0)+1
|
|
172
|
+
entropy = -sum((c/len(data))*math.log2(c/len(data)) for c in freq.values())
|
|
173
|
+
print(f'Entropy: {entropy:.3f}')
|
|
174
|
+
" <file>
|
|
175
|
+
# Entropy > 7.5 bits/byte on a non-compressed file is suspicious
|
|
176
|
+
|
|
177
|
+
# Behavioral analysis: install in isolated sandbox, trace syscalls
|
|
178
|
+
strace -e trace=network,file npm install <suspicious-package> 2>&1 | grep -E "(connect|open)"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Finding:** Packages with unexplained high-entropy bundled assets, network syscalls during
|
|
182
|
+
install scripts, or `postinstall` hooks that download external resources are HIGH findings.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### 5. Post-Quantum Signature Downgrade (Emerging Threat — FIPS 204/205 transition)
|
|
187
|
+
|
|
188
|
+
**Attack:** As NIST finalises ML-DSA (FIPS 204) and SLH-DSA (FIPS 205) for code signing,
|
|
189
|
+
systems that advertise support for hybrid classical/post-quantum signatures but fall back to
|
|
190
|
+
ECDSA-only when the PQ algorithm is unavailable are vulnerable to active downgrade attacks.
|
|
191
|
+
An adversary performing a MitM on artifact delivery can strip the PQ signature layer,
|
|
192
|
+
leaving only the classical ECDSA signature — which will be breakable by a CRQC.
|
|
193
|
+
|
|
194
|
+
**Detection method:**
|
|
195
|
+
```bash
|
|
196
|
+
# Check if Cosign or in-house signing supports ML-DSA or hybrid PQ schemes
|
|
197
|
+
cosign version # Look for PQ-capable release >= 2.4 (experimental)
|
|
198
|
+
# Check signing policy for downgrade enforcement
|
|
199
|
+
grep -r "algorithm\|key-type\|signing-algorithm" cosign.yaml policy.yaml 2>/dev/null
|
|
200
|
+
# If no policy enforces PQ-only or hybrid-minimum, flag as MEDIUM (escalates to HIGH by 2027)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Finding:** No post-quantum signing capability, no PQ migration roadmap, or policies that
|
|
204
|
+
allow silent downgrade to classical-only signing is a MEDIUM finding today, escalating
|
|
205
|
+
timeline to HIGH by 2027 per NIST PQC migration guidance.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
### 6. SBOM Completeness Evasion via Indirect Dependency Omission
|
|
210
|
+
|
|
211
|
+
**Attack:** SBOMs generated by shallow tools (e.g., `npm ls --depth=0`) omit transitive
|
|
212
|
+
dependencies. A compromised transitive dependency (e.g., the `event-stream` npm incident,
|
|
213
|
+
2018) is invisible to the SBOM consumer, who believes the SBOM is complete. The US Executive
|
|
214
|
+
Order 14028 and the EU Cyber Resilience Act both require *complete* SBOMs including all
|
|
215
|
+
transitive dependencies.
|
|
216
|
+
|
|
217
|
+
**Detection method:**
|
|
218
|
+
```bash
|
|
219
|
+
# Generate full-depth SBOM and compare node count against shallow SBOM
|
|
220
|
+
syft <image> -o cyclonedx-json > sbom-full.json
|
|
221
|
+
jq '.components | length' sbom-full.json
|
|
222
|
+
|
|
223
|
+
# Compare against any checked-in SBOM
|
|
224
|
+
jq '.components | length' sbom-checked-in.json
|
|
225
|
+
|
|
226
|
+
# Diff: if full SBOM has significantly more components, shallow SBOM is incomplete
|
|
227
|
+
# Also verify: every component in the full SBOM has a valid PURL
|
|
228
|
+
jq '[.components[] | select(.purl == null or .purl == "")] | length' sbom-full.json
|
|
229
|
+
# Non-zero = components without PURL = SBOM non-compliant with CycloneDX spec
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Finding:** SBOM missing transitive dependencies, or components lacking valid PURLs, is a
|
|
233
|
+
HIGH finding under US EO 14028 §4(e) and EU CRA Article 13.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### 7. Immutable Tag Bypass via Registry API (Container Supply Chain)
|
|
238
|
+
|
|
239
|
+
**Attack:** Even when a container registry is configured with `imageTagMutability: IMMUTABLE`
|
|
240
|
+
(ECR) or equivalent, some registry APIs expose administrative endpoints that allow tag
|
|
241
|
+
reassignment under specific IAM conditions. An over-permissioned CI role or a compromised
|
|
242
|
+
registry admin credential can silently reassign an immutable tag to a different digest without
|
|
243
|
+
triggering standard audit logs, breaking the deployment assumption that the tag points to a
|
|
244
|
+
known-good image.
|
|
245
|
+
|
|
246
|
+
**Detection method:**
|
|
247
|
+
```bash
|
|
248
|
+
# ECR: verify current tag -> digest mapping and compare to build-time expected digest
|
|
249
|
+
aws ecr describe-images --repository-name <repo> \
|
|
250
|
+
--image-ids imageTag=latest \
|
|
251
|
+
--query 'imageDetails[0].imageDigest' --output text
|
|
252
|
+
|
|
253
|
+
# Cross-reference against the digest recorded in the deployment manifest or SBOM
|
|
254
|
+
grep "sha256:" deployment.yaml | head -5
|
|
255
|
+
|
|
256
|
+
# Also: check ECR repository policy for any principal with ecr:PutImage on production repos
|
|
257
|
+
aws ecr get-repository-policy --repository-name <repo> | \
|
|
258
|
+
jq '.policyText | fromjson | .Statement[] | select(.Effect=="Allow") | .Action'
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Finding:** Any IAM principal other than the designated CI role with `ecr:PutImage` or
|
|
262
|
+
`ecr:BatchDeleteImage` on a production repository is a HIGH finding. Tag digest mismatch
|
|
263
|
+
between deployment manifest and live registry is a CRITICAL finding.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## §ARTIFACT_INTEGRITY_ANALYST-CHECKLIST
|
|
268
|
+
|
|
269
|
+
1. **Mutable action references in CI:** Scan all `.github/workflows/*.yml` for `uses:` lines
|
|
270
|
+
not pinned to a 40-character commit SHA. Grep: `uses:.*@` then filter out 40-char hashes.
|
|
271
|
+
Finding: any mutable tag reference (`@v1`, `@main`, `@latest`).
|
|
272
|
+
|
|
273
|
+
2. **SLSA level determination:** Read CI pipeline definitions; identify whether a hosted build
|
|
274
|
+
service is used (L2) and whether the build platform is hardened + isolated (L3). Grep for
|
|
275
|
+
`slsa-framework/slsa-github-generator` or equivalent. Finding: L1 or L2 for production
|
|
276
|
+
release artifacts.
|
|
277
|
+
|
|
278
|
+
3. **Cosign signing step present:** Grep CI files for `cosign sign`. Verify signing occurs
|
|
279
|
+
*after* build, *before* push. Finding: no signing step, or signing occurs after push
|
|
280
|
+
(signature may not be associated with the correct digest).
|
|
281
|
+
|
|
282
|
+
4. **Admission controller enforcement:** Check Kubernetes policy files for Kyverno
|
|
283
|
+
`ImageVerification` or Gatekeeper constraints. Grep: `imageVerification`, `cosign.dev`.
|
|
284
|
+
Finding: no admission policy enforcing signature verification at deploy time.
|
|
285
|
+
|
|
286
|
+
5. **SBOM generation and publication:** Verify a `syft` or `cdxgen` step in CI that outputs
|
|
287
|
+
CycloneDX JSON. Verify SBOM is signed (`cosign attest --type cyclonedx`). Verify SBOM is
|
|
288
|
+
uploaded to Dependency-Track or equivalent. Finding: missing generation, missing signature,
|
|
289
|
+
or missing publication.
|
|
290
|
+
|
|
291
|
+
6. **Base image digest pinning:** Grep all Dockerfiles for `FROM` lines. Any `FROM` without
|
|
292
|
+
`@sha256:` is a finding. Grep: `^FROM` then check for `@sha256:`.
|
|
293
|
+
Finding: any base image pinned only by tag.
|
|
294
|
+
|
|
295
|
+
7. **Transitive SBOM completeness:** Run `syft` at full depth and compare component count to
|
|
296
|
+
any checked-in SBOM. Grep generated SBOM for components with null PURLs.
|
|
297
|
+
Finding: component count mismatch > 10% or any null PURL.
|
|
298
|
+
|
|
299
|
+
8. **Registry tag mutability:** For ECR, run `aws ecr describe-repositories` and check
|
|
300
|
+
`imageTagMutability`. For GCR/GAR, check IAM for `artifactregistry.tags.update`.
|
|
301
|
+
Finding: `imageTagMutability: MUTABLE` on any production registry.
|
|
302
|
+
|
|
303
|
+
9. **Provenance attestation in Rekor:** Run `cosign verify-attestation --type slsaprovenance`
|
|
304
|
+
against the production artifact. Verify the certificate subject matches the expected
|
|
305
|
+
GitHub Actions workflow URL. Finding: no attestation, or subject mismatch.
|
|
306
|
+
|
|
307
|
+
10. **Dependency confusion namespace collision:** For each internal package name, query the
|
|
308
|
+
public registry. Grep `.npmrc` / `pip.conf` for scoped private-registry-only enforcement.
|
|
309
|
+
Finding: internal package name resolvable from public registry without scope enforcement.
|
|
310
|
+
|
|
311
|
+
11. **Build reproducibility:** Attempt to reproduce the build from source using the recorded
|
|
312
|
+
provenance. Compare resulting artifact digest to the published digest.
|
|
313
|
+
Finding: digest mismatch = non-reproducible build = provenance cannot be trusted.
|
|
314
|
+
|
|
315
|
+
12. **Over-permissioned CI IAM role:** Review the IAM role or service account used by CI.
|
|
316
|
+
Check for write permissions beyond the designated artifact repository. Grep Terraform/IaC
|
|
317
|
+
for `ecr:*`, `artifactregistry.repositories.*`, `storage.objects.*` with wildcard actions.
|
|
318
|
+
Finding: CI role with write access to registries, buckets, or repos beyond its build scope.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## §POC-REQUIREMENT
|
|
323
|
+
|
|
324
|
+
For every CRITICAL or HIGH finding in the artifact integrity domain, the following sequence is
|
|
325
|
+
MANDATORY before the finding is recorded:
|
|
326
|
+
|
|
327
|
+
1. **Write the working PoC FIRST.** For each finding class, examples include:
|
|
328
|
+
|
|
329
|
+
- *Mutable action reference exploit:*
|
|
330
|
+
```bash
|
|
331
|
+
# Simulate tag reassignment: verify that changing the action tag resolves different code
|
|
332
|
+
git ls-remote https://github.com/actions/checkout refs/tags/v4
|
|
333
|
+
# Record the current SHA, then show what a malicious reassignment would look like
|
|
334
|
+
# (do not execute against real repos — document the mechanism and reference real incidents)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
- *Dependency confusion exploit:*
|
|
338
|
+
```bash
|
|
339
|
+
# Create a dummy package with a higher version number than the internal package
|
|
340
|
+
mkdir /tmp/confusion-poc && cd /tmp/confusion-poc
|
|
341
|
+
echo '{"name":"<internal-pkg-name>","version":"9999.0.0","main":"index.js"}' > package.json
|
|
342
|
+
echo 'console.log("DEPENDENCY CONFUSION EXECUTED");' > index.js
|
|
343
|
+
# Install in a test environment without registry scoping — confirm the public package wins
|
|
344
|
+
npm install <internal-pkg-name> --registry https://registry.npmjs.org
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
- *Mutable tag image substitution:*
|
|
348
|
+
```bash
|
|
349
|
+
# Record current digest for a mutable tag
|
|
350
|
+
docker pull <registry>/<image>:latest
|
|
351
|
+
docker inspect <registry>/<image>:latest --format='{{.Id}}'
|
|
352
|
+
# Demonstrate that a re-push with a different payload under the same tag is undetected
|
|
353
|
+
# by deployments that reference the tag rather than the digest
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
2. **Confirm the PoC reproduces the issue** in an isolated test environment. Record observed
|
|
357
|
+
impact (code execution, artifact substitution, build poisoning).
|
|
358
|
+
|
|
359
|
+
3. **Write the fix** (digest pinning, scope enforcement, registry policy, etc.).
|
|
360
|
+
|
|
361
|
+
4. **Verify the PoC fails against the fix.** Re-run the PoC steps and confirm the attack path
|
|
362
|
+
is closed.
|
|
363
|
+
|
|
364
|
+
5. **Record in findings JSON:**
|
|
365
|
+
```json
|
|
366
|
+
{
|
|
367
|
+
"findingId": "AIA-001",
|
|
368
|
+
"severity": "HIGH",
|
|
369
|
+
"exploitPoC": {
|
|
370
|
+
"steps": ["step 1 command", "step 2 command"],
|
|
371
|
+
"observedImpact": "description of what happened",
|
|
372
|
+
"pocVerified": true,
|
|
373
|
+
"fixVerified": true
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**PoC skipping = finding severity automatically downgraded to MEDIUM.**
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## §PROJECT-ESCALATION
|
|
383
|
+
|
|
384
|
+
Immediately call `orchestration.update_agent_status` with `"CRITICAL_ESCALATION"` and halt
|
|
385
|
+
normal execution flow when ANY of the following conditions are detected:
|
|
386
|
+
|
|
387
|
+
1. **Active signing key compromise:** Rekor log contains a valid signature for a production
|
|
388
|
+
artifact from a certificate identity that does not match any known CI workflow URL. This
|
|
389
|
+
indicates either a key leak or an unauthorized signing event — the entire artifact fleet
|
|
390
|
+
may be compromised.
|
|
391
|
+
|
|
392
|
+
2. **Backdoored dependency already deployed to production:** A dependency in the production
|
|
393
|
+
SBOM matches a known-malicious package hash (e.g., cross-referenced against OSS-Fuzz or
|
|
394
|
+
the OSV database) and the artifact is currently running in production. Immediate incident
|
|
395
|
+
response, not a scheduled fix.
|
|
396
|
+
|
|
397
|
+
3. **Non-reproducible build with provenance mismatch:** The signed provenance claims a
|
|
398
|
+
specific source commit and build configuration, but a reproducibility attempt produces a
|
|
399
|
+
different artifact digest. This indicates the build was tampered between source and
|
|
400
|
+
publish — a SolarWinds-class event.
|
|
401
|
+
|
|
402
|
+
4. **Registry tag reassignment detected:** The digest currently pointed to by a production
|
|
403
|
+
tag differs from the digest recorded at deployment time in the deployment manifest or
|
|
404
|
+
GitOps repo. An image has been silently swapped in production.
|
|
405
|
+
|
|
406
|
+
5. **CI pipeline exfiltrating secrets to external endpoint:** Build logs or CI network traces
|
|
407
|
+
show outbound connections to non-whitelisted external IPs or domains during the signing or
|
|
408
|
+
build step. This indicates a compromised action or poisoned build environment.
|
|
409
|
+
|
|
410
|
+
6. **Transitive dependency with RCE vulnerability (CVSS >= 9.0) in production SBOM:** The
|
|
411
|
+
SBOM cross-reference against OSV/NVD returns a critical RCE CVE for a component that is
|
|
412
|
+
loaded in the production artifact's runtime execution path (not dev-only).
|
|
413
|
+
|
|
414
|
+
7. **SLSA provenance for a production release is entirely absent:** A production artifact
|
|
415
|
+
that customers receive has no provenance attestation of any kind. In regulated environments
|
|
416
|
+
(FedRAMP, PCI DSS 4.0), this alone is a compliance blocker that may require a release
|
|
417
|
+
recall or emergency patch.
|
|
418
|
+
|
|
419
|
+
8. **Over-permissioned CI role with production write access AND recent credential rotation
|
|
420
|
+
failure:** The CI service account has not rotated credentials in over 90 days AND has write
|
|
421
|
+
access to production registries. Combined with any other finding, this represents an
|
|
422
|
+
unacceptably wide blast radius for a single compromised CI run.
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## §EDGE-CASE-MATRIX
|
|
427
|
+
|
|
428
|
+
The 5 attack cases in this domain that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
|
|
429
|
+
|
|
430
|
+
| # | Edge Case | Why Scanners Miss It | Concrete Test |
|
|
431
|
+
|---|-----------|----------------------|---------------|
|
|
432
|
+
| 1 | Second-order / stored payload executed in different context | Scanner checks input context, not execution context | Store payload safely; trigger in separate request/session |
|
|
433
|
+
| 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 |
|
|
434
|
+
| 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 |
|
|
435
|
+
| 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 |
|
|
436
|
+
| 5 | Race condition between check and use (TOCTOU) | Sequential scanners don't model concurrency | Send two simultaneous requests to the same state-changing endpoint |
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## §TEMPORAL-THREATS
|
|
441
|
+
|
|
442
|
+
Threats materialising in the 2025–2030 window that defences designed today must account for.
|
|
443
|
+
|
|
444
|
+
| Threat | Est. Timeline | Relevance to This Domain | Prepare Now By |
|
|
445
|
+
|--------|--------------|--------------------------|----------------|
|
|
446
|
+
| 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) |
|
|
447
|
+
| 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 |
|
|
448
|
+
| EU AI Act full enforcement | 2026 | High-risk AI systems require mandatory conformity assessments | Classify all AI features against AI Act tiers now |
|
|
449
|
+
| Post-quantum TLS migration deadline | 2028–2030 | Browser vendors will drop classical-only TLS connections | Begin TLS agility assessment; test hybrid key exchange |
|
|
450
|
+
| 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 |
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## §DETECTION-GAP
|
|
455
|
+
|
|
456
|
+
What current security monitoring CANNOT detect in this domain, and what to build to close each gap.
|
|
457
|
+
|
|
458
|
+
**Standard gaps that MUST be checked:**
|
|
459
|
+
|
|
460
|
+
- **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.
|
|
461
|
+
- **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.
|
|
462
|
+
- **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.
|
|
463
|
+
- **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.
|
|
464
|
+
- **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.
|
|
465
|
+
|
|
466
|
+
**Artifact-integrity-specific gaps:**
|
|
467
|
+
|
|
468
|
+
- **Silent tag reassignment in registries**: Standard CloudTrail/Audit Logs capture `PutImage` events but do not diff tag-to-digest mappings. Need: a scheduled Lambda/Cloud Function that polls each production tag's digest and alerts on any change not initiated by a known CI run.
|
|
469
|
+
- **SBOM drift between release and runtime**: The signed SBOM reflects the artifact at build time; packages installed post-deployment (e.g., via entrypoint scripts) are invisible. Need: runtime SBOM diffing using Falco or Tetragon to detect new file writes to dependency directories after container start.
|
|
470
|
+
- **Compromised transparency log entry**: Rekor is append-only but its consistency proof requires active monitoring. A client that never checks the inclusion proof can be served a forged log by a MitM. Need: automated `rekor-monitor` deployment that continuously verifies the log's consistency tree.
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## §ZERO-MISS-MANDATE
|
|
475
|
+
|
|
476
|
+
This agent CANNOT declare any attack class clean without explicit evidence of checking. For each item, output one of:
|
|
477
|
+
- `CHECKED: [N files] | [patterns used] | CLEAN`
|
|
478
|
+
- `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
|
|
479
|
+
- `SKIPPED: [reason — must be "not applicable: [evidence]"]`
|
|
480
|
+
|
|
481
|
+
**Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
|
|
482
|
+
|
|
483
|
+
The output findings JSON MUST include a `coverageManifest` key:
|
|
484
|
+
```json
|
|
485
|
+
{
|
|
486
|
+
"coverageManifest": {
|
|
487
|
+
"attackClassesCovered": [{ "class": "Mutable Action Reference", "filesReviewed": 12, "patterns": ["uses:.*@(?![0-9a-f]{40})"], "result": "CLEAN" }],
|
|
488
|
+
"filesReviewed": 47,
|
|
489
|
+
"negativeAssertions": ["Mutable action references: searched 12 workflow files — 0 unpinned references"],
|
|
490
|
+
"uncoveredReason": {}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## LEARNING SIGNAL
|
|
498
|
+
|
|
499
|
+
On every finding resolved, emit:
|
|
500
|
+
```json
|
|
501
|
+
{
|
|
502
|
+
"findingId": "FINDING_ID",
|
|
503
|
+
"agentName": "artifact-integrity-analyst",
|
|
504
|
+
"resolved": true,
|
|
505
|
+
"remediationTemplate": "one-line description of what was done",
|
|
506
|
+
"falsePositive": false
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
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.
|