loadPolicy() read .llm-security/policy.json from whatever root it was
given, and every scanner passes the SCANNED TARGET: scan-orchestrator
(policyRoot = resolve(args.target)), entropy-scanner (thresholds and
suppression patterns), signature-scanner (sig.custom_rules_path and
enabled_families), trigger-scanner (phrase lists) and ast-taint-scanner
(enabled, python_path). A foreign/cloned target could raise its own
entropy thresholds, disable SIG families, supply its own SIG ruleset or
name the interpreter the AST scanner spawns — configuring the scan of
itself. Same defect class as S3b's .llm-security-ignore fix.
Chosen: move isOwnWorkingTree() to scanners/lib/own-working-tree.mjs (one
copy, reused by the orchestrator's ignore-file check) and make
loadPolicy() refuse an EXPLICIT root that is not the caller's own tree —
defaults plus one stderr line, same form as S3b — because one rule in one
function covers every scanner and a future call site cannot forget it.
The IMPLICIT root (CLAUDE_PROJECT_ROOT/cwd, what every hook uses) is the
caller's own project by construction and is read as before.
entropy-scanner's calibration.policy_source no longer reports an ignored
file as its source.
New tests/scanners/policy-scope.test.mjs was red on 0d37f5a (foreign
target: entropy finding silenced, custom SIG rule loaded, findings differ
from the same tree without policy.json, no stderr line) and is green now;
its own-tree scenario (known-positive) is green before and after. The 15
existing policy tests that placed own-tree fixtures under os.tmpdir() now
use tests/helpers/own-tree.mjs (fixture under $HOME, cwd set to it).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
30 lines
1.2 KiB
JavaScript
30 lines
1.2 KiB
JavaScript
// own-tree.mjs — Fixtures that ARE the process's own working tree (S3c).
|
|
//
|
|
// .llm-security/policy.json is honored for an explicit scan root only when
|
|
// that root is the caller's own working tree: under process.cwd(), never
|
|
// under os.tmpdir() (scanners/lib/own-working-tree.mjs). Tests of LOCAL
|
|
// policy behaviour therefore need a fixture that is the caller's own tree —
|
|
// a throwaway dir outside os.tmpdir() and outside this repo's git tree
|
|
// (under $HOME, same placement rule as ignore-file-scope.test.mjs), made the
|
|
// process cwd while the test runs. node --test runs each file in its own
|
|
// process, so the chdir never leaks into another test file.
|
|
|
|
import { mkdtempSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { homedir } from 'node:os';
|
|
|
|
/** Create a throwaway own-tree fixture dir (caller removes it). */
|
|
export function mkOwnTreeDir(prefix) {
|
|
return mkdtempSync(join(homedir(), `.${prefix}`));
|
|
}
|
|
|
|
/** Run fn with dir as the process cwd; the previous cwd is always restored. */
|
|
export async function inOwnTree(dir, fn) {
|
|
const prev = process.cwd();
|
|
process.chdir(dir);
|
|
try {
|
|
return await fn();
|
|
} finally {
|
|
process.chdir(prev);
|
|
}
|
|
}
|