Files
gstack/lib
Garry Tan 7fdd5a377d fix(security): close adversarial-review findings in decision memory
Adversarial review (Claude subagent) found a CRITICAL the specialist pass missed:
- F1 (CRITICAL): 'Human:'/'Assistant:' turn-prefixes bypassed BOTH the write-time
  denylist AND datamark(), landing verbatim in agent context inside the trusted
  ACTIVE DECISIONS fence. Add 'human:' (+ 'disregard previous', 'from now on') to
  the shared denylist, and have datamark() neutralize Human:/Assistant:/System:/User:
  turn-prefixes (ZWSP) at the render boundary.
- F2: datamark() only stripped ASCII C0; extend to Unicode line terminators
  (U+0085/2028/2029) and U+007F so 'strip newlines' actually holds.
- F3: validateDecide blocked only HIGH secrets; MEDIUM-tier PII (e.g. SSN) persisted
  silently and synced cross-machine. The store is non-interactive (no confirm path),
  so fail closed on MEDIUM too.
- F4: compact() was a lock-free read-modify-rewrite that could clobber a concurrent
  append (lost decision). Add an O_EXCL compact lock + a pre-rename size recheck that
  aborts untouched (skipped=true) if an append landed; caller re-runs.
- F7: filterByScope unknown/garbage scope fell through to 'return true' (leaked into
  every context); fail conservative (false).

F5 (pid reuse) and F6 (pgrep over-match) are intentionally left as-is: both fail SAFE
(over-refuse sync); making them precise would introduce a fail-DANGEROUS path
(allowing sync during a real autopilot). True disambiguation needs gbrain to stamp the
lock with a start-time, which gstack doesn't own. F8 (compact moves history to archive)
is by design.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 19:29:16 -07:00
..