Skip to content

fix: check records read back from the store value by value - #45

Open
rbartoli wants to merge 1 commit into
mainfrom
fix/validate-store-records
Open

rbartoli wants to merge 1 commit into
mainfrom
fix/validate-store-records

Conversation

@rbartoli

Copy link
Copy Markdown
Owner

This is L2 from the 2026-10-24 security review.

Peer records and journal rows read back from the mod store were only shape-checked. A corrupt or edited store file could:

  • switch off the machine-wide agent cap with running: -1000;
  • put any text into Claude's wind-down note and refusals through limit.kind, which windowName prints as it is;
  • put text into /agent-guard report, which Claude reads with its next request, through a row's tool, rule or kind;
  • make the agent gate throw with a non-string kind.

Writing to the store already needs the user's own file access, so this is defence in depth.

Changes

  • isPeerRecord: running must be a whole number, 0 or more; starts and dormantResumes must be finite numbers; agentTokens must be finite pairs with tokens 0 or more. A record that fails doesn't count.
  • isLimitReading (new): kind must match ^[a-z_]{1,32}$, percent must be from 0 to 1,000 (spend limits can pass 100), and the times must be finite. A peer whose reading fails keeps its counts and loses only the reading. The API declares kind as an open string, so a new window name can't make the guard drop a session's counts.
  • isJournalRow: ev and answer must come from the guard's own sets, ctx must be one of its buckets, rule, tool, kind and the session prefix must match plain patterns, and the numbers must be finite.

PR #42's fail-closed test made the gate throw with a peer record whose kind was a number, which this PR now filters out. It now throws through a plan reading from session.measure, so it still exercises the catch path.

Test plan

  • New core tests: five bad-count records are ignored, five bad readings are dropped while their counts are kept, and seven bad journal rows are rejected
  • claude plugin test . on 2.1.310: 105 pass. With core/state.ts and core/journal.ts stashed, both new tests fail.
  • tsc is clean
  • CI is green

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant