diff --git a/README.md b/README.md index 68b93fd..3835483 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Then open Claude Code and type `/plugin` to browse and install plugins from the ## Plugins -### [LLM Security](plugins/llm-security/) `v7.1.0` +### [LLM Security](plugins/llm-security/) `v7.2.0` Security scanning, auditing, and threat modeling for agentic AI projects. diff --git a/plugins/llm-security/.claude-plugin/plugin.json b/plugins/llm-security/.claude-plugin/plugin.json index 2f03d4d..ea73883 100644 --- a/plugins/llm-security/.claude-plugin/plugin.json +++ b/plugins/llm-security/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { "name": "llm-security", "description": "Security scanning, auditing, and threat modeling for Claude Code projects. Detects secrets, validates MCP servers, assesses security posture, and generates threat models aligned with OWASP LLM Top 10.", - "version": "7.1.0" + "version": "7.2.0" } diff --git a/plugins/llm-security/CHANGELOG.md b/plugins/llm-security/CHANGELOG.md index 7ee94f6..b3c90d2 100644 --- a/plugins/llm-security/CHANGELOG.md +++ b/plugins/llm-security/CHANGELOG.md @@ -4,6 +4,134 @@ All notable changes to the LLM Security Plugin are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [7.2.0] - 2026-04-29 + +Batch B release. Closes the remaining critical-review B-tier scanner +defects (B3, B5, B6, B7), lands the v7.2.0 evasion-arsenal hardening +patches (E1, E4, E5, E7, E15, E16, E17, E18), unifies the v1→v2 +risk-score formula across documentation surfaces, and ships 8 new +red-team scenarios (64 → 72) plus a polyglot fixture for the entropy +two-stage pipeline. + +### Added + +- **B6 destructuring/spread taint propagation** (`scanners/taint-tracer.mjs`). + `extractAssignedVariable` now recognises `const { secret: userInput } = req.body` + and `const [input, ...rest] = process.argv` — destructured and spread + bindings carry their tainted source into downstream usage. + `extractAssignedVariable` exported for direct unit testing. + `+19 tests`. + +- **B7 token-overlap typosquat fallback** (`scanners/lib/string-utils.mjs`, + `scanners/dep-auditor.mjs`, `scanners/supply-chain-recheck.mjs`). + New `tokenize` / `tokenOverlap` helpers + `TYPOSQUAT_SUSPICIOUS_TOKENS` + list catch typosquats that Levenshtein distance misses + (e.g. `chalk-color-utility` vs `chalk`). `+21 tests`. + +- **E15 `.claude/agents/*.md` memory-poisoning glob** (`scanners/memory-poisoning-scanner.mjs`). + Agent definitions are now scanned alongside `CLAUDE.md` and rules. + New fixture + `+3 tests`. + +- **E1 hidden-Unicode coverage extended to PUA-A and PUA-B** + (`scanners/lib/string-utils.mjs`). `containsUnicodeTags` now flags + U+F0000–U+FFFFD (Supplementary Private Use Area-A) and U+100000–U+10FFFD + (Supplementary Private Use Area-B) in addition to the U+E0000 Tag block. + PUA characters do not decode to ASCII (they have no standard mapping) + but their presence is suspicious enough to emit a HIGH advisory. + `+21 tests`. + +- **E16 homoglyph fold before pattern matching** + (`scanners/lib/string-utils.mjs`, `scanners/lib/injection-patterns.mjs`). + New `foldHomoglyphs` (NFKC + targeted Cyrillic/Greek → Latin map) + runs before every pattern match in `scanForInjection`. Attacks like + `ignоre previous instructions` (Cyrillic `о`) now trigger the same + CRITICAL pattern as the Latin form. ASCII fast-path keeps the helper + zero-cost on plain text. `+27 tests`. + +- **E17 configurable escalation window + 20-call MEDIUM advisory** + (`hooks/scripts/post-session-guard.mjs`). The + `LLM_SECURITY_ESCALATION_WINDOW` env-var now overrides the primary + escalation-after-input window (default 5). A secondary 20-call + MEDIUM advisory catches slow-burn variants outside the primary + window. `+5 tests`. + +- **E4 markdown link-title injection scan** (`hooks/scripts/post-mcp-verify.mjs`). + Every `[text](url "title")` title is HTML-entity-decoded and run + through `scanForInjection`. Bypassed the existing HTML-tag-gated + checks pre-E4. `+3 tests`. + +- **E5 SVG ` / / <metadata> / <foreignObject>` extractor** + (`hooks/scripts/post-mcp-verify.mjs`). Adversarial text inside SVG + containers is invisible in the rendered image but parsed by an + agent reading the source. `+3 tests`. + +- **E7 generalized HTML comment scan** (`hooks/scripts/post-mcp-verify.mjs`). + Pre-E7 the `<!-- AGENT|AI|HIDDEN -->` keyword-restricted CRITICAL + pattern fired only on marked comments. Now every `<!-- ... -->` + body is decoded and scanned. The keyword pattern still fires + (defense-in-depth). `+3 tests`. + +- **8 new red-team scenarios** (`knowledge/attack-scenarios.json`). + UNI-007/008 (E1 PUA-A/PUA-B), UNI-009 (E16 Greek-Latin homoglyph + fold blocks), MCP-005 (E4), MCP-006/007 (E5 desc/foreignObject), + MCP-008 (E7), TRI-004 (E17 escalation-after-input). + `attack-simulator.mjs` baseline: 64 → 72, 100 % pass. + +### Changed + +- **B5 entropy two-stage pipeline** (`scanners/entropy-scanner.mjs`). + New `classifyFileContext(absPath, lines)` returns + `'shader-dominant' | 'markup-dominant' | 'code-dominant' | 'mixed'`, + keyed off file extension with a content-density fallback for + code-extension files (≥50 % sampled lines matching GLSL/inline-markup + → downgrade to `mixed`). `isFalsePositive` now accepts the context + and gates rules 11-13 (GLSL / CSS-in-JS / inline-markup + line-proximity) on `context !== 'code-dominant'`. Polyglot `.ts` + files with embedded GLSL blocks no longer suppress credentials + adjacent to shader keywords (the v7.0.0 false-negative class). + Conservative defaults preserve existing rule-11 / 12 / 13 behaviour + for the single-line `.js` / `.jsx` test fixtures. New fixture + `tests/fixtures/entropy/polyglot-ts-with-glsl.ts`. `+3 tests`. + +- **E18 entropy rule 18 — markdown-image CDN-aware + secret pre-check** + (`scanners/entropy-scanner.mjs`). Pre-E18, every + `![…](https?://…)` line was suppressed regardless of host or query. + Now suppression requires (host matches `MARKDOWN_IMAGE_CDN_HOSTS` + allowlist) AND (no secret-shaped token in query). Non-CDN hosts and + CDN hosts carrying `?token=…` / `?api_key=…` / AWS / GitHub / npm + prefixes fall through to entropy classification. `+4 tests`. + +- **v1 → v2 risk-formula constants unified across docs** + (`commands/scan.md`, `commands/audit.md`, `agents/mcp-scanner-agent.md`, + `agents/posture-assessor-agent.md`). The four files referenced the + legacy v1 `score >= 61` / `score >= 21` / `Critical × 25` constants; + authoritative implementation in `scanners/lib/severity.mjs` has been + v2 (`BLOCK ≥65`, `WARNING ≥15`, severity-dominated log-scaled tiers) + since v7.0.0. `tests/lib/doc-consistency.test.mjs` adds a guard so + these surfaces cannot drift back. `+28 tests`. + +### Documentation + +- **B3 `info` severity is scoring-inert** (`scanners/lib/severity.mjs` JSDoc, + `CLAUDE.md`). Documents the long-standing implementation: `info` + findings appear in OWASP aggregates but contribute zero to + `risk_score`, `verdict`, and `riskBand`. `+1 anchor test`. + +### Tests + +- **1522 → 1665+** (Wave 1 +29, Wave 2 +43, Wave 3 +53, Wave 4 +9, + Wave 5 +7, Wave 6 attack scenarios). All green except the + documented `pre-compact-scan` perf-flake (passes 6/6 in isolation, + fluctuates around the 500 ms ceiling under full-suite parallelism). + `attack-simulator`: 64 → 72 scenarios, 100 % pass. + +### Notes + +- E15 (`.claude/agents/*.md` glob) and E18 (entropy rule 18 CDN + allowlist) are scanner-only — they have unit / integration + coverage in their respective scanner test files and no + `attack-simulator.mjs` scenario. + ## [7.1.1] - 2026-04-29 Patch release. Closes the narrative-coherence gap that survived v7.0.0: diff --git a/plugins/llm-security/CLAUDE.md b/plugins/llm-security/CLAUDE.md index f5423af..1ab975c 100644 --- a/plugins/llm-security/CLAUDE.md +++ b/plugins/llm-security/CLAUDE.md @@ -1,6 +1,6 @@ -# LLM Security Plugin (v7.1.0) +# LLM Security Plugin (v7.2.0) -Security scanning, auditing, and threat modeling for Claude Code projects. 5 frameworks: OWASP LLM Top 10, Agentic AI Top 10 (ASI), Skills Top 10 (AST), MCP Top 10, AI Agent Traps (DeepMind). 1511 unit and integration tests; mutation-testing coverage not published. +Security scanning, auditing, and threat modeling for Claude Code projects. 5 frameworks: OWASP LLM Top 10, Agentic AI Top 10 (ASI), Skills Top 10 (AST), MCP Top 10, AI Agent Traps (DeepMind). 1665+ unit and integration tests; mutation-testing coverage not published. **v7.0.0 — Severity-dominated risk scoring (v2 model, BREAKING).** Three changes target the false-positive cascade on real codebases (hyperframes.com gave `BLOCK / Extreme / 100`, ~70% noise): diff --git a/plugins/llm-security/README.md b/plugins/llm-security/README.md index 230d33c..e6407b8 100644 --- a/plugins/llm-security/README.md +++ b/plugins/llm-security/README.md @@ -6,7 +6,7 @@ *AI-generated: all code produced by Claude Code through dialog-driven development. [Full disclosure →](../../README.md#ai-generated-code-disclosure)* -![Version](https://img.shields.io/badge/version-7.1.0-blue) +![Version](https://img.shields.io/badge/version-7.2.0-blue) ![Platform](https://img.shields.io/badge/platform-Claude_Code_Plugin-purple) ![Agents](https://img.shields.io/badge/agents-6-orange) ![Scanners](https://img.shields.io/badge/scanners-22-cyan) @@ -824,6 +824,7 @@ This plugin provides full-stack security hardening (static analysis + supply cha | Version | Date | Highlights | |---------|------|------------| +| **7.2.0** | 2026-04-29 | **Batch B release.** Closes the remaining critical-review B-tier scanner defects (B3, B5, B6, B7) and lands the v7.2.0 evasion-arsenal hardening patches (E1, E4, E5, E7, E15, E16, E17, E18). **Added:** B6 destructuring/spread taint propagation in `taint-tracer.mjs`; B7 token-overlap typosquat fallback in `string-utils.mjs`/`dep-auditor`/`supply-chain-recheck`; E15 `.claude/agents/*.md` glob in `memory-poisoning-scanner`; E1 PUA-A/PUA-B coverage in `containsUnicodeTags`; E16 `foldHomoglyphs` (Cyrillic/Greek → Latin via NFKC) before every pattern match in `scanForInjection` (with ASCII fast-path); E17 `LLM_SECURITY_ESCALATION_WINDOW` env-var + 20-call MEDIUM secondary advisory in `post-session-guard`; E4 markdown link-title scan, E5 SVG `<desc>/<title>/<metadata>/<foreignObject>` extractor, E7 generalized HTML comment scan in `post-mcp-verify`. **Changed:** B5 entropy two-stage pipeline — new `classifyFileContext` in `entropy-scanner.mjs` gates rules 11-13 (GLSL/CSS-in-JS/inline-markup line-proximity) on `context !== 'code-dominant'`, ending the v7.0.0 polyglot false-negative class while preserving existing behaviour for short single-line fixtures. E18 entropy rule 18 — `MARKDOWN_IMAGE_CDN_HOSTS` allowlist + secret-in-query pre-check; non-CDN hosts and CDN URLs carrying secret-shaped query tokens fall through to entropy classification. v1 → v2 risk-formula constants (BLOCK ≥65, WARNING ≥15) unified across `commands/scan.md`, `commands/audit.md`, `agents/mcp-scanner-agent.md`, `agents/posture-assessor-agent.md` with a `tests/lib/doc-consistency.test.mjs` drift-guard. **Documentation:** B3 `info` severity is scoring-inert — documented in `severity.mjs` JSDoc and CLAUDE.md. **Red team:** 8 new attack scenarios (UNI-007/008/009, MCP-005/006/007/008, TRI-004); attack-simulator 64 → 72, 100 % pass. **Tests:** 1522 → 1665+ (Wave 1-6 cumulative). | | **7.1.0** | 2026-04-29 | **Critical-review patch.** Closes the highest-impact items from the v7.0.0 adversarial review (`docs/critical-review-2026-04-20.md`, grade B-). Bug-fixes + documentation honesty-sweep, no new features. **Fixed:** (1) `pre-write-pathguard.mjs` regex hole — `.env.production.local.backup`, `.env.prod.local.bak`, etc. could be written. New regex `/[\\/]\.env(\.[A-Za-z0-9._-]+)*$/` covers arbitrary multi-segment suffixes; `.envrc` still allowed. (2) `post-session-guard.mjs` — `LLM_SECURITY_TRIFECTA_MODE=block` only blocked when trifecta was MCP-concentrated or hit a sensitive path; distributed trifectas across MCP servers were advisory-only. AND-gate removed. (3) `scanners/lib/severity.mjs` JSDoc + CHANGELOG arithmetic — `riskScore({critical: 4})` is 93, not 90 (computation always was). **Changed (honesty-sweep, critical-review §9):** "Trustworthy scoring" → "Severity-dominated risk scoring (v2 model)"; "Context-aware entropy scanner" → "Rule-based entropy scanner with file-extension skip, 8 line-level suppression rules, and configurable policy"; "1487 tests" → "1511 unit and integration tests; mutation-testing coverage not published"; "Fully Schrems II compatible" → "Schrems II compatible in default offline mode. Optional OSV.dev enrichment (`supply-chain-recheck --online`) transmits package identifiers to a Google-operated API and is a separate compliance consideration"; "Rule of Two enforcement" → "Rule of Two detection (configurable; default `warn`; blocks on high-confidence trifectas in opt-in `block` mode; distributed trifectas detected but not blocked by default)"; "Hardened ZIP extractor" → suffix " — no fuzz-testing results published to date"; "defense-in-depth" preserved but quantified in `docs/security-hardening-guide.md` §4: "three independent detection layers with documented bypass classes". **CaMeL claim toned down:** `post-session-guard.mjs:646` and `CLAUDE.md:184` now describe the implementation honestly — opportunistic byte-matching of truncated output fingerprints (first 200 bytes, SHA-256/16-hex tag); not semantic data-flow tracking; trivially bypassed by mutation, summarisation, or re-encoding. Inspired by CaMeL (DeepMind 2025) but not a CaMeL capability-tracking implementation. **Tests:** +24 (+8 pathguard multi-segment + 1 distributed-trifecta + 15 verdict/riskBand co-monotonicity sweep + 1 `riskScore({critical: 4}) === 93` anchor). 1511 tests (was 1487). All green. **Why:** the critical-review CISO perspective (§F) flagged overclaim language as a blocker for regulated environments — toning it down does not weaken the actual defenses; it lets users trust the documentation. | | **7.0.0** | 2026-04-19 | **Trustworthy scoring (BREAKING).** Three changes target the false-positive cascade on real codebases (scan of hyperframes.com gave `BLOCK / Extreme / 100` with ~70% noise). **1. Risk-score v2** (`scanners/lib/severity.mjs`) — severity-dominated, log-scaled within tier. Replaces sum-and-cap that collapsed every non-trivial scan to 100/Extreme. Tiers: critical → 70–95, high only → 40–65, medium only → 15–35, low only → 1–11. Verdict cutoffs realigned (BLOCK ≥65, WARNING ≥15) for band co-monotonicity. **2. Context-aware entropy scanner** — file-extension skip (`.glsl/.frag/.vert/.shader/.wgsl/.css/.scss/.sass/.less/.svg/.min.*/.map`) + 8 new line-suppression rules (GLSL keywords, CSS-in-JS templates, inline SVG, ffmpeg `filter_complex`, User-Agent strings, SQL DDL on dedicated lines, `throw new Error(\`...\`)`, markdown image URLs). Configurable via `.llm-security/policy.json` `entropy` section (thresholds, `suppress_extensions`, `suppress_line_patterns`, `suppress_paths`). Envelope `calibration` block reports skip counters + effective thresholds + policy source. **3. DEP typosquat allowlist expansion** — 22 npm + 5 PyPI entries for short-name tools that tripped Levenshtein on every modern codebase (`knip`, `oxlint`, `tsx`, `nx`, `rimraf`, `uv`, `ruff`, etc.). Synthesizer "Scan Calibration" section + "never override verdict" rule added. Legacy `riskScoreV1()` kept for reference. **CI pipelines with `--fail-on` thresholds may need recalibration.** 1487 tests (was 1461). | | **6.6.0** | 2026-04-18 | **JetBrains/IntelliJ plugin scanning.** `/security ide-scan` now covers JetBrains IDEs (IntelliJ IDEA, PyCharm, GoLand, WebStorm, RubyMine, PhpStorm, CLion, DataGrip, RustRover, Rider, Aqua, Writerside, Android Studio) — Fleet and Toolbox excluded. OS-aware discovery of `~/Library/Application Support/JetBrains/<IDE><version>/plugins/` (macOS), `%APPDATA%\JetBrains\...` (Windows), `~/.config/JetBrains/...` (Linux). Zero-dep parsers for `META-INF/plugin.xml` and `META-INF/MANIFEST.MF` with nested-jar extraction. 7 JetBrains-specific checks: theme-with-code, broad activation (`application-components`), `Premain-Class` instrumentation (HIGH — javaagent retransform), native binaries (`.so`/`.dylib`/`.dll`/`.jnilib`), long `<depends>` chains (supply-chain pressure), typosquat vs top JetBrains plugins, shaded-jar advisory. URL fetch for `plugins.jetbrains.com/plugin/<numericId>-<slug>` + direct `/plugin/download?pluginId=<xmlId>`; metadata resolves numericId → xmlId before download. `.kt`, `.groovy`, `.scala` added to `taint-tracer` code extensions. Reuses existing OS sandbox (`lib/vsix-sandbox.mjs` parameterized via `buildSandboxedWorker(..., workerPath)`). Knowledge: `knowledge/jetbrains-marketplace-api-notes.md`, expanded `knowledge/ide-extension-threat-patterns.md`, seeded `knowledge/top-jetbrains-plugins.json`. 1461 tests (was 1352). | diff --git a/plugins/llm-security/package.json b/plugins/llm-security/package.json index e07ea20..1396a8f 100644 --- a/plugins/llm-security/package.json +++ b/plugins/llm-security/package.json @@ -1,6 +1,6 @@ { "name": "llm-security", - "version": "7.1.0", + "version": "7.2.0", "description": "Security scanning, auditing, and threat modeling for Claude Code projects", "type": "module", "bin": { diff --git a/plugins/llm-security/scanners/ide-extension-scanner.mjs b/plugins/llm-security/scanners/ide-extension-scanner.mjs index b0d1f29..9ae42cc 100644 --- a/plugins/llm-security/scanners/ide-extension-scanner.mjs +++ b/plugins/llm-security/scanners/ide-extension-scanner.mjs @@ -49,7 +49,7 @@ import { scan as scanTaint } from './taint-tracer.mjs'; import { scan as scanMemoryPoisoning } from './memory-poisoning-scanner.mjs'; import { scan as scanSupplyChain } from './supply-chain-recheck.mjs'; -const VERSION = '7.1.0'; +const VERSION = '7.2.0'; const SCANNER = 'IDE'; // ---------------------------------------------------------------------------