chore(llm-security): v7.8.1 — security patch release
Version bump + release notes for the auto-cleaner command-injection fix
(f083cda). Security patch only; no feature changes. 1865 tests, 0 fail.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQyMTQfyrsAapaCMPxTtQ
This commit is contained in:
parent
f083cdad2e
commit
55d01d1656
6 changed files with 65 additions and 5 deletions
|
|
@ -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.8.0"
|
||||
"version": "7.8.1"
|
||||
}
|
||||
|
|
|
|||
31
CHANGELOG.md
31
CHANGELOG.md
|
|
@ -6,6 +6,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [7.8.1] - 2026-07-18
|
||||
|
||||
Security patch. Fixes a CRITICAL command-injection defect in the auto-cleaner
|
||||
that shipped in v7.8.0. No feature changes. 1865 tests, 0 fail.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **CRITICAL — command injection via scanned filename**
|
||||
(`scanners/auto-cleaner.mjs`). `validateContent()` syntax-checked
|
||||
`.mjs`/`.js`/`.cjs` candidates with
|
||||
``execSync(`node --check "${tmpPath}"`)``, where `tmpPath` derives from the
|
||||
**untrusted scanned-repo filename**. The F-2 guard added in v7.8.0 checks
|
||||
path containment but neither strips nor quotes shell metacharacters, and a
|
||||
filename containing `"` closes the interpolated quote. A repository shipping
|
||||
a file named ``x";<command>;".mjs`` therefore turned `/security clean` —
|
||||
whose live mode is the documented default — into arbitrary command execution
|
||||
on the operator's machine. Verified with a live proof-of-concept before the
|
||||
fix. Both subprocess call sites (the syntax check, and the CLI's
|
||||
scan-orchestrator fallback) now use `spawnSync` with an argv array, so no
|
||||
shell parses the path.
|
||||
- **Defense-in-depth:** `applyFixes()` now refuses findings whose `file` field
|
||||
carries shell or control metacharacters, reporting them as `skipped` rather
|
||||
than passing them to any sink. This guards against a future call site
|
||||
re-introducing string interpolation.
|
||||
|
||||
### Changed
|
||||
|
||||
- `validateContent` is exported from `scanners/auto-cleaner.mjs` so the
|
||||
regression suite can exercise the subprocess sink directly, independently of
|
||||
the `applyFixes` guard that would otherwise mask it.
|
||||
|
||||
## [7.8.0] - 2026-06-20
|
||||
|
||||
Three new deterministic deep-scan scanners (TRG/SIG/AST) targeting the
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# LLM Security Plugin (v7.8.0)
|
||||
# LLM Security Plugin (v7.8.1)
|
||||
|
||||
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). 1820+ 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.0: see `docs/version-history.md` — read on demand.
|
||||
Release notes for v7.0.0 → v7.8.1: see `docs/version-history.md` — read on demand.
|
||||
|
||||
**v7.8.1 highlights** — Security patch, no feature changes. Fixes a CRITICAL command injection in `scanners/auto-cleaner.mjs`: `validateContent()` syntax-checked candidate `.mjs`/`.js`/`.cjs` content via ``execSync(`node --check "${tmpPath}"`)``, where `tmpPath` derives from the **untrusted scanned-repo filename**. The v7.8.0 F-2 guard checks path containment but neither strips nor quotes shell metacharacters, so a file named ``x";<command>;".mjs`` closes the interpolated quote and injects a command; since `/security clean` runs live by default, scanning a hostile repository sufficed for arbitrary local command execution (live-PoC verified). Both subprocess sites — the syntax check and the CLI's inline scan-orchestrator fallback — now use `spawnSync` with an argv array, so no shell parses a path. Defense-in-depth: `applyFixes()` refuses findings whose `file` carries shell/control metacharacters, surfaced as `skipped`. `validateContent` is now exported so regression tests can drive the sink directly — the guard would otherwise mask a re-introduced shell.
|
||||
|
||||
**v7.8.0 highlights** — Three new deterministic deep-scan scanners (TRG/SIG/AST) targeting the skills/agents attack surface, each with its own finding prefix, OWASP/AST mapping, policy block, and graceful-skip behaviour. **TRG** (`scanners/trigger-scanner.mjs`) inspects command/agent/skill `name` + `description` frontmatter for activation-surface abuse — `TRG-shadow` (name collides with a built-in and intercepts it), `TRG-baiting` (maximally-activating phrases that bait indiscriminate invocation), `TRG-broad` (generic name + universal-applicability claim); descriptions pass the decode pipeline first so obfuscated baiting still trips (LLM06/AST04). **SIG** (`scanners/signature-scanner.mjs`) is a pure-Node known-malware *identity* engine (webshells, reverse shells, cryptominers, hacktools) that tests each signature against both raw bytes and the decode pipeline, so obfuscated known-malware a byte-matcher misses is still caught; rules in `knowledge/signatures.json` (LLM03/LLM02). **AST** (`scanners/ast-taint-scanner.mjs`) shells out to a PARSE-ONLY `python3` helper (`scanners/lib/py-ast-taint.py`) for scope-aware Python taint analysis, falling back to the regex `taint-tracer.mjs` when `python3` is absent; the helper only `ast.parse`s the target, never executes it (LLM01/LLM02/AST02). Built behind a security-fix gate (F-1/F-2/F-3 landed first). No existing scanner, hook, or command behaviour changes.
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
*AI-generated: all code produced by Claude Code through dialog-driven development. [Full disclosure →](../../README.md#ai-generated-code-disclosure)*
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
|
@ -628,6 +628,7 @@ demonstrations — each with `README.md`, fixture, run script, and
|
|||
|
||||
| Version | Date | Highlights |
|
||||
|---------|------|------------|
|
||||
| **7.8.1** | 2026-07-18 | **Auto-cleaner command-injection fix (CRITICAL).** `scanners/auto-cleaner.mjs` syntax-checked candidate `.mjs`/`.js`/`.cjs` content via ``execSync(`node --check "${tmpPath}"`)``, where `tmpPath` derives from the untrusted scanned-repo **filename**. The v7.8.0 F-2 guard checks path containment but does not strip or quote shell metacharacters, so a file named ``x";<command>;".mjs`` closes the interpolated quote and injects a command — and `/security clean` runs live by default, making a hostile repository sufficient for arbitrary local command execution. Reproduced with a live PoC before the fix. Both subprocess sites (syntax check + the CLI scan-orchestrator fallback) now use `spawnSync` with an argv array, so no shell parses a path. Defense-in-depth: `applyFixes()` refuses findings whose `file` carries shell/control metacharacters, reported as `skipped`. Regression coverage is split across both layers so the guard cannot mask a re-introduced shell in the sink. No feature changes. 1865 tests, 0 fail. |
|
||||
| **7.8.0** | 2026-06-20 | **TRG/SIG/AST deep-scan scanners.** Three new deterministic deep-scan scanners targeting the skills/agents attack surface, each with its own finding prefix, OWASP/AST mapping, policy block, and graceful-skip behaviour. **TRG** (`scanners/trigger-scanner.mjs`) inspects command/agent/skill `name` + `description` frontmatter for activation-surface abuse: `TRG-shadow` (name collides with a built-in and intercepts it), `TRG-baiting` (maximally-activating phrases that bait indiscriminate invocation), `TRG-broad` (generic name + universal-applicability claim); descriptions pass the decode pipeline first so obfuscated baiting still trips (LLM06/AST04). **SIG** (`scanners/signature-scanner.mjs`) is a pure-Node known-malware *identity* engine (webshells, reverse shells, cryptominers, hacktools) that tests each signature against both raw bytes and the decode pipeline (base64/hex/url/entity/unicode, homoglyph fold, rot13), so obfuscated known-malware a byte-matcher misses is still caught; rules ship in `knowledge/signatures.json` (LLM03/LLM02). **AST** (`scanners/ast-taint-scanner.mjs`) shells out to a PARSE-ONLY `python3` helper (`scanners/lib/py-ast-taint.py`) for variable-level, scope-aware Python taint analysis — higher recall than the ~70% regex `taint-tracer.mjs` — and falls back to the regex tracer when `python3` is unavailable, so the scan never hard-fails; the helper only `ast.parse`s the target and never executes it (LLM01/LLM02/AST02). Built behind a security-fix gate (F-1/F-2/F-3 shell-injection + path-traversal fixes landed first). 1863 tests, 0 fail. |
|
||||
| **7.7.2** | 2026-05-19 | **Language consistency pass.** Norwegian had crept into surface text across v7.5-v7.7. Per the `~/.claude/CLAUDE.md` convention (English for code and documentation, Norwegian for dialog only), this release translates: the HTML Report-step appended by all 18 skill commands, the canonical CLI renderer `scripts/lib/report-renderers.mjs` (display strings + JS comments), the playground UI strings, the `skill-scanner-agent` and `mcp-scanner-agent` system prompts, the Recent versions table and playground architecture prose in this README, the v7.7.x highlights in `CLAUDE.md`, and the llm-security entries in the marketplace root `README.md` + `CLAUDE.md`, plus six table cells in `docs/scanner-reference.md`. Demo-state fixture content for the `dft-komplett-demo` project (intentional Norwegian persona) and regex alternations that match Norwegian-language report markdown (`/^high\|^høy/`, `/resolution\|løsning/`) were preserved. No scanner, hook, or behavior changes — purely surface text. |
|
||||
| **7.7.1** | 2026-05-18 | **Playground UX strip.** Operator feedback immediately after v7.7.0: the home surface led with three project tracks (Re-onboard / New project / Command catalog) even though the catalog was the important entry point. Minimum strip delivered as three atomic commits (`b732eee` + `2a6f73f` + `81b7beb`): (1) the router always forces `activeSurface = 'catalog'` (the onboarding/home/project render functions are preserved in source but no longer routable); (2) the topbar `Home` and `Re-onboard` buttons removed, `Catalog` retained; (3) the breadcrumb org-name (`shared.organization.name` from demo state) replaced with a static `llm-security` neutral scope anchor. Fix: the hardcoded `'Plugin v7.6.1'` on line 6933 of `renderHome` (template literal not caught by the v7.7.0 grep) was synced. The onboarding concept is documented as a v7.8.0 candidate (per-command context injection) in `ROADMAP.md`. No scanner or hook behavior changes. |
|
||||
|
|
|
|||
|
|
@ -2,6 +2,32 @@
|
|||
|
||||
Per-release notes for v7.0.0 onward. Imported from `CLAUDE.md` via `@docs/version-history.md`.
|
||||
|
||||
## v7.8.1 — Auto-cleaner command-injection fix (CRITICAL)
|
||||
|
||||
Security patch for a CRITICAL defect introduced with the v7.8.0 auto-cleaner
|
||||
hardening pass. No feature changes; full suite green at 1865/0.
|
||||
|
||||
`scanners/auto-cleaner.mjs` validated candidate `.mjs`/`.js`/`.cjs` content by
|
||||
shelling out to ``node --check "${tmpPath}"`` via `execSync`. `tmpPath` is
|
||||
derived from the finding's `file` field — an untrusted scanned-repo filename.
|
||||
The F-2 containment guard that landed in v7.8.0 verifies the resolved path
|
||||
stays inside the scanned tree, but performs no shell-metacharacter handling, so
|
||||
a filename whose `"` terminates the interpolated quote injects a second
|
||||
command. Because `/security clean` runs in live mode by default, scanning a
|
||||
hostile repository was sufficient to execute attacker-chosen commands locally.
|
||||
The defect was reproduced with a live proof-of-concept before being fixed.
|
||||
|
||||
Both subprocess sites now use `spawnSync` with an argv array — the syntax check
|
||||
and the CLI's inline scan-orchestrator fallback — so no shell interprets a path.
|
||||
As defense-in-depth, `applyFixes()` additionally refuses any finding whose
|
||||
`file` carries shell or control metacharacters, surfacing it as `skipped`.
|
||||
|
||||
Regression coverage is deliberately split across both layers
|
||||
(`tests/scanners/auto-cleaner-rce.test.mjs`): one test drives `validateContent`
|
||||
directly to prove the shell is gone, because the metacharacter guard would
|
||||
otherwise stop the hostile input before it reached the sink and the test would
|
||||
pass without testing the fix.
|
||||
|
||||
## v7.8.0 — Trigger, signature, and AST-taint scanners
|
||||
|
||||
Three new deterministic deep-scan scanners (TRG/SIG/AST), each with its own
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "llm-security",
|
||||
"version": "7.8.0",
|
||||
"version": "7.8.1",
|
||||
"description": "Security scanning, auditing, and threat modeling for Claude Code projects",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue