Skip to content

prune: malformed legacy state can escape fail-open handling #361

Description

@SUaDtL

Problem

The prune hook's nudge path is guarded, but the later growth short-circuit trusts the loaded session record:

if rec and (st.st_size - rec.get(last_pruned_size, 0)) < cfg.min_growth:
    return 0

A truthy non-dict record raises on .get(). A dict with a nonnumeric last_pruned_size raises during subtraction. The security review for #360 reproduced this with string, boolean, and list-shaped records and confirmed by blame that the gap predates that PR.

Impact

A malformed ~/.codearbiter/prune-state.json session entry can escape the hook's fail-open contract and disrupt a submit instead of being ignored safely. The new context_bytes_freed parsing in #360 is already strict and fail-soft; this issue concerns the inherited record and growth-short-circuit handling only.

Done when

  • Truthy non-dict session records fail open.
  • Missing, boolean, string, nonfinite, negative, and container-shaped last_pruned_size values fail open.
  • Valid numeric records preserve the existing minimum-growth short-circuit.
  • Regression coverage exercises hook_run at the malformed-state boundary across the shared core copies.

Scope

Reliability hardening only. Do not change prune transformations, metric classification, defaults, or nudge thresholds.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions