chore(release): v8.1.0 — antivirus surface

Version sync to 8.1.0: package.json, .claude-plugin/plugin.json, README
badge + Recent versions row + self-scan counts, CLAUDE.md header +
highlights (and the GitHub-only remote-scan wording git-clone no longer
has), CHANGELOG [8.1.0] covering S0-S3c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-22 20:29:54 +02:00
commit 7c5514e5dd
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
5 changed files with 106 additions and 7 deletions

View file

@ -6,6 +6,102 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased]
## [8.1.0] - 2026-09-22
Antivirus surface. A Windows user should be able to clone the repository and
install the plugin without Defender or a similar product quarantining a file,
and the plugin should still find what it finds today. No payload now sits on
disk as a file that would run it: test fixtures and the malicious-plugin demo
are stored encoded or built from fragments, and exist only in a temp directory
while a test or the demo runs. Two scope fixes ride along: a scanned repository
no longer controls its own suppression or detection thresholds. Detection
tables untouched; golden baseline identical. 2286 tests, 2280 pass, 6 skipped,
0 fail.
### Added
- **`tests/av-surface.test.mjs`** — a gate that fails the suite if a payload
comes back to disk. Five probes over `git ls-files`: (a) files that match
the webshell / reverse-shell / cryptominer signatures in a file type that
would run them, plus (a2) the same families as literals in test sources;
(b) base64 blobs that decode to a shell command; (c) Unicode Tag and
zero-width characters outside the conformance corpus; (d) whole malicious
fixture trees on disk; (e) runnable payload literals in the files Claude
Code loads every session (agents, commands, skills, hooks, knowledge).
- **README § Antivirus false positives** — what the repository contains and
why, how to restore a quarantined file, where to report a false positive to
Microsoft, and a sparse-checkout recipe for users who only want the scanners
and hooks. No exclusion is recommended.
### Changed
- **Test payloads are built at test time, never stored.** The poisoned
fixtures for the signature, memory-poisoning and trigger scanners are
written into a temp directory from split strings or rot13; zero-width test
lines use `String.fromCodePoint`. `tests/fixtures/signature-scan/poisoned/`
is gone. The sha256 of every removed file is asserted against what the
builders produce, so the content is provably unchanged.
- **The malicious-skill demo is stored encoded.** `examples/malicious-skill-demo/`
and `examples/poisoned-claude-md/` ship as encoded archives and are written
to a temp directory when run (`materialize.mjs` prints the demo's path).
The README and the demo's security assessment describe the base64 payloads
instead of showing decodable lines.
- **`tests/fixtures/ast-scan/*.py` are materialized at test time** (all five).
- **Skill-scanner detection lists moved** from `agents/skill-scanner-agent.md`
to `knowledge/skill-threat-patterns.md` § Detection Rules, a file the four
scanning commands already hand the agent. A quarantined agent file would
break the plugin for the user; a knowledge file would not. Runnable
one-liners in `knowledge/*.md` are written as descriptions where that costs
no precision.
- **Two hook rule names split** so no download-into-shell literal sits on disk
in `hooks/scripts/pre-bash-destructive.mjs`. Hook stderr is byte-identical.
- **`.llm-security-ignore` now covers the MEM, SIG, AST, TRG and UNI
prefixes**, and the README's self-scan numbers are measured, not claimed:
a fresh clone scans WARNING 61/100 with 58 findings (the earlier "0 findings
(ALLOW)" was false).
### Fixed
- **`.llm-security-ignore` is honoured only for the caller's own working
tree.** A scanned repository with `**` in its own ignore file turned
WARNING (1 finding) into ALLOW (0). The file is now read only when the
target is the current working directory or below it, and never when the
target is under the system temp directory (where remote clones land).
Otherwise it is ignored with one stderr line.
- **`.llm-security/policy.json` — including `sig.custom_rules_path`,
`ast.python_path` and `ci.failOn` — is honoured only for the caller's own
working tree**, by the same rule (`scanners/lib/own-working-tree.mjs`). A
foreign target could raise its own entropy thresholds out of reach or add
signature rules. Entropy's `calibration.policy_source` now says `defaults`
when the file was present but ignored.
**Behaviour change:** running a scanner with a target outside the current
working directory no longer applies that target's `policy.json`. Hooks,
and CI that runs `scan .` from the repository root, are unaffected.
- **`scanners/lib/git-clone.mjs` accepts HTTPS repository URLs on any host**,
not only GitHub, so the README's Forgejo example works. SSH URLs remain
GitHub-only.
### Known open
- "Own working tree" means the target is the working directory or below it.
A foreign clone that sits under the user's working directory (for example
with the working directory at `$HOME`, or a cloned vendor folder inside a
project) still has its `policy.json`, ignore file and custom SIG rules read.
Clones under the temp directory and targets outside the working directory
are covered.
- The README's self-scan suppression count drifts by one per commit:
`git-forensics` looks at the last 50 commits, and each new commit pushes one
older finding out of that window.
## [8.0.0] - 2026-09-18
Major release. The breaking part is small and was announced in v7.3.0: four