fix: validate session ID centrally in DispatchLifecycleEvent

main

Commit

Soph3mo ago

handleLifecycleTurnEnd builds .entire/metadata/<session_id>/ via os.MkdirAll + os.WriteFile directly from the hook-supplied event.SessionID with no validation — unlike its siblings (SessionStart/TurnStart/ToolUse), which each validate. A "../"-laden ID could write the transcript outside the metadata directory. The ModelUpdate/Compaction/SubagentEnd handlers were also unguarded, surviving only because the strategy layer (MutateSessionState/StoreModelHint) validates internally.

Per-handler validation is the wrong altitude: it is exactly the kind of check a new (or existing) handler forgets, which is what happened here. Validate non-empty event.SessionID once in DispatchLifecycleEvent, before routing, so every handler — current and future — is covered uniformly. Empty IDs still pass through to each handler's own empty-handling (e.g. TurnEnd's fallback to the "unknown" constant).

The existing per-handler validations are now redundant but left in place as harmless defense-in-depth; they could be consolidated separately.

Taint is local hook input (same-privilege), so severity is low; this completes the hook-path hardening theme on this branch.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com Entire-Checkpoint: 0a614e131bab

Checkpoints

Review Security Vulnerability Report

Claude CodeOpus 4.8[1m]
View session
Checkpoint 1