chore(llm-security): STATE — Session A (F-1 + F-5/F-6) done; next = Session B
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3s6WnubSSrFjAQTLQdVbG
This commit is contained in:
parent
e46b5a3256
commit
f5988f9500
1 changed files with 24 additions and 23 deletions
47
STATE.md
47
STATE.md
|
|
@ -1,40 +1,41 @@
|
|||
# STATE — llm-security
|
||||
|
||||
**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).
|
||||
DONE — brief verified sound. Implementing must-fixes over MULTIPLE sessions (context-limited).
|
||||
**Session A (F-1 + F-5/F-6) DONE + pushed.** Next = Session B (F-2 + F-3).
|
||||
TRG/SIG/AST (TRG/SIG/AST) shipped Steps 1–7; v7.8.0 release (Step 8) stays DEFERRED behind these fixes.
|
||||
|
||||
## 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-5 / F-6 = cheap cleanup.** DONE — `--json` + `.orphaned_at` removed in Session A.
|
||||
- **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.
|
||||
- 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.
|
||||
|
||||
## 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.
|
||||
- **Session A — F-1 (CRITICAL) + cleanup. DONE (commit 5f50899, pushed).** `git()` in
|
||||
`scanners/git-forensics.mjs` now `spawnSync('git', [...tokens], {cwd})` (no shell); ALL ~25 call
|
||||
sites pass discrete arrays. Repro `tests/scanners/git-injection.test.mjs` (hostile `$(...)`
|
||||
filename) RED→GREEN. F-5/F-6 `git rm` folded in. Suite 1860/0.
|
||||
- **Session B — F-2 + F-3 (both HIGH). ← NEXT**
|
||||
- F-2 `scanners/auto-cleaner.mjs` (sink ~`:776` `resolve(targetPath, f.file)`, 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`.
|
||||
`hooks/scripts/pre-install-supply-chain.mjs:254` → `inspectNpmPackage`: 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.
|
||||
|
||||
## 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()`.
|
||||
## COLD START (next session = Session B)
|
||||
1. `pwd` + `git status` (expect clean). Read `docs/security-fix-brief-2026-06-20.md` (F-2/F-3) + this STATE.
|
||||
2. Start Session B TDD — F-2 first (failing repro: a `../escape.txt` finding must be refused), then F-3.
|
||||
3. Mirror the Session-A pattern: array-arg `spawnSync` (style ref `scanners/lib/git-clone.mjs`),
|
||||
repro-first, keep suite green, gitleaks clean, commit + push.
|
||||
|
||||
## 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.
|
||||
- Disclosure hold MOOT: review `738770e` + brief `fea943b` already on `origin/main` (verified). No
|
||||
special bundling — push fixes normally.
|
||||
- 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.
|
||||
holidays anytime. Suite now 1860/0 (was 1859; +1 F-1 regression test).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue