fix(llm-security): normalization/discovery evasion + SIG embedded-base64 & custom rules (#21,#23,#30,#36,#42,#52,#55)
#21 the bash normalizer decoded only \xHH, leaving ANSI-C octal/\u/\U forms literal so canonical rm/curl never surfaced; now decodes all three. #23 file-discovery keyed on extname so .env.local/.env.example (extname .local/.example) were silently skipped; now matches multi-part suffixes. #42 a legitimate leading UTF-8 BOM was flagged HIGH (and the tool's own auto-cleaner refused to strip it); pos-0 BOM now excepted. #52 collapseLetterSpacing used a literal space, letting multi-space/tab spacing evade; now [ \t]+. #55 redact(_,60,0) did slice(-0) and leaked the whole unredacted URL; showEnd===0 now means no tail. #30 embedded base64 (const x = "<base64>") never satisfied the whole-string decode, so the SIG identity engine never saw it; added decodeEmbeddedBase64 as an OPT-IN param on normalizeForScan (default off — appending a decoded copy would double-count per-match findings, e.g. content-extractor's injection scan) and enabled it only in signature-scanner, which dedups variants. #36 signature-scanner ignored the documented sig.custom_rules_path policy option; now loads+merges custom rules through the same family filter. Suite 2004/0. 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
b224e18b42
commit
21c6c2b534
11 changed files with 602 additions and 42 deletions
|
|
@ -86,6 +86,26 @@ describe('signature-scanner: poisoned', () => {
|
|||
assert.ok(rev, `Expected a reverse-shell finding on revshell.sh, got: ${result.findings.map(f => f.file).join('; ')}`);
|
||||
});
|
||||
|
||||
it('flags a webshell base64-EMBEDDED in surrounding code (#30, decodeEmbedded)', async () => {
|
||||
// The whole-string decode pipeline only fires when the ENTIRE file is one
|
||||
// base64 blob (webshell-b64.txt). #30: a payload embedded in surrounding
|
||||
// code (const x = "<base64>") must also reach the SIG decode pipeline via
|
||||
// decodeEmbedded. Regression guard for the signature-scanner opt-in flag.
|
||||
const payload = readFileSync(join(POISONED_FIXTURE, 'webshell.php'), 'utf8');
|
||||
const b64 = Buffer.from(payload).toString('base64');
|
||||
const dir = mkdtempSync(join(tmpdir(), 'sig-embed-b64-'));
|
||||
try {
|
||||
writeFileSync(join(dir, 'loader.js'), `const p = "${b64}";\nrun(atob(p));\n`);
|
||||
resetCounter();
|
||||
const d = await discoverFiles(dir);
|
||||
const result = await scan(dir, d);
|
||||
const hit = result.findings.find(f => f.file.includes('loader.js'));
|
||||
assert.ok(hit, `Expected the embedded-base64 webshell to be flagged, got: ${result.findings.map(f => f.file).join('; ')}`);
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('all findings have required fields', async () => {
|
||||
const result = await scan(POISONED_FIXTURE, discovery);
|
||||
assert.ok(result.findings.length >= 3, `expected >= 3 findings, got ${result.findings.length}`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue