# v0.3.3 — MCP framework DoS + Doris SQLi + Anthropic SDK hardening

Date: 2026-04-21. Target tag: v0.3.3. Prior tag: v0.3.2 (2026-04-20).

## Scope (3 new rules, 148 → 151)

| Rule | Severity | CVE / Incident | Scanner |
|---|---|---|---|
| AAK-MCPFRAME-001 | MEDIUM | CVE-2026-39313 | `scanners/transport_limits.py` (new) + `scanners/supply_chain.py` pin-check |
| AAK-DORIS-001 | HIGH | CVE-2025-66335 | `scanners/supply_chain.py` pin-check |
| AAK-ANTHROPIC-SDK-001 | HIGH | OX-MCP-2026-04-15 | `scanners/mcp_sdk_hardening.py` (new) |

Deferred: CVE-2026-6599 and CVE-2026-39861 — NVD records unresolvable this morning, do not author speculative rules.

## Task A — SLA-watcher dedup (root cause fix)

`scripts/cve_watcher.py` currently dedups against `CHANGELOG.cves.md`. A CVE that sits in the SLA queue with no rule yet never reaches the changelog, so the 6-hourly cron re-opens it. Fix:

1. Persist seen CVE IDs in `.aak/cve-watcher-state.json` (write after successful file-issue, never reset).
2. Cross-check open `cve-response` issues via the GitHub REST API (no `gh`) before filing — if a CVE ID appears anywhere in an existing open issue title, skip.
3. Add `scripts/close_duplicate_cve_issues.py` that groups open `cve-response` issues by extracted CVE ID, keeps the lowest-numbered one, closes the rest with a cross-reference body.
4. Fixture test `tests/test_cve_watcher_dedup.py` replays the same CVE three times across different timestamps and asserts exactly one issue-file call.

## Task B — AAK-MCPFRAME-001 + AAK-DORIS-001

### AAK-MCPFRAME-001 (MEDIUM, CWE-770)

- **Detection A** (pin-check, `supply_chain.py`): `package.json` dependency on `mcp-framework` with version `<0.2.22` (semver-aware).
- **Detection B** (pattern, `transport_limits.py`): TS/JS files with `readRequestBody`-like pattern (`req.on('data', ...)` concatenating chunks into a string without a `Content-Length` or `maxMessageSize` guard). Regex over `.ts`/`.js`/`.mjs`.
- **Fixtures**: `tests/fixtures/cves/cve-2026-39313/vulnerable/` (0.2.21 pin + custom loop), `.../patched/` (0.2.22 pin), `.../length-capped/` (custom impl with `Content-Length` check).
- **OWASP**: `ASI09` (Resource Abuse). AICM: `LOG-13` (capacity monitoring).

### AAK-DORIS-001 (HIGH, CWE-89)

- **Detection**: pin-check `apache-doris-mcp-server<0.6.1` in `requirements*.txt`, `pyproject.toml`, `poetry.lock`, `uv.lock`.
- **OWASP**: `ASI02` Tool Misuse + `MCP04:2025` Tool-Layer Injection. AICM: `AIS-07` (input validation) + `DSP-07` (database access).
- **Fixture**: `tests/fixtures/cves/cve-2025-66335/vulnerable/requirements.txt` (pin to 0.6.0) + `.../patched/requirements.txt` (0.6.1).

## Task C — AAK-ANTHROPIC-SDK-001 (HIGH)

New scanner `agent_audit_kit/scanners/mcp_sdk_hardening.py`. **Fires when all three are true**:

1. Repo's manifests declare the upstream Anthropic/MCP SDK:
   - Python: `mcp` or `modelcontextprotocol` in `requirements*.txt`/`pyproject.toml`.
   - TS/JS: `@modelcontextprotocol/sdk` in `package.json`.
   - Java: `io.modelcontextprotocol:*` in `pom.xml`/`build.gradle`.
   - Rust: `mcp` or `modelcontextprotocol` in `Cargo.toml`.
2. Repo exposes an MCP server with a STDIO transport — any file contains `StdioServerTransport`, `StdioTransport`, `stdio_server`, `StdioServer`, etc.
3. No sanitizer marker is present (all of these opt out):
   - `shlex.quote` or `shlex.split` import used against argv-assembly variables (Python).
   - An allow-list function (regex matches `ALLOWED_`, `WHITELIST`, `VALID_TOOLS`, etc.).
   - `stdio_disabled: true` or `transports: ["http"]`/`["sse"]` in a discovered MCP config.
   - `.agent-audit-kit.yml` contains `accepts_stdio_risk: true` with a non-empty `justification` field (documented risk acceptance).

