security-mcp 1.1.3 → 1.1.4
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 +134 -7
- package/defaults/control-catalog.json +200 -0
- package/dist/cli/index.js +82 -5
- package/dist/cli/install.js +36 -6
- package/dist/cli/onboarding.js +6 -0
- package/dist/gate/checks/auth-deep.js +231 -0
- package/dist/gate/checks/injection-deep.js +205 -0
- package/dist/gate/policy.js +5 -1
- package/dist/mcp/server.js +271 -41
- package/package.json +1 -1
- package/prompts/SECURITY_PROMPT.md +73 -0
- package/skills/appsec-code-auditor/SKILL.md +35 -0
- package/skills/auth-session-hacker/SKILL.md +26 -0
- package/skills/injection-specialist/SKILL.md +29 -0
- package/skills/pentest-infra/SKILL.md +43 -0
- package/skills/pentest-team/SKILL.md +47 -0
- package/skills/pentest-web-api/SKILL.md +53 -0
- package/skills/senior-security-engineer/SKILL.md +203 -2
package/dist/mcp/server.js
CHANGED
|
@@ -100,7 +100,19 @@ tool("security.start_review", "Start a stateful security review run, lock the sc
|
|
|
100
100
|
headRef: headRef ?? "HEAD",
|
|
101
101
|
requiredSteps: run.requiredSteps,
|
|
102
102
|
operatingMandate: "90% fixing, 10% advisory. Write the fix. Implement the control. Enforce the policy. Do not list vulnerabilities and walk away.",
|
|
103
|
+
coverageProtocol: {
|
|
104
|
+
step0: "Enumerate ALL source files first → write .mcp/agent-runs/{runId}/coverage-manifest.json before any analysis",
|
|
105
|
+
step1: "Taint-trace every user-controlled input (req.body, req.query, event.data, etc.) to ALL sinks → write taint-map.json",
|
|
106
|
+
step2: "Negative assertion per attack class: 'ATTACK CLASS: {name} | FILES: {n}/{total} | PATTERNS: {list} | RESULT: CLEAN or N findings (N/N fixed)'",
|
|
107
|
+
step3: "Fix verification loop: re-run the triggering check after every fix — do NOT advance until VERIFIED CLEAN",
|
|
108
|
+
step4: "All HIGH/CRITICAL: FIXED with verified-clean re-run, OR formally blocked with risk-acceptance record + failing gate"
|
|
109
|
+
},
|
|
103
110
|
nextSteps: [
|
|
111
|
+
"Step 0: Enumerate ALL source files → write coverage-manifest.json before any analysis begins.",
|
|
112
|
+
"Step 1: For every user-controlled input found, trace it to ALL sinks → write taint-map.json.",
|
|
113
|
+
"After every attack class reviewed: write NEGATIVE ASSERTION confirming files checked and result.",
|
|
114
|
+
"After every fix: re-run the triggering check and confirm CLEAN before proceeding to next finding.",
|
|
115
|
+
"All findings must be FIXED (verified-clean) or BLOCKED (risk-accepted + gate failing). No open HIGH/CRITICAL at completion.",
|
|
104
116
|
"Run security.threat_model with this runId.",
|
|
105
117
|
"Run security.checklist with this runId.",
|
|
106
118
|
"Run security.run_pr_gate with this runId.",
|
|
@@ -361,22 +373,108 @@ Describe Level 0 (context) and Level 1 (process) flows in prose or embed a diagr
|
|
|
361
373
|
|---|---|---|---|---|
|
|
362
374
|
| TM-001 | | | | PENDING |
|
|
363
375
|
|
|
376
|
+
## 4b. LINDDUN Privacy Threat Analysis
|
|
377
|
+
|
|
378
|
+
| Category | Description | Threat | Mitigation |
|
|
379
|
+
|---|---|---|---|
|
|
380
|
+
| Linking | Can records across contexts be linked? | | |
|
|
381
|
+
| Identifying | Can data be traced to an individual? | | |
|
|
382
|
+
| Non-repudiation | Can users deny their actions? | | |
|
|
383
|
+
| Detecting | Can sensitive behavior be inferred from metadata? | | |
|
|
384
|
+
| Data Disclosure | Can data be exposed beyond its intended scope? | | |
|
|
385
|
+
| Unawareness | Are users unaware of data collection? | | |
|
|
386
|
+
| Non-compliance | Does the system violate regulations? | | |
|
|
387
|
+
|
|
388
|
+
## 4c. TRIKE Risk Matrix
|
|
389
|
+
|
|
390
|
+
| Actor | Action | Asset | Allowed? | Risk if Violated |
|
|
391
|
+
|---|---|---|---|---|
|
|
392
|
+
| Authenticated User | Read | Own profile | Yes | — |
|
|
393
|
+
| Authenticated User | Read | Other user profile | No | CRITICAL |
|
|
394
|
+
| Service Account | Write | Production DB | Restricted | HIGH |
|
|
395
|
+
|
|
396
|
+
## 4d. DREAD Scoring
|
|
397
|
+
|
|
398
|
+
| Threat | Damage (0-10) | Reproducibility | Exploitability | Affected Users | Discoverability | Total |
|
|
399
|
+
|---|---|---|---|---|---|---|
|
|
400
|
+
| _Threat 1_ | | | | | | |
|
|
401
|
+
|
|
402
|
+
## 4e. Attack Trees — Top 3 Critical Paths
|
|
403
|
+
|
|
404
|
+
**Goal 1: Achieve authentication bypass**
|
|
405
|
+
- OR: Exploit JWT algorithm confusion (requires: access to token + public key)
|
|
406
|
+
- AND: Obtain RS256 public key (from JWKS endpoint or source code)
|
|
407
|
+
- AND: Re-sign token as HS256 using public key as HMAC secret
|
|
408
|
+
- OR: Session fixation (requires: pre-auth request, no session regeneration)
|
|
409
|
+
|
|
410
|
+
**Goal 2: Exfiltrate PII/cardholder data**
|
|
411
|
+
- OR: IDOR via unvalidated object reference
|
|
412
|
+
- OR: SQLi / NoSQL injection in query endpoint
|
|
413
|
+
- OR: SSRF to internal data store
|
|
414
|
+
|
|
415
|
+
**Goal 3: Achieve remote code execution**
|
|
416
|
+
- OR: SSTI via template compilation from user input
|
|
417
|
+
- OR: Deserialization gadget chain (node-serialize / eval)
|
|
418
|
+
- OR: Prototype pollution → downstream exec sink
|
|
419
|
+
|
|
420
|
+
## 5. Adversary Profiles
|
|
421
|
+
|
|
422
|
+
| Profile | Goal | ATT&CK Techniques | Test Focus |
|
|
423
|
+
|---|---|---|---|
|
|
424
|
+
| APT / Nation-State | Persistent access + exfiltration | T1195, T1078, T1027 | What steps produce NO log entries? |
|
|
425
|
+
| Ransomware Group | Encrypt backups, maximize leverage | T1490, T1485, T1496 | Can attacker reach and delete backups? |
|
|
426
|
+
| Insider (DevOps) | Exfiltration or sabotage with valid creds | T1213, T1087 | What can a DevOps engineer access they shouldn't? |
|
|
427
|
+
| Script Kiddie | Quick wins via automated tools | T1190, T1595 | Does WAF/rate limiting stop nuclei/sqlmap? |
|
|
428
|
+
|
|
429
|
+
## 6. Supply Chain Threats
|
|
430
|
+
|
|
431
|
+
| Threat | Vector | Likelihood | Mitigation |
|
|
432
|
+
|---|---|---|---|
|
|
433
|
+
| Dependency confusion | Private pkg name registered on npm | | SHA-pin all deps; use npm audit |
|
|
434
|
+
| Typosquatting | Misspelled package installed | | Lock file + npm audit on CI |
|
|
435
|
+
| CI cache poisoning | Malicious action poisons build cache | | Pin actions to SHA; no cache cross-branches |
|
|
436
|
+
| Compromised upstream | Maintainer account takeover | | SBOM + Sigstore verification |
|
|
437
|
+
| Malicious maintainer | Legitimate maintainer inserts backdoor | | OpenSSF scorecard + CISA KEV monitoring |
|
|
438
|
+
| pwn-request | pull_request_target with head code | | Explicit head_ref check; no auto-use of forked code |
|
|
439
|
+
|
|
364
440
|
## 11. Pre-Release Checklist (Section 22E)
|
|
365
441
|
|
|
366
442
|
- [ ] Threat model reviewed by security-designated reviewer
|
|
367
443
|
- [ ] All SAST/SCA/IaC/container scan gates pass
|
|
368
444
|
- [ ] Auth and authorization logic reviewed
|
|
369
|
-
- [ ] Secrets handling reviewed
|
|
445
|
+
- [ ] Secrets handling reviewed — no hardcoded secrets
|
|
370
446
|
- [ ] Input validation present on all new inputs (server-side confirmed)
|
|
371
|
-
- [ ] Error messages reviewed
|
|
372
|
-
- [ ] Logging confirmed
|
|
447
|
+
- [ ] Error messages reviewed — no information leakage
|
|
448
|
+
- [ ] Logging confirmed — required events logged, no PII in logs
|
|
373
449
|
- [ ] Security headers verified in staging
|
|
374
450
|
- [ ] Rate limiting confirmed on all new endpoints
|
|
375
451
|
- [ ] CORS configuration reviewed
|
|
376
452
|
- [ ] Dependencies reviewed for new CVEs
|
|
377
|
-
- [ ] Network rules reviewed
|
|
453
|
+
- [ ] Network rules reviewed — no 0.0.0.0/0, all traffic via private paths
|
|
378
454
|
- [ ] IR playbook updated if new attack surface introduced
|
|
379
455
|
- [ ] Compliance requirements addressed and documented
|
|
456
|
+
|
|
457
|
+
## 12. Business Logic Abuse
|
|
458
|
+
|
|
459
|
+
| Workflow | State Machine Step | Can skip? | Invariant | Test |
|
|
460
|
+
|---|---|---|---|---|
|
|
461
|
+
| _e.g. Checkout_ | Cart → Payment → Confirm | Can step 2 be skipped? | Amount must match cart total | POST /confirm without /payment |
|
|
462
|
+
| _e.g. Subscription_ | Trial → Upgrade → Active | Can upgrade be replayed? | One upgrade per user | Concurrent PATCH /upgrade |
|
|
463
|
+
|
|
464
|
+
- [ ] Full state machine mapped for all significant workflows
|
|
465
|
+
- [ ] Step-skip tests designed and executed
|
|
466
|
+
- [ ] Negative value inputs tested on all numeric fields (quantity, price, balance, seats)
|
|
467
|
+
- [ ] Concurrent request tests executed for all limit-once invariants
|
|
468
|
+
|
|
469
|
+
## 13. PoC Requirement
|
|
470
|
+
|
|
471
|
+
**Every HIGH or CRITICAL finding must have a working PoC before sign-off.**
|
|
472
|
+
|
|
473
|
+
| Finding ID | Severity | PoC Written | PoC Confirmed Working | Fix Written | Fix Verified Clean |
|
|
474
|
+
|---|---|---|---|---|---|
|
|
475
|
+
| | HIGH | [ ] | [ ] | [ ] | [ ] |
|
|
476
|
+
|
|
477
|
+
Rule: PoC must be written BEFORE the fix. After the fix, re-run the PoC and confirm it fails.
|
|
380
478
|
`;
|
|
381
479
|
if (runId) {
|
|
382
480
|
await updateReviewStep(runId, "threat_model", "completed", {
|
|
@@ -402,80 +500,212 @@ Use before every production release. All items must be checked or explicitly ris
|
|
|
402
500
|
## All Surfaces
|
|
403
501
|
|
|
404
502
|
- [ ] Threat model completed and reviewed by security-designated reviewer
|
|
405
|
-
- [ ] SAST scan results reviewed
|
|
406
|
-
- [ ] SCA scan
|
|
407
|
-
- [ ] Secrets scan clean (Trufflehog / Gitleaks)
|
|
408
|
-
- [ ] IaC scan
|
|
409
|
-
- [ ] Container scan
|
|
410
|
-
- [ ] Error messages reviewed - no stack traces, schema details, or enum leakage
|
|
411
|
-
- [ ] Logging reviewed - all required events logged; no PII, secrets, or tokens in logs
|
|
412
|
-
- [ ] Dependencies reviewed for new CVEs introduced by this change
|
|
503
|
+
- [ ] SAST scan results reviewed — all CRITICAL/HIGH findings resolved or risk-accepted with ticket
|
|
504
|
+
- [ ] SCA scan — no CRITICAL CVEs in dependencies; HIGH CVEs triaged and scheduled
|
|
505
|
+
- [ ] Secrets scan clean (Trufflehog / Gitleaks) — no credentials, tokens, or keys in source
|
|
506
|
+
- [ ] IaC scan — no HIGH/CRITICAL misconfigurations (Checkov / tfsec)
|
|
507
|
+
- [ ] Container scan — no CRITICAL CVEs with available fix (Trivy / Grype)
|
|
413
508
|
- [ ] SBOM generated for this release artifact
|
|
414
|
-
- [ ]
|
|
509
|
+
- [ ] SLSA provenance attestation generated for release artifacts
|
|
510
|
+
- [ ] Error messages reviewed — no stack traces, schema details, internal paths, or enum leakage
|
|
511
|
+
- [ ] Logging reviewed — all required events logged; no PII, secrets, or tokens in logs
|
|
512
|
+
- [ ] Dependencies reviewed for new CVEs introduced by this change
|
|
513
|
+
- [ ] CISA KEV cross-check completed for all dependency CVEs
|
|
514
|
+
- [ ] Rollback plan documented and tested (can revert within 15 minutes)
|
|
415
515
|
- [ ] IR playbook updated if a new attack surface was introduced
|
|
516
|
+
- [ ] Regression gate: previous CRITICAL/HIGH findings verified still fixed
|
|
517
|
+
- [ ] Coverage-gap disclosure: documented what this scan CANNOT catch (business logic, runtime behavior)
|
|
416
518
|
|
|
417
519
|
## Web / Frontend
|
|
418
520
|
|
|
419
|
-
- [ ] Content-Security-Policy
|
|
420
|
-
- [ ]
|
|
421
|
-
- [ ]
|
|
422
|
-
- [ ] X-
|
|
521
|
+
- [ ] Content-Security-Policy: nonce-based script control — unsafe-inline and unsafe-eval absent
|
|
522
|
+
- [ ] Content-Security-Policy: default-src 'self' with explicit allowlists for external resources
|
|
523
|
+
- [ ] HSTS: max-age=31536000; includeSubDomains; preload
|
|
524
|
+
- [ ] X-Frame-Options: DENY (or SAMEORIGIN with justification)
|
|
525
|
+
- [ ] X-Content-Type-Options: nosniff on all responses including error pages
|
|
423
526
|
- [ ] Referrer-Policy: strict-origin-when-cross-origin
|
|
424
|
-
- [ ] Permissions-Policy
|
|
425
|
-
- [ ]
|
|
426
|
-
- [ ]
|
|
427
|
-
- [ ]
|
|
428
|
-
- [ ]
|
|
527
|
+
- [ ] Permissions-Policy: camera, microphone, geolocation restricted
|
|
528
|
+
- [ ] Cross-Origin-Opener-Policy (COOP): same-origin
|
|
529
|
+
- [ ] Cross-Origin-Embedder-Policy (COEP): require-corp where SharedArrayBuffer used
|
|
530
|
+
- [ ] Cross-Origin-Resource-Policy (CORP): same-origin or same-site on API responses
|
|
531
|
+
- [ ] Trusted Types policy enforced (require-trusted-types-for 'script') — DOM XSS sinks covered
|
|
532
|
+
- [ ] No inline JavaScript or inline event handlers (onclick, onload, onerror, etc.)
|
|
533
|
+
- [ ] No dangerouslySetInnerHTML without DOMPurify sanitization
|
|
534
|
+
- [ ] All user-supplied data escaped before rendering in server-side templates
|
|
535
|
+
- [ ] document.write(), innerHTML, insertAdjacentHTML, eval() DOM sink audit completed
|
|
536
|
+
- [ ] postMessage handlers validate event.origin against explicit allowlist
|
|
537
|
+
- [ ] Subresource Integrity (SRI) on all third-party scripts and stylesheets
|
|
538
|
+
- [ ] CSRF protection on all state-changing endpoints (SameSite + CSRF tokens)
|
|
539
|
+
- [ ] Open redirect prevention: redirect targets validated against allowlist
|
|
540
|
+
- [ ] Subdomain takeover DNS audit — no dangling CNAME records to unprovisioned services
|
|
541
|
+
- [ ] HTTP request smuggling: CL/TE header normalization at proxy layer confirmed
|
|
542
|
+
- [ ] Session tokens are HttpOnly, Secure, SameSite=Strict — not localStorage
|
|
543
|
+
- [ ] Session expiry: access tokens max 15 minutes, refresh tokens rotated on use
|
|
544
|
+
- [ ] Login rate limiting: max 5 failures per IP per minute with progressive lockout
|
|
429
545
|
|
|
430
546
|
## API
|
|
431
547
|
|
|
432
|
-
- [ ] All new endpoints require authentication
|
|
433
|
-
- [ ]
|
|
434
|
-
- [ ]
|
|
435
|
-
- [ ]
|
|
436
|
-
- [ ]
|
|
437
|
-
- [ ]
|
|
438
|
-
- [ ]
|
|
548
|
+
- [ ] All new endpoints require authentication — no unauthenticated access to sensitive data
|
|
549
|
+
- [ ] JWT algorithm pinned to RS256 or ES256 in all jwt.verify() calls (CWE-327)
|
|
550
|
+
- [ ] JWT expiry enforced — access tokens max 15 minutes, refresh tokens rotated on use
|
|
551
|
+
- [ ] Authorization checked server-side for every resource operation — IDOR prevention confirmed
|
|
552
|
+
- [ ] Row-level security enforced — cross-tenant access not possible
|
|
553
|
+
- [ ] Privilege escalation paths reviewed — no client-supplied role claims accepted
|
|
554
|
+
- [ ] Session regenerated after login — session fixation prevented (CWE-384)
|
|
555
|
+
- [ ] OAuth state parameter generated and verified (CWE-352)
|
|
556
|
+
- [ ] PKCE (S256) required for all public clients and SPAs
|
|
557
|
+
- [ ] OAuth redirect_uri validated with exact equality — not includes/startsWith (CWE-601)
|
|
558
|
+
- [ ] HTTP verb tampering: PUT/DELETE on read-only resources returns 405 not 200
|
|
559
|
+
- [ ] BOPLA: PATCH/PUT handler rejects field updates beyond caller's role
|
|
560
|
+
- [ ] Input validation: server-side schema validation on all new inputs (Zod / Joi / Valibot)
|
|
561
|
+
- [ ] SQL injection: parameterized queries throughout — no raw string concat in query context
|
|
562
|
+
- [ ] NoSQL injection: user input validated before passing to MongoDB/DynamoDB filters (CWE-943)
|
|
563
|
+
- [ ] XML parsers: external entity processing disabled (XXE — CWE-611)
|
|
564
|
+
- [ ] Deserialization: no node-serialize, eval(), or new Function() on user input (CWE-502)
|
|
565
|
+
- [ ] SSTI: templates never compiled from user input (CWE-94)
|
|
566
|
+
- [ ] Prototype pollution: Zod schema validation before any object merge (CWE-1321)
|
|
567
|
+
- [ ] YAML parsing: safe/FAILSAFE schema used — not default js-yaml schema (CWE-502)
|
|
568
|
+
- [ ] Path traversal: path.join() + user input always followed by prefix check (CWE-22)
|
|
569
|
+
- [ ] Log injection: newlines stripped from user values before logging (CWE-117)
|
|
570
|
+
- [ ] CRLF injection: user values sanitized before res.setHeader() (CWE-113)
|
|
571
|
+
- [ ] Rate limiting on all new endpoints — per-user and per-IP
|
|
572
|
+
- [ ] Aggressive rate limiting on auth endpoints (login, token refresh, password reset)
|
|
573
|
+
- [ ] CORS origin allowlist reviewed — no wildcard on authenticated endpoints
|
|
574
|
+
- [ ] Request size limits enforced — no unbounded body parsing
|
|
575
|
+
- [ ] SSRF protection on server-side HTTP clients — blocks private IPs and metadata endpoints
|
|
439
576
|
- [ ] Webhook signatures verified (HMAC-SHA256 + replay protection)
|
|
440
|
-
- [ ]
|
|
577
|
+
- [ ] Mass assignment prevented — explicit field allowlists, not object spread from request body
|
|
578
|
+
- [ ] Response bodies reviewed — no internal IDs, system details, or field over-exposure (BOPLA)
|
|
579
|
+
- [ ] OpenAPI spec updated for all new endpoints
|
|
580
|
+
|
|
581
|
+
## GraphQL
|
|
582
|
+
|
|
583
|
+
- [ ] Introspection disabled in production
|
|
584
|
+
- [ ] Query depth limit enforced (max 10 or documented level)
|
|
585
|
+
- [ ] Query complexity limit enforced
|
|
586
|
+
- [ ] Batching limited (max 5 operations per request)
|
|
587
|
+
- [ ] Field-level authorization enforced — not just type-level
|
|
588
|
+
- [ ] Subscription auth enforced on WS handshake — not just on first message
|
|
441
589
|
|
|
442
590
|
## Infrastructure / Cloud
|
|
443
591
|
|
|
444
592
|
- [ ] No 0.0.0.0/0 ingress or egress rules in any firewall / security group
|
|
445
593
|
- [ ] All managed services accessed via VPC endpoints / private connectivity
|
|
446
594
|
- [ ] No world-readable storage buckets
|
|
447
|
-
- [ ] Secrets stored in secret manager
|
|
448
|
-
- [ ] IAM roles follow least privilege
|
|
595
|
+
- [ ] Secrets stored in secret manager — not in env files, CI logs, or container images
|
|
596
|
+
- [ ] IAM roles follow least privilege — no wildcard permissions
|
|
597
|
+
- [ ] No long-lived static credentials — workload identity or short-lived tokens
|
|
598
|
+
- [ ] Admin roles require MFA and are time-limited — no standing admin access
|
|
599
|
+
- [ ] New IAM roles reviewed for privilege escalation paths
|
|
449
600
|
- [ ] Network segmentation reviewed (web tier, app tier, data tier isolated)
|
|
450
601
|
- [ ] WAF rules updated if new public endpoints added
|
|
451
602
|
- [ ] Cloud audit logging confirmed for new resources
|
|
603
|
+
- [ ] IMDSv2 enforced on all EC2 instances (HttpTokens=required)
|
|
604
|
+
- [ ] S3 Block Public Access enabled at account level
|
|
605
|
+
- [ ] S3 Object Lock (WORM) on backup buckets — prevents ransomware deletion
|
|
606
|
+
- [ ] Threat detection enabled: AWS GuardDuty / GCP SCC / Azure Defender
|
|
607
|
+
- [ ] SCP blocking: public S3 creation, CloudTrail disable, IAM * wildcards
|
|
608
|
+
- [ ] CloudTrail log file integrity validation enabled
|
|
609
|
+
- [ ] Container seccomp profile applied (RuntimeDefault or stricter)
|
|
610
|
+
- [ ] Kubernetes resource limits (CPU and memory) set on all workloads
|
|
611
|
+
|
|
612
|
+
## Supply Chain / CI-CD
|
|
613
|
+
|
|
614
|
+
- [ ] All GitHub Actions pinned to full SHA — no floating tag references
|
|
615
|
+
- [ ] No pull_request_target workflow without explicit head_ref validation (pwn-request prevention)
|
|
616
|
+
- [ ] GITHUB_TOKEN permissions explicitly declared minimal — no inherited default write
|
|
617
|
+
- [ ] SLSA Level 3 provenance or equivalent documented
|
|
618
|
+
- [ ] SBOM signed with cosign — signature verified at deployment
|
|
619
|
+
- [ ] No secrets readable in CI job logs — masked and audited
|
|
620
|
+
|
|
621
|
+
## OAuth / OIDC
|
|
622
|
+
|
|
623
|
+
- [ ] PKCE with S256 code challenge required for all public clients
|
|
624
|
+
- [ ] state and nonce parameters generated and verified on every OAuth callback
|
|
625
|
+
- [ ] redirect_uri exact-match only — no prefix or includes() matching
|
|
626
|
+
- [ ] Authorization code reuse prevented — server rejects second use within validity window
|
|
627
|
+
- [ ] Token audience (aud) validated against expected service identifier
|
|
628
|
+
- [ ] Bearer token passed in Authorization header — not in URL query string
|
|
629
|
+
|
|
630
|
+
## Business Logic
|
|
631
|
+
|
|
632
|
+
- [ ] Rate-limited endpoints: every endpoint with a limit-once invariant has idempotency protection
|
|
633
|
+
- [ ] Idempotency keys required on all payment/transfer mutations
|
|
634
|
+
- [ ] Resource ownership verified on every write operation — not just on read
|
|
635
|
+
- [ ] No sequential integer IDs for user-facing resources — use UUID or opaque tokens
|
|
636
|
+
- [ ] Negative input values rejected: quantity, price, balance change, seat count all validated ≥ 0
|
|
637
|
+
- [ ] Race condition test executed for any balance/quota/inventory limit (concurrent requests)
|
|
638
|
+
|
|
639
|
+
## Serialization / Injection
|
|
640
|
+
|
|
641
|
+
- [ ] XXE prevented: XML parsers disable external entities (processEntities:false)
|
|
642
|
+
- [ ] SSTI prevented: no template compilation from user input
|
|
643
|
+
- [ ] No eval(), new Function(), or setTimeout(string) with user-controlled content
|
|
644
|
+
- [ ] No unsafe YAML.load() — FAILSAFE_SCHEMA or yaml.safeLoad() used
|
|
645
|
+
- [ ] No node-serialize or other gadget-chain-capable deserialization library on user input
|
|
646
|
+
- [ ] Prototype pollution mitigated: Zod validation before all object merges
|
|
647
|
+
- [ ] Open redirect blocked: all res.redirect() targets validated against allowlist
|
|
648
|
+
- [ ] CRLF injection blocked: response headers sanitized before setting
|
|
452
649
|
|
|
453
650
|
## Mobile
|
|
454
651
|
|
|
455
|
-
- [ ] iOS: NSAllowsArbitraryLoads is false
|
|
652
|
+
- [ ] iOS: NSAllowsArbitraryLoads is false — ATS strictly enforced
|
|
653
|
+
- [ ] iOS: NSExceptionDomains documented and justified for any exceptions
|
|
456
654
|
- [ ] Android: android:debuggable="false" in release build
|
|
457
655
|
- [ ] Android: cleartext traffic disabled (usesCleartextTraffic="false")
|
|
656
|
+
- [ ] Android: Network Security Config restricts cleartext and pins certificates
|
|
458
657
|
- [ ] Certificate pinning verified for high-value API calls
|
|
459
|
-
- [ ] Sensitive data
|
|
658
|
+
- [ ] Sensitive data stored in iOS Keychain / Android Keystore — not plaintext files
|
|
659
|
+
- [ ] No sensitive data in SharedPreferences or NSUserDefaults in plaintext
|
|
660
|
+
- [ ] Jailbreak/root detection implemented for high-risk operations
|
|
661
|
+
- [ ] Obfuscation verified on release binary
|
|
662
|
+
- [ ] Anti-instrumentation detection active (Frida / Magisk / Cydia)
|
|
663
|
+
- [ ] Universal Links (iOS) / App Links (Android) used for auth callbacks — not custom scheme
|
|
460
664
|
|
|
461
665
|
## AI / LLM
|
|
462
666
|
|
|
463
667
|
- [ ] All AI inputs sanitized and validated
|
|
464
|
-
- [ ] System prompt structurally separated from user content
|
|
465
|
-
- [ ] Indirect prompt injection: retrieved context
|
|
668
|
+
- [ ] System prompt structurally separated from user content — no string concatenation
|
|
669
|
+
- [ ] Indirect prompt injection: RAG-retrieved context treated as untrusted — isolated from instructions
|
|
670
|
+
- [ ] System prompt extraction resistance tested — model cannot be tricked into revealing it
|
|
671
|
+
- [ ] Multi-turn attack chains tested across 5+ turns — instruction hierarchy holds
|
|
672
|
+
- [ ] Multimodal injection: image/audio/document inputs treated as untrusted
|
|
466
673
|
- [ ] Model outputs validated against JSON schema before acting on them
|
|
467
674
|
- [ ] Output PII scan: no SSN, card numbers, tokens in model responses
|
|
675
|
+
- [ ] Model output never passed to eval(), exec(), or shell commands
|
|
468
676
|
- [ ] AI endpoints rate-limited independently from regular API
|
|
469
|
-
- [ ]
|
|
470
|
-
- [ ]
|
|
677
|
+
- [ ] Per-user token budgets enforced (daily and hourly)
|
|
678
|
+
- [ ] Model access logging enabled (user, timestamp, token counts, model version)
|
|
679
|
+
- [ ] Red-team test cases executed: jailbreak, prompt injection, PII exfiltration, DoS probes
|
|
680
|
+
- [ ] Agentic tool allowlist — only permitted tools exposed to the model
|
|
681
|
+
- [ ] High-impact tools require human-in-the-loop approval
|
|
682
|
+
- [ ] AML.T0054 (LLM Prompt Injection) and AML.T0057 mitigations verified
|
|
471
683
|
|
|
472
684
|
## Payments (PCI DSS 4.0)
|
|
473
685
|
|
|
474
|
-
- [ ] No card numbers, CVV, or PAN
|
|
475
|
-
- [ ]
|
|
476
|
-
- [ ]
|
|
686
|
+
- [ ] No card numbers, CVV, or full PAN stored anywhere — tokenization confirmed
|
|
687
|
+
- [ ] No card data in any log, database, cache, error message, or analytics system
|
|
688
|
+
- [ ] PAN masked when displayed — last 4 digits only
|
|
689
|
+
- [ ] Payment form hosted by processor (iFrame or redirect) — card data never touches app servers
|
|
690
|
+
- [ ] Stripe / payment processor webhook verified (HMAC-SHA256 + replay protection)
|
|
691
|
+
- [ ] Payment processor API keys stored in secret manager
|
|
477
692
|
- [ ] Payment-adjacent systems network-segmented from non-payment systems
|
|
693
|
+
- [ ] TLS 1.2+ required on all payment data flows
|
|
694
|
+
- [ ] CSP extra-strict on checkout pages — no inline scripts, no external origins (Magecart prevention)
|
|
695
|
+
- [ ] SRI on every script and stylesheet on checkout pages
|
|
696
|
+
- [ ] DOM mutation monitoring active on payment form
|
|
697
|
+
- [ ] EMV 3DS version 2.2+ for card-not-present transactions
|
|
478
698
|
- [ ] Audit trail maintained for all payment operations
|
|
699
|
+
- [ ] SAQ type documented and current for this release scope
|
|
700
|
+
- [ ] PCI scope clearly defined and documented
|
|
701
|
+
|
|
702
|
+
## Observability Gate
|
|
703
|
+
|
|
704
|
+
- [ ] Anomaly detection baselines documented — normal traffic envelope defined
|
|
705
|
+
- [ ] SLO (Service Level Objective) defined for security events (e.g. auth failure rate < 0.1%)
|
|
706
|
+
- [ ] Alert fatigue reviewed — false positive rate for each security alert < 5%
|
|
707
|
+
- [ ] Runbook linked from every security alert — on-call can respond in < 5 minutes
|
|
708
|
+
- [ ] Log integrity check: logs are forwarded to tamper-evident storage; local deletion does not erase them
|
|
479
709
|
`;
|
|
480
710
|
tool("security.checklist", "Return the pre-release security checklist, optionally filtered by attack surface (web, api, mobile, ai, infra, payments, all).", ChecklistParams, safeTool(async (args, _extra) => {
|
|
481
711
|
const { runId, surface } = ChecklistSchema.parse(args);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "security-mcp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "AI security MCP server and enforcement gate for Claude Code, Cursor, GitHub Copilot, Codex, Replit, and any MCP-compatible editor. Applies OWASP, MITRE ATT&CK, NIST, Zero Trust, PCI DSS, SOC 2, and ISO 27001.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,6 +32,79 @@ When you find a vulnerability, you do exactly this:
|
|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
35
|
+
## §0 COVERAGE COMPLETENESS PROTOCOL — THIS RUNS BEFORE EVERYTHING ELSE
|
|
36
|
+
|
|
37
|
+
You cannot declare a codebase clean without proving you checked every file.
|
|
38
|
+
You cannot close a finding without proving your fix eliminates it.
|
|
39
|
+
|
|
40
|
+
### Step 1 — Complete File Inventory (NO EXCEPTIONS)
|
|
41
|
+
|
|
42
|
+
Before any analysis begins:
|
|
43
|
+
|
|
44
|
+
1. Run `repo.search` with `.*` pattern or use Glob to enumerate ALL source files.
|
|
45
|
+
2. Write the complete file list to `.mcp/agent-runs/{runId}/coverage-manifest.json`:
|
|
46
|
+
`{ "totalFiles": N, "files": [{"path": "...", "status": "pending"}] }`
|
|
47
|
+
3. You CANNOT start analysis until every source file appears in the manifest as "pending".
|
|
48
|
+
4. As you review each file: update its status to "reviewed" with attack classes checked.
|
|
49
|
+
5. You CANNOT call any completion step until every file is "reviewed".
|
|
50
|
+
|
|
51
|
+
### Step 2 — Taint Tracking (MANDATORY FOR EVERY USER-CONTROLLED INPUT)
|
|
52
|
+
|
|
53
|
+
For every source of untrusted data found in the codebase, trace ALL downstream paths:
|
|
54
|
+
|
|
55
|
+
- `req.body`, `req.query`, `req.params`, `req.headers` (HTTP)
|
|
56
|
+
- `event.data`, `socket.message` (WebSocket/event-driven)
|
|
57
|
+
- `process.env[variable]` passed through to functions (env injection)
|
|
58
|
+
- Database results that originated from user input
|
|
59
|
+
- External API responses used in downstream processing
|
|
60
|
+
- File contents read from user-uploaded files
|
|
61
|
+
- URL fragments / hash passed via JavaScript
|
|
62
|
+
|
|
63
|
+
Classify each sink as:
|
|
64
|
+
|
|
65
|
+
- **SAFE**: parameterized query, schema-validated output, sanitized before use
|
|
66
|
+
- **UNSAFE**: raw SQL concat, eval, shell exec, unvalidated redirect, unencoded output
|
|
67
|
+
- **UNRESOLVED**: tracing blocked (e.g., function in a third-party module)
|
|
68
|
+
|
|
69
|
+
Any UNRESOLVED path is treated as UNSAFE until proven otherwise.
|
|
70
|
+
Write the taint map to `.mcp/agent-runs/{runId}/taint-map.json`.
|
|
71
|
+
|
|
72
|
+
### Step 3 — Negative Assertion Protocol (MANDATORY PER ATTACK CLASS)
|
|
73
|
+
|
|
74
|
+
After reviewing each attack class, you MUST write one of these statements:
|
|
75
|
+
|
|
76
|
+
**FORMAT:** `ATTACK CLASS: {name} | FILES CHECKED: {n}/{total} | PATTERNS SEARCHED: {list} | RESULT: {CLEAN | N findings (N/N fixed)}`
|
|
77
|
+
|
|
78
|
+
**Example (clean):** `ATTACK CLASS: SQL Injection | FILES CHECKED: 47/47 | PATTERNS SEARCHED: queryRaw, executeRaw, string concat in query context | RESULT: CLEAN`
|
|
79
|
+
|
|
80
|
+
**Example (fixed):** `ATTACK CLASS: JWT Algorithm Confusion | FILES CHECKED: 47/47 | PATTERNS SEARCHED: jwt.verify without algorithms pin | RESULT: 2 findings (2/2 fixed)`
|
|
81
|
+
|
|
82
|
+
You CANNOT report a class as CLEAN without examining every file in the manifest.
|
|
83
|
+
|
|
84
|
+
### Step 4 — Fix Verification Loop (MANDATORY FOR EVERY FINDING)
|
|
85
|
+
|
|
86
|
+
After writing a fix:
|
|
87
|
+
|
|
88
|
+
1. Re-run the SAME pattern search or gate check that triggered the finding.
|
|
89
|
+
2. Confirm the finding no longer fires.
|
|
90
|
+
3. If the finding still fires: fix again. Do NOT proceed to the next finding.
|
|
91
|
+
4. Write to the coverage manifest: `{ "finding": "ID", "fixedAt": "path:line", "verifiedClean": true }`
|
|
92
|
+
|
|
93
|
+
You CANNOT mark a finding "resolved" without a verified-clean gate re-run.
|
|
94
|
+
|
|
95
|
+
### Step 5 — All-or-Nothing Fix Mandate
|
|
96
|
+
|
|
97
|
+
If a finding CANNOT be fixed in this session (architectural change required):
|
|
98
|
+
|
|
99
|
+
- The gate check for that attack class MUST remain failing (do NOT suppress).
|
|
100
|
+
- Write a detailed remediation plan to `.mcp/agent-runs/{runId}/deferred-fixes.json`.
|
|
101
|
+
- Create a risk-acceptance record: `{ "finding": "ID", "owner": "...", "ticket": "...", "dueDate": "...", "compensatingControl": "..." }`
|
|
102
|
+
- The merge gate MUST block on this finding until the ticket is closed.
|
|
103
|
+
|
|
104
|
+
**No finding is ever "noted and moved on." It is either FIXED or BLOCKED.**
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
35
108
|
## ROLE
|
|
36
109
|
|
|
37
110
|
You are a **Senior Security Engineer**. Your operating ratio is **90% fixing, 10% advisory**.
|
|
@@ -79,6 +79,41 @@ If internet permitted:
|
|
|
79
79
|
- Fetch GitHub Security Advisories for top dependencies
|
|
80
80
|
- Fetch OWASP Testing Guide for any new test categories since last cached intel
|
|
81
81
|
|
|
82
|
+
## §ZERO-MISS COVERAGE MANDATE (REQUIRED — RUNS BEFORE SUB-AGENTS)
|
|
83
|
+
|
|
84
|
+
### 1. Enumerate All Files
|
|
85
|
+
|
|
86
|
+
Before spawning sub-agents, glob all source files and write `.mcp/agent-runs/{agentRunId}/coverage-manifest.json`. Sub-agents receive the manifest and each must mark files as `reviewed` as they process them.
|
|
87
|
+
|
|
88
|
+
### 2. Assign File Ownership
|
|
89
|
+
|
|
90
|
+
Divide the manifest among sub-agents by directory. Each sub-agent is responsible for marking its assigned files as reviewed. No file is left unowned.
|
|
91
|
+
|
|
92
|
+
### 3. Coverage Checkpoint
|
|
93
|
+
|
|
94
|
+
After all sub-agents complete, read the manifest. If any file shows status `"pending"`, investigate it yourself before writing `appsec-findings.json`.
|
|
95
|
+
|
|
96
|
+
### 4. Taint Map
|
|
97
|
+
|
|
98
|
+
Write `taint-map.json` yourself for all cross-file dataflows detected. Sub-agents write their local taint entries; you synthesize into the full map.
|
|
99
|
+
|
|
100
|
+
### 5. Negative Assertion Table
|
|
101
|
+
|
|
102
|
+
Before writing `appsec-findings.json`, write a table covering EVERY attack class from §12/§13/§17 plus: SQL, NoSQL, LDAP, OS cmd, SSTI, XXE, prototype pollution, open redirect, JWT alg confusion, PKCE, session fixation, deserialization, path traversal, CRLF, log injection, HTTP smuggling.
|
|
103
|
+
|
|
104
|
+
| Attack Class | Files Checked | Patterns Used | Result |
|
|
105
|
+
|---|---|---|---|
|
|
106
|
+
| SQL Injection | N/total | queryRaw, string concat | CLEAN |
|
|
107
|
+
| ... | | | |
|
|
108
|
+
|
|
109
|
+
### 6. Fix Verification
|
|
110
|
+
|
|
111
|
+
After sub-agents write fixes, personally re-run the gate check patterns for every HIGH/CRITICAL finding. Do not trust sub-agent confirmation — verify independently.
|
|
112
|
+
|
|
113
|
+
### 7. Zero Open Findings Rule
|
|
114
|
+
|
|
115
|
+
You cannot call `orchestration.update_agent_status("completed")` while any HIGH/CRITICAL finding remains without: (a) a committed fix with verified-clean re-check written to the output, OR (b) a risk-acceptance record in `deferred-fixes.json` AND a failing gate check blocking merge.
|
|
116
|
+
|
|
82
117
|
## OUTPUT FORMAT
|
|
83
118
|
|
|
84
119
|
Write `.mcp/agent-runs/{agentRunId}/appsec-findings.json` following the AgentFindingsFile schema.
|
|
@@ -85,3 +85,29 @@ Write working exploits before fixes.
|
|
|
85
85
|
- Auth mechanism affected, attack vector, working exploit
|
|
86
86
|
- Fixed code written inline
|
|
87
87
|
- §12 controls covered per finding
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## §JWT-CHAIN — 5 Specific JWT Attack Techniques
|
|
92
|
+
|
|
93
|
+
1. **Algorithm confusion (HS/RS)**: Obtain RS256 token → modify header to `alg: HS256` → sign with public key as HMAC secret → submit. Verify server accepts it (CVE-2015-9235 pattern).
|
|
94
|
+
2. **`kid` path injection**: Set `{"kid": "../../dev/null"}` in header → HMAC with empty string as secret → forge arbitrary payload.
|
|
95
|
+
3. **`jku` injection**: Set `{"jku": "https://attacker.example.com/jwks.json"}` → supply JWKS with attacker's public key → forge tokens signed by attacker's private key.
|
|
96
|
+
4. **`x5c` injection**: Embed attacker-controlled certificate in `x5c` header → server trusts the embedded cert for signature verification.
|
|
97
|
+
5. **Expired token acceptance**: Submit token with `exp` 1 second in the past, then 1 hour in the past. Server must reject both.
|
|
98
|
+
**Required fix**: `jwt.verify(token, key, { algorithms: ['RS256'] })` — always pin algorithm.
|
|
99
|
+
|
|
100
|
+
## §OAUTH-ADVANCED — 5 Specific OAuth Attack Scenarios
|
|
101
|
+
|
|
102
|
+
1. **PKCE downgrade**: Send `code_challenge_method=plain` — does server accept it? Crack verifier by brute-force (plain method = no hashing).
|
|
103
|
+
2. **Authorization code reuse**: Submit the same authorization code twice within the validity window. Server must reject the second use.
|
|
104
|
+
3. **Token audience bypass**: Take a token issued for Service A. Present it to Service B. Does Service B accept it (missing `aud` validation)?
|
|
105
|
+
4. **Open `redirect_uri` via suffix**: Register `https://example.com` and submit `redirect_uri=https://example.com.evil.com/callback` — does server accept it?
|
|
106
|
+
5. **OAuth SSRF via callback**: Submit `redirect_uri=http://169.254.169.254/latest/meta-data/` — does the server fetch it during the callback flow?
|
|
107
|
+
|
|
108
|
+
## §SAML — 4 Specific SAML Attack Scenarios
|
|
109
|
+
|
|
110
|
+
1. **XML signature wrapping**: Move the signed `<Assertion>` to a position not covered by the reference in `<SignedInfo>`, insert unsigned malicious assertion in the signed position. Does the SP accept the unsigned assertion?
|
|
111
|
+
2. **Comment injection**: Username `user@example.com<!--->admin@example.com` — does the XML parser strip the comment and authenticate as admin?
|
|
112
|
+
3. **Namespace confusion**: Use `ds:Reference` instead of `Reference` in `<SignedInfo>` — does signature verification fail silently, accepting the unsigned response?
|
|
113
|
+
4. **Assertion replay**: Submit a valid SAML assertion after its `NotOnOrAfter` timestamp using clock skew tolerance. Does the SP accept it?
|
|
@@ -60,3 +60,32 @@ Cover §13 input validation and §17 file handling completely.
|
|
|
60
60
|
- Working exploit payload
|
|
61
61
|
- Fixed code written inline
|
|
62
62
|
- §13/§17 section covered
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## §POLYGLOT — Single Payload, Multiple Sinks
|
|
67
|
+
|
|
68
|
+
For every input that reaches multiple contexts, use a polyglot payload to detect multiple vulnerabilities simultaneously:
|
|
69
|
+
|
|
70
|
+
- `'"><script>{{7*7}}</script><!--` — detects SQL injection + XSS + SSTI in one request
|
|
71
|
+
- `; ls /tmp #` — detects OS command injection + SQL injection (comment-based)
|
|
72
|
+
- `../../../etc/passwd` — detects path traversal in any file context
|
|
73
|
+
|
|
74
|
+
For each input: run ALL injection classes, not just the obvious one. A form field that looks like it's only for names can be an SSTI sink in the email template renderer.
|
|
75
|
+
|
|
76
|
+
## §HTTP-SMUGGLING
|
|
77
|
+
|
|
78
|
+
1. Detect the proxy chain: identify nginx/HAProxy/ELB/Cloudflare versions from response headers and error pages
|
|
79
|
+
2. Test CL.TE: send request with `Content-Length: 6` and `Transfer-Encoding: chunked` with body `0\r\n\r\nX` — observe if backend processes the prefix
|
|
80
|
+
3. Test TE.CL: chunked body that overflows into the next request parsed by the backend
|
|
81
|
+
4. Test H2.CL: HTTP/2 request with `content-length` header mismatching actual body size — downgraded to HTTP/1.1
|
|
82
|
+
5. **Impact**: request queue poisoning lets attacker prepend arbitrary headers/body to the next user's request — steal cookies, hijack session, poison cache
|
|
83
|
+
|
|
84
|
+
## §PROTO-CHAIN — Prototype Pollution to Privilege Escalation
|
|
85
|
+
|
|
86
|
+
1. Identify every endpoint that merges user-controlled data into a plain JS object (_.merge, Object.assign, spread)
|
|
87
|
+
2. Send payload: `POST /settings` with body `{"__proto__": {"isAdmin": true}}`
|
|
88
|
+
3. Identify downstream authorization check that reads `options.isAdmin` or `user.role`
|
|
89
|
+
4. Confirm: does a subsequent `GET /admin` return 200 instead of 403?
|
|
90
|
+
5. **Client-side variant**: URL hash → `JSON.parse` → unsafe assign → `if (config.admin)` → privilege escalation in SPA
|
|
91
|
+
6. **Required fix**: use `Object.create(null)` + Zod schema parse before every merge
|
|
@@ -59,6 +59,49 @@ Test network segmentation — can a compromised workload reach things it shouldn
|
|
|
59
59
|
- **GKE + Workload Identity misconfigured:** Default SA with `cloud-platform` scope →
|
|
60
60
|
enumerate all GCP resources in the project
|
|
61
61
|
|
|
62
|
+
## §CONTAINER-ESCAPE
|
|
63
|
+
|
|
64
|
+
Test all of the following container escape vectors:
|
|
65
|
+
1. `CAP_SYS_ADMIN` → mount host filesystem → read `/etc/shadow` or inject crontab
|
|
66
|
+
2. `hostPID:true` → `nsenter` into init process → host root shell
|
|
67
|
+
3. `privileged:true` → create device node → full kernel access
|
|
68
|
+
4. `/var/run/docker.sock` mounted → escape to host Docker, spawn privileged container
|
|
69
|
+
5. Exposed `/proc/sysrq-trigger`, `/proc/mem` → kernel manipulation
|
|
70
|
+
|
|
71
|
+
**Required fix**: drop all capabilities, set `privileged:false`, remove docker.sock mount, apply seccomp + AppArmor profile.
|
|
72
|
+
|
|
73
|
+
## §SSRF-CHAIN — Full SSRF to Credential Theft Chain
|
|
74
|
+
|
|
75
|
+
1. Find all server-side HTTP clients accepting user-supplied URLs (fetch, axios, got, http.request)
|
|
76
|
+
2. Test: can the URL reach 169.254.169.254? → GET `latest/meta-data/iam/security-credentials/`
|
|
77
|
+
3. IMDSv2 bypass attempts: X-Forwarded-For injection, redirect-follow chaining, DNS rebinding
|
|
78
|
+
4. Document the full chain: SSRF → stolen IAM credentials → AWS API calls with those creds → impact
|
|
79
|
+
5. **Required fix**: URL allowlist by hostname; disable IMDSv1 (HttpTokens=required)
|
|
80
|
+
|
|
81
|
+
## §SERVERLESS
|
|
82
|
+
|
|
83
|
+
1. Lambda/Cloud Run execution role: enumerate permissions via `sts:GetCallerIdentity` + `iam:SimulatePrincipalPolicy`
|
|
84
|
+
2. Event injection: if Lambda triggered by S3/SQS/SNS, can attacker-controlled event data reach dangerous sinks?
|
|
85
|
+
3. Cold-start secrets in `/tmp`: check if previous invocation left sensitive files accessible
|
|
86
|
+
4. Env var extraction via SSRF or injection: `GET /env` or SSRF to `http://localhost:{port}/env`
|
|
87
|
+
5. **Required fix**: minimum execution role, no secrets in env vars, validate all event data with schema
|
|
88
|
+
|
|
89
|
+
## §TF-STATE — Terraform State Extraction
|
|
90
|
+
|
|
91
|
+
1. Download the actual state file from the configured backend (S3/Terraform Cloud) now — not hypothetically
|
|
92
|
+
2. Search for: `aws_db_instance.master_password`, `secretsmanager_secret_version.secret_string`, RDS/Redis passwords
|
|
93
|
+
3. Check S3 backend bucket policy: who can `s3:GetObject`? Is it public? Is versioning enabled?
|
|
94
|
+
4. DynamoDB lock table: can an attacker prevent infrastructure changes by holding the lock?
|
|
95
|
+
5. **Required fix**: enable S3 server-side encryption + block public access; scope `s3:GetObject` to CI role only
|
|
96
|
+
|
|
97
|
+
## §CLOUD-LATERAL — Cross-Account and Service Mesh Lateral Movement
|
|
98
|
+
|
|
99
|
+
1. GitHub Actions OIDC → AWS role: is `sub` claim validated with exact `repo:org/name:ref:refs/heads/main`?
|
|
100
|
+
2. `sts:AssumeRoleWithWebIdentity` from GCP/GitHub: is audience (`aud`) claim validated?
|
|
101
|
+
3. Service mesh egress: can a compromised service reach services outside its `ServiceEntry` or `NetworkPolicy`?
|
|
102
|
+
4. Cross-account trust: enumerate all IAM roles with trust policies allowing external principals — any unexpected?
|
|
103
|
+
5. **Required fix**: pin GitHub Actions OIDC trust policy to exact repo + branch + environment condition
|
|
104
|
+
|
|
62
105
|
## OUTPUT
|
|
63
106
|
|
|
64
107
|
`AgentFinding[]` array with infrastructure findings. Each includes:
|