fix(llm-security): SIG self-flagged the vendored commons it detects from

Scanning this repository with the SIG scanner produced 7 findings, 4 of them
on our own detection data: scanners/commons/CHANGELOG.md and
scanners/commons/signatures/malware-signatures.json. The ruleset that describes
xmrig and webshells is, byte for byte, a document containing those strings, so
the engine matched it as malware. EXCLUDED_PATH_RE already carried
knowledge/, tests/, docs/ and node_modules/ for exactly this reason; the
vendored commons arrived in v8 Phase 5 (bbada84) without being added.

One alternation branch closes it. Tests first: two cases added to
describe('signature-scanner: path exclusions'), both verified red against the
real scan() entry point before the regex changed.

Stated plainly, because it is a real cost and not a technicality: the branch is
`scanners\/commons` behind the existing `(^|\/)` prefix, so it matches that
two-segment path ANYWHERE in a target's relative path, not only at its root. A
webshell planted at vendor/scanners/commons/shell.php in a hostile repository is
therefore invisible to SIG. The second new test asserts that blind spot
deliberately, so it can never be discovered by accident. It is accepted because
anchoring at ^scanners/commons/ would miss the same payload one directory
deeper while re-opening the self-flag whenever the plugin is scanned from a
parent directory. TRG, AST, entropy and supply-chain still read these files;
only SIG identity-matching is blinded.

scanners/lib/supply-chain-data.mjs is NOT excluded. Its finding is a true
positive against real blocklist data.

Measured before: 7 findings. After: 3 (2 on STATE.md, 1 on
supply-chain-data.mjs). signature-scanner.test.mjs 23/23; custom-rules + e2e
54/54; golden-baseline 8/8 with suite-counts.json untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SBJVYzwch63Rpk1hii1cNM
This commit is contained in:
Kjell Tore Guttormsen 2026-08-13 21:41:09 +02:00
commit eceb71bbb3
3 changed files with 59 additions and 2 deletions

View file

@ -25,7 +25,18 @@ import { SIGNATURE_RULES, compileRules } from './lib/malware-signatures.mjs';
// self-flag. `knowledge/` is kept even though the ruleset itself moved to the
// vendored commons in v8 Phase 5 — a scanned target's own knowledge/ directory
// is as likely to hold ruleset-shaped prose as ours was.
const EXCLUDED_PATH_RE = /(^|\/)(knowledge|tests|docs|node_modules)\//i;
//
// `scanners/commons/` is the vendored ruleset itself (v8 Phase 5). Its CHANGELOG
// and malware-signatures.json describe the malware they detect, so SIG matched
// them as malware: scanning this repo yielded 4 findings on our own detection
// data. Note the alternation matches the two-segment path ANYWHERE in the
// relative path, not only at the root — so a webshell planted at
// `vendor/scanners/commons/shell.php` in a hostile repo is invisible to SIG.
// That blind spot is accepted knowingly: anchoring at `^scanners/commons/`
// would miss the same payload one directory deeper anyway, while re-opening the
// self-flag whenever the plugin is scanned from a parent directory. Other
// scanners still read these files; only SIG identity-matching is blinded.
const EXCLUDED_PATH_RE = /(^|\/)(knowledge|tests|docs|node_modules|scanners\/commons)\//i;
const DEFAULT_FAMILIES = ['webshell', 'reverse_shell', 'cryptominer', 'hacktool'];