fix(session-codec): validate session ID format in serialize/deserialize#116
Open
LucidPaths wants to merge 1 commit into
Open
fix(session-codec): validate session ID format in serialize/deserialize#116LucidPaths wants to merge 1 commit into
LucidPaths wants to merge 1 commit into
Conversation
The sessionCodec accepts any non-empty string as a session ID. When
parseHermesOutput false-captures the word "from" from the error message
"Use a session ID from a previous CLI run", the codec stores it without
question. The corrupted value then poisons --resume on every subsequent
run, creating an unrecoverable stall.
Add HERMES_SESSION_ID_RE (/^\d{8}_\d{6}_[a-f0-9]+$/) validation to
readValidSessionId() — used by both serialize() and deserialize(). Any
value that does not match the Hermes YYYYMMDD_HHMMSS_hex format is
rejected at the storage boundary, regardless of how it was parsed.
Complements NousResearch#112 (regex anchoring in parseHermesOutput) as a
defense-in-depth layer: even if a future output format fools the regex,
the codec rejects it before it reaches the database.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
This is a good defense-in-depth layer and should land with the parser fix, not instead of it. I reproduced the current failure class locally from Paperclip
This PR blocks invalid values at the codec boundary, which is exactly the right invariant for adapter runtime state. I would recommend adding/confirming tests for both invalid examples:
Then merge alongside #83 or after #112; otherwise one future parser regression can re-poison durable runtime state. |
This was referenced May 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds format validation to the
sessionCodecinsrc/server/index.ts. The codec currently accepts any non-empty string as a session ID — including the word"from", which is false-captured from Hermes error output bySESSION_ID_REGEX_LEGACY. Once stored, the corrupted value poisons--resumeon every subsequent run, creating an unrecoverable agent stall.This is a defense-in-depth complement to #112 (regex anchoring). Even if a future output format fools the regex, the codec rejects invalid values at the storage boundary before they reach the database.
Related Issue
Complements #112 — that PR anchors the regex to prevent the false capture; this PR validates at the codec layer so no garbage can be persisted regardless of how it was parsed.
Type of Change
Changes Made
src/server/index.ts— AddedHERMES_SESSION_ID_RE(/^\d{8}_\d{6}_[a-f0-9]+$/) andreadValidSessionId()helper. Bothserialize()anddeserialize()now validate session IDs match the HermesYYYYMMDD_HHMMSS_hexformat before accepting them. Non-matching values (e.g."from", truncated IDs like"20260513_091310_", empty strings) returnnull.src/server/session-codec.test.mjs— 10 regression tests covering both serialize and deserialize: valid IDs accepted,"from"rejected, truncated IDs rejected, empty/null handling, snake_case key fallback.How to Test
All 10 tests pass. To reproduce the original bug without this fix:
Checklist
Code
fix(session-codec):)session-codec.test.mjs)tsc --noEmitpasses with zero errorsDocumentation & Housekeeping
Context
Discovered in production on a Paperclip instance running 7 Hermes agents (4
claude_local+ 3hermes_local). When any Hermes run failed, the legacy regex captured"from"from the error help text"Use a session ID from a previous CLI run". The codec stored it without validation. Every subsequent run tried--resume from, failed instantly with"Session not found: from", re-captured"from"from the new error output, and the loop never broke. Two of three Hermes agents were stuck in this state. Claude agents on the same instance were unaffected (different adapter, different codec).The regex anchoring in #112 prevents the specific false capture. This codec validation prevents the class of corruption — any non-Hermes-format string is rejected before it can poison stored state.