The S0 rule fired on 'http' anywhere in decoded text and flagged an SVG
data URI (xmlns) in the hyperframes-like skill-scan fixture - markup, not
a command. PM decision for S2: the decoded text must start with a command
word or contain a pipe into a shell or $(. Measured before any blob was
removed: 8 blobs/7 files -> 8 blobs/6 files; SVG out, one split-payload
fragment in security-assessment.md newly caught, all 7 command blobs kept.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(a) keeps .mjs/.js out of its denominator, so contiguous payload literals in
test sources were ungated. a2 walks tests/**/*.{mjs,js} (tests/golden/**
excluded) and matches the webshell/reverse_shell/cryptominer SIG rules on raw
text. Measured red: a2=3 (scan-pipeline e2e, signature-scanner,
signature-scanner-custom-rules) of 116 test sources.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tests/av-surface.test.mjs walks git ls-files and fails on four surfaces a
clone or the plugin cache puts on a user's disk: (a) own SIG payloads
(webshell/reverse_shell/cryptominer) in a runnable file type, (b) base64
blobs decoding to a shell command, (c) Tag/zero-width/bidi carriers in text
files outside the conformance corpus, (d) known payload trees.
Red on purpose (order S0): it is the failing test for S1-S3. Measured on
this tree: a=3 b=9 (8 files) c=5 d=5. Chosen definitions are documented in
the file header: .mjs/.js/.cjs/.json and scanners/commons/** are outside (a)
so the untouchable signature tables stay out of a gate that must reach
zero; binaries are outside (c) because decoding PNG/WOFF2 as UTF-8 yields
the codepoints by chance.
PLAN.md is local-only, so .gitignore now names it. No production code, no
fixtures, no signature tables touched; golden baseline unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>