Conversation
The receiver printed the sender's filename verbatim in its "Receiving" line, before the receiver had agreed to anything. A name carrying an escape sequence could clear the line, move the cursor, retitle the window or plant a hyperlink, and a right-to-left override could make `exe.pdf` read as `fdp.exe`. Error messages from a peer, or from the relay, which is equally untrusted, reached the terminal the same way. `display.rs` replaces control characters and bidirectional and invisible formatting characters with U+FFFD rather than deleting them, so a doctored name looks doctored. It collapses whitespace padding and shortens long names in the middle, keeping the extension. Honest names in any script, emoji included, pass through unchanged. Applied to every place where someone else's text is printed. Pinned end to end through the real binary over a real relay. With the fix reverted, the test fails on the escape sequence reaching the receiver. Receiver consent plan, phase 1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7Fy45hUvna94cd79WKG8S
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This branch has not been deployed
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.
Receiver consent plan, phase 1. This fixes a bug in shipped releases and does not change the protocol. It is a behaviour change, so it waits for your review. Stacked on #67.
The bug
drop recvprinted the sender's filename verbatim (Receiving <name>), before the receiver had agreed to anything. A filename can carry:invoice_<U+202E>fdp.exereads asinvoice_exe.pdf.Error messages from the peer or the relay reached the terminal unfiltered in the same way. The relay is untrusted in Drop's threat model, so its messages count as peer text too.
The fix
New
cli/src/display.rs:for_terminalreplaces control characters (C0, DEL, C1) and bidi/invisible formatting characters withU+FFFD. It replaces rather than deletes, so a doctored name looks doctored. It also collapses whitespace padding.namedoes the same, then shortens anything over 80 columns in the middle so the extension survives. Wide characters count as two columns.peer_messagedoes the same, capped at 200 columns.It is applied to: the receiver's Receiving, collision, Saved and extraction lines; archive warnings; every
errorframe's message (recv, send, relay transport); the relay's HTTP error body; the sender's own summary and warnings; and the interface's file browser rows.Only what gets printed changes. The received file keeps the name its bytes arrived with.
Tests
Łódź 東京 🎉.txt, Arabic, an emoji ZWJ sequence,10:30 standup.md) left unchanged.ESC[2K ESC[1A U+202Ecrosses, and neither side's stderr contains ESC or U+202E.#[cfg(unix)]because Windows can't create that filename.cargo fmt --check,clippy -D warnings, andcargo test --workspace --all-targetsall pass: 193 tests, up from 180.check-secrets.shpasses.unicode-widthbecomes a direct dependency. It was already in the tree through ratatui, so no new crate is built.🤖 Generated with Claude Code
https://claude.ai/code/session_01G7Fy45hUvna94cd79WKG8S