**Rule fields**: `owasp_agentic_references=["ASI02","ASI10"]`, `owasp_mcp_references=["MCP01:2025"]`, `incident_references=["OX-MCP-2026-04-15"]`, `aicm_references=["AIS-07","STA-08"]`. No CVE — Anthropic declined to CVE.

**Fixtures**: `tests/fixtures/incidents/ox-mcp-2026-04-15/{python,typescript,java,rust}/` each with `vulnerable/` + `sanitized/` subdirs. No live exploit code — just minimal reproducible server scaffolds.

**Cross-link**: `AAK-STDIO-001.description` gets a trailing sentence pointing to the SDK-level rule.

## Task D — OWASP Agentic density floor + README marker

- Extend `tests/test_owasp_agentic_coverage.py` with a parametrized `test_density_floor(asi)` asserting ≥3 rules per slot.
- Current density gap: only **ASI08** (Agent Communication Poisoning) has 1 rule. Promote existing A2A rules to tag ASI08: `AAK-A2A-002` (message replay), `AAK-A2A-005` (cross-agent forgery), `AAK-A2A-009` (context spillover). Verify the fit before tagging; fall back to 2-of-3 if one doesn't fit.
- Extend `scripts/gen_owasp_coverage.py` to emit a compact table snippet between `<!-- owasp-coverage -->` and `<!-- /owasp-coverage -->` markers in `README.md`.

## Task E — AICM density 10 → ≥75

Mechanical overlay expansion in `agent_audit_kit/rules/builtin.py::_AICM_TAGS`:

| Rule family | Target AICM domain |
|---|---|
| `AAK-SECRET-003..009` | DSP-17 Secrets Management |
| `AAK-SUPPLY-003..006` | STA-02 / STA-08 |
| `AAK-TRUST-002,003,005,006,007` | IAM-02 / IAM-16 |
| `AAK-TRANSPORT-001..004` | CEK-08 Data-in-transit |
| `AAK-A2A-001..012` | IAM-04 / STA-10 |
| `AAK-POISON-001..006` | AIS-07 / STA-10 |
| `AAK-TAINT-001..008` | AIS-07 Input validation |
| `AAK-SSRF-001..005` | IVS-04 Network perimeter |
| `AAK-OAUTH-*` | IAM-01 / IAM-16 |
| `AAK-SKILL-001..005` | STA-10 Third-party assessment |
| `AAK-HOOK-001..012` | IAM-01 / CCC-08 |
| `AAK-MCP-001..020` (where applicable) | IAM-01, CEK-08, LOG-06 |

Target: ≥75 rules tagged. `tests/test_aicm.py` gets a density assertion `len([r for r in RULES.values() if r.aicm_references]) >= 75`.

## Task F — CycloneDX AI-BOM emitter

Extend `agent_audit_kit/output/sbom.py::emit_cyclonedx` with an `aibom: bool` kwarg. When true:

- Add a `components` entry with `type: "machine-learning-model"` for each detected Anthropic/Claude/OpenAI client.
- Add a `formulation` section with a `components` array listing detected MCP SDKs and agent platform integrations (LangChain, LangSmith, LangGraph, LangFuse, Helicone, Humanloop, Context.ai).
- Include `metadata.properties`: `aak:rule-bundle-sha256`, and one `aak:incident-fired` entry per `incident_references` that fired in the scan.
- New CLI flag wiring: `--sbom-format aibom` in `cli.py`.
- Test: `tests/test_cyclonedx_aibom.py` — validate against the CycloneDX 1.5 JSON Schema (vendored minimal subset, no new dependency).

## Ship sequence

1. Commit A (watcher dedup + close script) → close dup issues via the script.
2. Commit B (two CVE rules + fixtures + tests).
3. Commit C (SDK hardening rule + scanner + fixtures + tests).
4. Commit D (density floor + README marker + coverage script regen).
5. Commit E (AICM overlay expansion + density test).
6. Commit F (AI-BOM emitter + test).
7. Version bump, regenerate `rules.json`, update CHANGELOG.md + CHANGELOG.cves.md.
8. Tag `v0.3.3`, push, monitor release.yml to PyPI + GHCR + Sigstore + GH Release.
9. Close #46, #49, #51, #54 (handled by new rules or consolidated), file v0.3.4 tracker for CVE-2026-6599 + CVE-2026-39861.
