diff --git a/STATE.md b/STATE.md index 28d569a..0aa4d26 100644 --- a/STATE.md +++ b/STATE.md @@ -1,37 +1,40 @@ # STATE — llm-security -**Active focus:** TRG/SIG/AST-gap scanners (TRG/SIG/AST) — DONE & pushed (Steps 1–7). -Release v7.8.0 (Step 8) DEFERRED by operator. **The next session is NOT TRG/SIG/AST** — it is -the security-fix brief (see PREREQUISITE) which must run before we resume/release this track. +**Active focus:** Security-fix track (from `docs/security-fix-brief-2026-06-20.md`). Critical review +is DONE — brief verified sound. Implement the must-fixes over MULTIPLE sessions (context-limited). +TRG/SIG/AST (TRG/SIG/AST) shipped Steps 1–7; v7.8.0 release (Step 8) stays DEFERRED behind these fixes. -## PREREQUISITE — do BEFORE continuing TRG/SIG/AST / releasing v7.8.0 -- Run the security-fix session: **`docs/security-fix-brief-2026-06-20.md`** - (F-1 RCE + F-2/F-3 shell/path injection sinks; from the marketplace-wide review - `docs/review-2026-06-20.md`). Operator instruction (2026-06-20): do NOT interleave it with - TRG/SIG/AST work; it gates the v7.8.0 release — don't ship a version with F-1/F-2/F-3 open. +## Critical-review verdict (DONE — do NOT re-derive) +- **F-1 / F-2 / F-3 = MUST FIX.** Verified real, correctly diagnosed, fixes are local + mechanical. +- **F-5 / F-6 = cheap cleanup.** `git rm -- ./--json .orphaned_at` — both confirmed present in repo root. +- **F-4 = optional** (LOW, by-design MCP spawn; a confirm-gate is a judgment call). +- No false positives / over-scoping in the must-layer. One gap to add: F-2's prefix containment does + not stop a symlink-escape — note it, but the prefix check is the must-do part. -## What landed this session (pushed to Forgejo, main @ d19abf0) -- **TRG** `scanners/trigger-scanner.mjs` — shadow/baiting/broad triggers; decode-pipeline on - descriptions. + wiring (orchestrator/policy/4 OWASP maps). Commits 54115a9, 75aeeee. Test 16/0. -- **SIG** `scanners/signature-scanner.mjs` + `knowledge/signatures.json` (webshell/reverse_shell/ - cryptominer/hacktool, matched over normalizeForScan/foldHomoglyphs/rot13 — catches obfuscated - malware). + wiring. Commits bac6f6f, 76e3543. Test 12/0. -- **AST** `scanners/ast-taint-scanner.mjs` + `scanners/lib/py-ast-taint.py` (PARSE-ONLY ast.parse, - scope-aware var taint, 5s timeout, graceful skip when python3 absent). + wiring. - Commits e497bb7, b50313e. Test 9/0. Parse-only proven (sentinel: no SENTINEL written). -- Docs/packaging `d19abf0` — scanner-reference rows + count bumps, output.mjs JSDoc prefixes, - orchestrator header (→14), `package.json` files[] += `knowledge/`. -- Full suite **1859/0**. Orchestrator runs **14** scanners (trg/sig/ast keys present). Zero-dep holds. +## Multi-session plan (TDD each: repro → red → green; full `node --test` green; gitleaks clean) +- **Session A — F-1 (CRITICAL) + cleanup.** Convert the `git()` helper in + `scanners/git-forensics.mjs` (`:59-66`, currently `execSync(\`git ${cmd}\`)`) to + `spawnSync('git', [...tokens], {cwd})` — one change fixes every call site (`:202/:211/:223/:231/ + :549/:564` already pass discrete tokens). Add a fixture repo with a hostile filename; assert the + scan completes and the injected side-effect never runs (write failing repro FIRST). Keep existing + git-forensics tests green (glob `commands/*.md` must still match via git, not shell). Fold in + F-5/F-6 `git rm`. Commit + push. +- **Session B — F-2 + F-3 (both HIGH).** + - F-2 `scanners/auto-cleaner.mjs` (sink ~`:776`, write ~`:878-881`): before write assert + `absPath === targetPath || absPath.startsWith(targetPath + sep)`; else skip + report. Test: a + finding `file: "../escape.txt"` is refused, not written. + - F-3 `scanners/lib/supply-chain-data.mjs:221-227` (`execSafe` = `execSync`) reached via + `hooks/scripts/pre-install-supply-chain.mjs:254`: switch to `spawnSync('npm',['view',spec,'--json'])` + OR validate spec `^[@/A-Za-z0-9._-]+$` first. Test: spec `foo;touch X` must not execute `touch`. +- **Session C — release.** Then Step 8 (v7.8.0) per + `docs/plans/trekplan-2026-06-20-TRG/SIG/AST-gap-analysis.md`. Optionally F-4 confirm-gate. -## Step 8 (deferred) — release v7.8.0 when ready, AFTER the security fix -- Bump 7.7.2 → 7.8.0 in `.claude-plugin/plugin.json`, `package.json`, README badge (`README.md:9`), - CHANGELOG `[7.8.0]`, `docs/version-history.md`, CLAUDE.md header. Verify w/ version-consistency grep. - Spec: Step 8 of `docs/plans/trekplan-2026-06-20-TRG/SIG/AST-gap-analysis.md`. +## COLD START (next session = Session A) +1. `pwd` + `git status` (expect clean). Read `docs/security-fix-brief-2026-06-20.md` + this STATE. +2. Start Session A (F-1) TDD — write the failing repro FIRST, then convert `git()`. -## Known pre-existing doc drift (out of this plan's scope — flagged, NOT fixed) -- `docs/scanner-reference.md` orchestrated count/list never counted `workflow` (true array = 14, docs - now say 13). Per the plan I bumped each count by +3; reconciling the workflow omission needs its own scope. - -## Continuity -- STATE.md canonical + committed (never gitignored). trekexecute progress scratch deleted (run done; - git history is the durable record). origin = Forgejo `open/llm-security` (never GitHub). +## Continuity notes +- Brief's "disclosure hold" gate is MOOT: review `738770e` + brief `fea943b` are already on + `origin/main`. Push the F-1 fix normally; no special bundling needed. +- origin = Forgejo `open/llm-security` (never GitHub). Push window: weekdays 20:00–23:00; weekends/ + holidays anytime. TRG/SIG/AST scanners (14 total, suite 1859/0) already shipped + pushed.