chore(llm-security): v7.8.2 — security patch release
Bumps package.json, .claude-plugin/plugin.json and the README badge to 7.8.2; adds the release entry to CHANGELOG.md, docs/version-history.md, the README recent-versions table and the CLAUDE.md highlights block. Also fixes test pollution introduced with the ide-extension regression suite: its temp roots used an `llmsec-jb-plugin-` prefix, and jetbrains-parser.test.mjs asserts globally that no `llmsec-jb-*` directory survives anywhere in tmpdir. The shared prefix made that assertion fail depending on test order — it passed on the first full run and failed on the next. Prefix is now `llmsec-nullmanifest-`. npm test: 1901/1901 green, three consecutive runs. 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
566c281b56
commit
f4c65070ff
7 changed files with 146 additions and 6 deletions
67
CHANGELOG.md
67
CHANGELOG.md
|
|
@ -6,6 +6,73 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [7.8.2] - 2026-07-18
|
||||
|
||||
Security patch. Fixes five defects from the v7.8.1 completion review, four of
|
||||
which caused a scanner or hook to fail silently — reporting success while the
|
||||
check it was named for did not run. No feature changes. 1901 tests, 0 fail.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **HIGH — bare root/home targets bypassed the rm block**
|
||||
(`hooks/scripts/pre-bash-destructive.mjs`). The BLOCK rule's target
|
||||
alternation ended in a shared `\b`, and a word boundary cannot hold after `/`
|
||||
or `~` at end-of-command. `rm -rf /`, `rm -rf ~`, `rm -rf /*`, `rm -fr /` and
|
||||
the sudo-prefixed forms all fell through to WARN (exit 0) — advisory only,
|
||||
command executed. Only targets starting with a word character (`/etc`,
|
||||
`/usr`) were ever blocked. `\b` now applies to the `$HOME` alternative alone,
|
||||
where it is meaningful.
|
||||
|
||||
- **HIGH — entropy suppression keyed off the absolute path**
|
||||
(`scanners/entropy-scanner.mjs`). The test/fixture suppression rule matched
|
||||
`/(test|spec|fixture|mock|__test__|__spec__)/i` against the **absolute**
|
||||
path, so any directory name above the scan root silenced every entropy
|
||||
finding in the entire target while still reporting status `ok`. The rule now
|
||||
keys off the path relative to the scan root.
|
||||
|
||||
- **HIGH — one unparseable JetBrains plugin crashed the whole ide-scan**
|
||||
(`scanners/ide-extension-scanner.mjs`). The two manifest parsers disagree on
|
||||
how they signal failure: `parseVSCodeExtension` returns bare `null`,
|
||||
`parseIntelliJPlugin` returns a truthy `{ manifest: null, warnings }`. Only
|
||||
the bare-null form was guarded, so every JetBrains failure path dereferenced
|
||||
`manifest.hasSignature`; the TypeError escaped through `mapConcurrent`'s
|
||||
unguarded `Promise.all` and aborted the scan of every other installed
|
||||
extension. Guard widened, plus per-extension fault isolation at the call
|
||||
site.
|
||||
|
||||
- **HIGH — obfuscated injections were reported but not stripped**
|
||||
(`scanners/content-extractor.mjs`). `stripInjection` scanned both the raw and
|
||||
the decoded text but removed matches only via a literal replace against the
|
||||
raw text. For a decoded-only match, `match[0]` is the decoded string, which
|
||||
by construction does not occur in the raw text — so the replace was a silent
|
||||
no-op and the encoded payload reached the LLM agent verbatim via
|
||||
`sanitized_content`, alongside a finding announcing it. Every obfuscation the
|
||||
normalizer exists to defeat was affected. Decoded-only matches are now
|
||||
removed by redacting the source line; multi-line payloads that cannot be
|
||||
attributed are flagged `unstripped: true` rather than left silently.
|
||||
|
||||
- **Out-of-range numeric character reference emptied a plugin.xml field**
|
||||
(`scanners/lib/ide-extension-parser.mjs`). `decodeEntities` guarded
|
||||
`parseInt` with `Number.isFinite`, which bounds nothing, so any code point
|
||||
above `0x10FFFF` made `String.fromCodePoint` raise `RangeError`. The
|
||||
no-throw contract held (the per-field `safe()` wrapper catches it), but the
|
||||
affected field was discarded and replaced with `''`. Undecodable references
|
||||
are now left literal. Filed as HIGH; it is lower — such a document is not
|
||||
well-formed XML, so the plugin would not load in IntelliJ either.
|
||||
|
||||
### Changed
|
||||
|
||||
- `stripInjection` (content-extractor) and `scanOneExtension` (ide-extension-
|
||||
scanner) are exported for testing; `content-extractor.mjs` runs `main()`
|
||||
behind the standard `isMain` guard so importing it no longer executes the
|
||||
CLI. The remote-scan injection boundary had no direct test coverage before
|
||||
this release.
|
||||
|
||||
### Removed
|
||||
|
||||
- `tests/hooks/probe-rm.mjs` — a self-labelled temporary debug probe with no
|
||||
assertions, pointing at a hardcoded path into the installed marketplace copy.
|
||||
|
||||
## [7.8.1] - 2026-07-18
|
||||
|
||||
Security patch. Fixes a CRITICAL command-injection defect in the auto-cleaner
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue