Repository navigation
Reject control characters in the USER ident - #123
Merged
Merged
Conversation
The ident appears in every nick!ident@host prefix (JOIN, message sources, WHO, WHOIS, NAMES with userhost-in-names), but USER only rejected NUL, CR, LF, space and @. TAB, the CTCP delimiter \x01, formatting codes, DEL and C1 controls such as U+0085 (NEL) passed, so a client could forge line breaks, CTCP framing or colors inside other users' views of its hostmask. Any ISO control now falls back to the ident "user", like the other invalid content. Truncating the ident to its 9-char limit could also cut a surrogate pair in half, leaving a lone surrogate that goes out as '?'; the cut now steps back before a high surrogate. fixes #121 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reviewer's GuideThe PR hardens USER ident handling by rejecting all ISO control characters before they can appear in hostmasks, retains the existing Sequence diagram for safe USER ident handlingsequenceDiagram
participant Client
participant UserCommandHandler
participant Hostmask
participant ClientSession
participant IRCResponse
Client->>UserCommandHandler: handle(USER)
UserCommandHandler->>Hostmask: isValidUsernameContent(username)
alt invalid username content
UserCommandHandler->>ClientSession: setIdent(user)
else valid username content
UserCommandHandler->>ClientSession: setIdent(username)
end
UserCommandHandler->>ClientSession: setRealname(realname)
ClientSession->>IRCResponse: render hostmask ident
IRCResponse-->>Client: JOIN, WHOIS 311, or WHO 352
Flow diagram for surrogate-safe ident truncationflowchart LR
A[USER ident] --> B{Length exceeds IDENT_MAX_CHARS?}
B -- No --> C["setIdent(ident)"]
B -- Yes --> D{Character at truncation boundary is high surrogate?}
D -- Yes --> E[Remove boundary high surrogate]
D -- No --> F[Keep IDENT_MAX_CHARS boundary]
E --> C
F --> C
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="specs/001-ircv3-server/contracts/irc-protocol-commands.md" line_range="139" />
<code_context>
ever stating.
- **Username** (the `<user>` parameter of `USER`, RFC 2812 §2.3.1's
- `user` production): any octet except NUL, CR, LF, space, and `@` — no
+ `user` production): any character except space, `@`, and ISO control characters (C0 including NUL, CR, LF, TAB and \x01, DEL, and C1) — no
length limit specified by the RFC itself, but this server MUST apply
the same 9-character limit as `Hostmask`'s `ident` field for display
</code_context>
<issue_to_address>
**Research gives stale username rule**
When a reader relies on the research document for the USER username rule, `research.md` states the old octet rule while `Hostmask.isValidUsernameContent` rejects TAB, CTCP and C1 characters and `UserCommandHandler` substitutes `user`, so readers expect usernames the server rejects.
Update the registration grammar in `research.md` to match the username rule in the contract and validator.
</issue_to_address>Sourcery assessment
Approved.
Refs #121 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
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.



Fixes #121.
Why
The ident appears in every
nick!ident@hostprefix the server sends: JOIN, PRIVMSG and NOTICE sources, WHO, WHOIS, and NAMES withuserhost-in-names. USER only rejected NUL, CR, LF, space and@. Every other control character got through: TAB, the CTCP delimiter\x01, the formatting codes\x02,\x03and so on, DEL, and C1 controls such as U+0085 (NEL). A client could therefore plant line breaks, CTCP framing or colors inside its hostmask as other users see it. Sourcery found this while reviewing #120.What
Hostmask.isValidUsernameContentnow rejects any ISO control character (Character.isISOControl: C0, DEL and C1). Space and@are still rejected.UserCommandHandleralready falls back to the identuserfor invalid content, and that hasn't changed.IDENT_MAX_CHARS(9 chars) no longer splits a surrogate pair. Before,abcdefgh😀becameabcdefghplus a lone surrogate, which goes out as?. Now it becomesabcdefgh.specs/001-ircv3-server/contracts/irc-protocol-commands.mdnow matches.Formatting codes in message text, the realname, topics and reasons are untouched. #122 tracks a channel mode for those.
Validation
HostmaskUsernameContentTestchecks that TAB,\x01,\x1f, DEL, U+0080, U+0085, U+009F, NUL, CR, LF, space and@are rejected. It also checks thatalice,~ident,界界andcaféare accepted, and that null and empty input are handled.UserIdentControlCharacterTestis a socket test. It sends idents containing\x01, U+0085, TAB and DEL, and checks that JOIN, WHOIS 311 and WHO 352 showuser. A second case shows the surrogate-safe cut../gradlew cleanTest build sonarpasses, and the local SonarCloud branch scan passed the quality gate with 0 issues..github/REVIEW_CHECKLIST.mdand found nothing. It also confirmed thatUserCommandHandleris the only production caller ofsetIdent.🤖 Generated with Claude Code
Summary by Sourcery
Harden USER ident validation and display handling against control characters and malformed Unicode.
Bug Fixes:
Documentation:
Tests: