Harden KEXINIT parsing#1055
Open
ejohnstown wants to merge 2 commits into
Open
Conversation
ejohnstown
commented
Jun 24, 2026
Contributor
- Strip trailing comma from peer name lists (F-2478): GetNameListRaw folded a legal trailing comma (e.g. aes128-cbc,) into the final name, decoding it as ID_UNKNOWN and failing negotiation. Now trims it, mirroring AlgoListSz.
- Bound KEXINIT language name-list skips (F-5576): the two language lists were skipped via an unchecked GetUint32 + begin += skipSz, letting a forged length wrap the parse offset back into earlier payload bytes and still return success. Both now use GetSkip, which validates the length against the remaining payload.
- GetNameListRaw folded a trailing comma into the last name, so NameToId returned ID_UNKNOWN and negotiation failed. - Trim one trailing comma up front, matching AlgoListSz. - Add regression test for a KEX list with a trailing comma. Issue: F-2478
Contributor
There was a problem hiding this comment.
Pull request overview
Hardens SSH_MSG_KEXINIT parsing to be more robust against edge-case (but wire-valid) name-lists and against malformed packets that attempt to manipulate parser offsets via oversized language list lengths.
Changes:
- Trim a trailing comma from incoming (peer) name-lists before decoding IDs to avoid mis-parsing the final algorithm name.
- Replace unchecked
GetUint32+begin += skipSzskipping of KEXINIT language name-lists withGetSkip()to enforce bounds and prevent offset wrap. - Add regression tests covering trailing-comma negotiation and overlong language length rejection.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
tests/regress.c |
Adds targeted regression tests to lock in the KEXINIT parsing hardening behaviors. |
src/internal.c |
Adjusts name-list decoding to ignore a trailing comma and uses bounded skipping for KEXINIT language fields. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- DoKexInit skipped both language name-lists with an unchecked begin += skipSz; a forged length could wrap begin into earlier payload bytes and still return success. - Use bounds-checked GetSkip for both language fields. - Add regression test; checked skip now rejects with WS_BUFFER_E. Issue: F-5576
048dc7c to
e49154d
Compare
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.