test(v8.1.3): red tests for plan points 1, 2, 3, 5 and addenda a-c

Each test fails on fd7de23:
- own-working-tree: venv site-packages, vendor/, config-dir skills/
  (punkt 1); ~/.claude/plugins next to $CLAUDE_CONFIG_DIR and a leading
  ~ in the variable (punkt 2); NODE_MODULES case variant and a
  case-mismatched parent segment (punkt 3, closes v8.1.2 punkt 4).
- watch-cron-scope: a watched project's own ignore file is honored
  (punkt 5).
- av-surface (b2): no runnable base64-to-shell line with a short
  command blob (addendum a; 3 hits today).
- doc-consistency: scanner-reference Knowledge Files matches knowledge/
  (addendum b); ci-cd-guide makes no offline claim (addendum c).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-23 11:29:22 +02:00
commit b62c3e60f5
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
4 changed files with 290 additions and 0 deletions

View file

@ -36,6 +36,12 @@
// caught the second half of a payload split across two blobs in
// examples/malicious-skill-demo/security-assessment.md, which the S0
// rule missed. All 7 command blobs the S0 rule saw still hit.
// (b2) a line that holds a base64 decode piped into a shell AND a base64
// blob of ANY length (8+ characters) decoding to a command shape or a
// recursive `rm`: the whole runnable line, comments included. (b) alone
// misses it below 24 characters: a home-directory deletion encodes to 16.
// Added in v8.1.3 (2026-09-23, order 20260923T092223Z, tillegg a) after
// the README fact-check found one in a comment.
// (c) a Unicode Tag (U+E0000-U+E007F), zero-width (U+200B-U+200D, U+2060,
// U+FEFF) or bidi-control (U+202A-U+202E, U+2066-U+2069) codepoint in a
// TEXT file outside scanners/commons/conformance/**. Binary files (a NUL
@ -91,6 +97,9 @@ const BASE64_BLOB = /[A-Za-z0-9+/]{24,}={0,2}/g;
const PRINTABLE = /^[\x20-\x7e\t\r\n]+$/;
const COMMAND_SHAPE = /^\s*(?:curl|wget|bash|sh|python[0-9.]*|eval|nc)\b|\|\s*(?:bash|sh)\b|\$\(/;
const SHORT_BASE64_BLOB = /[A-Za-z0-9+/]{8,}={0,2}/g;
const DELETION_SHAPE = /\brm\s+-[a-zA-Z]*[rR]/;
const CARRIER = /[\u{E0000}-\u{E007F}\u200B-\u200D\u2060\uFEFF\u202A-\u202E\u2066-\u2069]/u;
const SESSION_LOADED = /^(?:agents|commands|hooks)\//;
@ -127,6 +136,7 @@ function measureAvSurface() {
const rules = SIGNATURE_RULES.filter(r => PAYLOAD_FAMILIES.has(r.family));
const a = [];
const b = [];
const b2 = [];
const c = [];
const a2 = [];
const e = [];
@ -184,6 +194,16 @@ function measureAvSurface() {
}
}
text.split('\n').forEach((line, i) => {
if (!BASE64_PIPE_TO_SHELL.test(line)) return;
for (const m of line.matchAll(SHORT_BASE64_BLOB)) {
const decoded = Buffer.from(m[0], 'base64').toString('latin1');
if (PRINTABLE.test(decoded) && (COMMAND_SHAPE.test(decoded) || DELETION_SHAPE.test(decoded))) {
b2.push(`${rel}:${i + 1} :: ${decoded.slice(0, 60).replace(/\s+/g, ' ')}`);
}
}
});
if (!rel.startsWith(CONFORMANCE) && CARRIER.test(text)) c.push(rel);
if (TEST_SOURCE.test(rel)) {
@ -205,6 +225,7 @@ function measureAvSurface() {
testSources,
b,
bFiles: new Set(b.map(x => x.split(' :: ')[0])).size,
b2,
c,
d,
e,
@ -234,6 +255,11 @@ describe('av-surface: tracked tree carries no AV-triggering payloads', () => {
assert.deepEqual(m.b, [], report('base64 blobs', m.b));
});
it(`(b2) no runnable base64-to-shell line with a short command blob (of ${m.textFiles} text files)`, (t) => {
t.diagnostic(`b2=${m.b2.length}`);
assert.deepEqual(m.b2, [], report('runnable base64-to-shell lines', m.b2));
});
it(`(c) no Tag/zero-width/bidi carrier outside the conformance corpus (of ${m.textFiles} text files)`, (t) => {
t.diagnostic(`c=${m.c.length}`);
assert.deepEqual(m.c, [], report('files with a carrier codepoint', m.c));