Skip to content

Terminate on any unsupported version instead of sending code 2 - #40

Merged
markmnl merged 3 commits into
mainfrom
fix/terminate-unsupported-challenge
Aug 25, 2026
Merged

Terminate on any unsupported version instead of sending code 2#40
markmnl merged 3 commits into
mainfrom
fix/terminate-unsupported-challenge

Conversation

@markmnl

@markmnl markmnl commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Design correction from spec review (markmnl/fmsg#29): an unsupported version is one we don't know how to respond in, so the listener MUST TERMINATE without writing anything — on both first-byte branches.

  • First byte ≤ 128 (unsupported message version): previously REJECT 2. Now terminates.
  • First byte > 128 (unsupported challenge version): previously REJECT 2. Now terminates. A 1-byte code written here is especially bad — the challenger's next read is exactly the 32-byte CHALLENGE-RESPONSE hash and 0x02 is a valid hash prefix, so the code is indistinguishable from hash bytes and the challenger only discovers the truth via a short read at EOF.

Changes

  • readVersionOrChallenge closes without writing on both unsupported branches.
  • Code 2 is consequently never sent on the wire. RejectCodeUnsupportedVersion and its responseCodeName case are removed; 2 is left unassigned so existing numbering is unchanged, matching the spec's code table (which already has an unassigned 104). responseCodeName falls through to unknown(2) should one ever be read from a peer.
  • The corresponding host_test.go table row is dropped. go build, go vet, go test ./... all pass.

History

An earlier v0.5.0 spec draft split the two branches — REJECT 2 for the message-version branch, TERMINATE for the challenge branch — and an earlier revision of this PR implemented that split. Review settled on the simpler rule: terminate in both cases. This PR now implements that, and depends on markmnl/fmsg#29 landing with it.

🤖 Generated with Claude Code

A challenger's next read after sending CHALLENGE is exactly the
32-byte CHALLENGE-RESPONSE hash, so a response code written into that
stream is indistinguishable from the start of a hash. Close without
responding (SPEC SS10.5); code 2 remains for unsupported MESSAGE
versions, where the peer's first read is always a response code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Follows the revised ruling in markmnl/fmsg#29: an unsupported version is
one we do not know how to respond in, so both branches of
readVersionOrChallenge now TERMINATE without writing anything — the
message-version branch (first byte <= 128) as well as the challenge
branch.

Code 2 is therefore never sent on the wire. RejectCodeUnsupportedVersion
and its responseCodeName case are removed, with 2 left unassigned so the
numbering is unchanged; responseCodeName falls through to unknown(2) if
one is ever read from a peer. Its host_test row goes with it.
@markmnl markmnl changed the title Terminate on unsupported challenge version instead of sending code 2 Terminate on any unsupported version instead of sending code 2 Aug 25, 2026
@markmnl
markmnl merged commit 4078565 into main Aug 25, 2026
1 of 2 checks passed
@markmnl
markmnl deleted the fix/terminate-unsupported-challenge branch August 25, 2026 10:07
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