# LLM Security Plugin (v8.1.1) Security scanning, auditing, and threat modeling for Claude Code projects. 5 frameworks: OWASP LLM Top 10, Agentic AI Top 10 (ASI, 2026 edition), Skills Top 10 (AST), MCP Top 10, AI Agent Traps (DeepMind). 2250+ unit, integration, and end-to-end tests (`tests/e2e/` covers the multi-hook attack chain, multi-session state simulation, and the full scan-orchestrator pipeline); mutation-testing coverage not published. Release notes for v7.0.0 → v7.8.2: see `docs/version-history.md` — read on demand. **v8.1.1 highlights** — Patch closing the v8.1.0 follow-up list; detection tables, golden baseline and hooks untouched. "Own working tree" (`scanners/lib/own-working-tree.mjs`) now also requires the target to share cwd's git root (nearest `.git`, dir or file; none for both), so a clone, submodule or worktree *under* cwd is foreign and its `.llm-security-ignore` / `policy.json` / custom SIG rules are ignored — closes v8.1.0's known-open item (`tests/lib/own-working-tree.test.mjs`, `tests/scanners/nested-clone-scope.test.mjs`). `ci.failOn` / `ci.compact` from `policy.json` got a real test (the old one never read the policy). README and `.llm-security-ignore` no longer state self-scan counts that drift per commit (git-forensics' 50-commit window). `/security scan` description names the accepted URLs. Known open: a target with no `.git` of its own (`node_modules/`, plugin-cache copy, tarball export) under cwd still counts as own. Windows/Defender quarantine remains **not measured** (no Windows machine). 2306 tests. **v8.1.0 highlights** — Antivirus surface: a Windows user can clone and install without Defender quarantining a file, and detection is unchanged. No payload sits on disk as a file that would run it — test fixtures (signature, memory-poisoning, trigger, `ast-scan/*.py`) are built in a temp dir at test time from split strings/rot13, the malicious-skill demo and `poisoned-claude-md` ship as encoded archives (`materialize.mjs`), zero-width test lines use `String.fromCodePoint`; sha256 of every removed file asserted. Gate: `tests/av-surface.test.mjs`, probes (a)/(a2) SIG payloads, (b) base64→shell command, (c) Tag/zero-width outside the conformance corpus, (d) malicious trees on disk, (e) runnable literals in session-loaded files. Skill-scanner detection lists moved from `agents/skill-scanner-agent.md` to `knowledge/skill-threat-patterns.md` § Detection Rules (a quarantined agent file breaks the plugin). README § Antivirus false positives (restore, report, sparse checkout; no exclusions recommended). Scope fixes: `.llm-security-ignore` and `.llm-security/policy.json` (incl. `sig.custom_rules_path`, `ast.python_path`, `ci.failOn`) are honoured only for the caller's own working tree (`scanners/lib/own-working-tree.mjs`: target = cwd or below, never under tmpdir) — a foreign target's file is ignored with one stderr line. `git-clone.mjs` accepts HTTPS on any host. Signature tables and golden baseline untouched. Known open: a foreign clone *under* cwd still counts as own tree. 2286 tests. **v8.0.0 highlights** — Breaking cleanup + commons foundation. BREAKING: the four `LLM_SECURITY_*` env-vars deprecated in v7.3.0 (`INJECTION_MODE`, `TRIFECTA_MODE`, `ESCALATION_WINDOW`, `AUDIT_LOG`, plus `DEPRECATION_QUIET`) are removed — `.llm-security/policy.json` is the only source and a removed variable is **inert** (no warning, silently back to default); `riskScoreV1()` + `SEVERITY_WEIGHTS_V1` deleted (`riskScore()` v2 untouched). Structural, behaviour-preserving: five detection tables are now built from the pull-only vendored subtree `scanners/commons/` (`llm-security-commons`) instead of source literals — codepoint carriers (`scanners/lib/codepoints.mjs`), `OWASP_MAP` (`owasp-map.mjs`), the 83 injection patterns (`injection-lexicon.mjs`), the 19 fixed secret shapes (`secret-egress.mjs`), the 7 SIG rules (`malware-signatures.mjs`; `knowledge/signatures.json` removed). Each swap was measured position-by-position first and diffed record-for-record against the golden baseline (`scripts/golden-baseline.mjs`, `tests/golden/`). The commons root is resolved from the plugin directory only, **never** from a scanned target's policy (a substitutive override would let a hostile repo empty the detection corpus). **Loud failure is contract:** an unresolvable injection lexicon or SIG ruleset writes one stderr line and never throws — an empty table would be the v7.8.2 defect class (clean report, nothing run). Commons conformance spec 1.1 implemented (`tests/lib/conformance-corpus.test.mjs`; not-applicable verdict, derived declaration, anti-narrowing floor). Fixes: `