fix(cli): strip ASCII control chars from getpass output on Windows - #25133
Open
john7864 wants to merge 1 commit into
Open
fix(cli): strip ASCII control chars from getpass output on Windows#25133john7864 wants to merge 1 commit into
john7864 wants to merge 1 commit into
Conversation
On Windows, getpass.getpass() uses msvcrt.getwch() which emits a NUL
byte followed by a scan code when a special key is pressed (arrow keys,
function keys, etc.) instead of filtering them out. An inadvertent
arrow keypress before/during paste therefore injects e.g. "\x00K" (the
Left Arrow scan code) into the returned value.
When that value lands in an API-key prompt and is then written via
save_env_value(), reloading the .env crashes with:
ValueError: embedded null character
…inside python-dotenv's os.environ[k] = v call. The same value also
fails when sent as an HTTP header (httpx ASCII-encodes headers).
This patch adds a thin wrapper read_secret_line() in
hermes_cli.cli_output that strips \x00-\x1f from the getpass result,
and routes all 19 secret-input callsites across the CLI through it.
teknium1
reviewed
Jul 13, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for isolating a real Windows credential-input failure class. The current branch needs substantive salvage against current main.
Problems
hermes_cli/cli_output.py:62strips the\x00prefix but leaves its printable scan-code byte. For the reported\x00Ksequence, the result remainsK-prefixed;tests/hermes_cli/test_read_secret_line.py:19asserts that result despite its “both bytes” docstring.- The call-site sweep is stale: current main routes most secret prompts through
hermes_cli/secret_prompt.py:95-99, which consumes the complete Windows special-key pair, buthermes_cli/setup_whatsapp_cloud.py:181still callsgetpass.getpassdirectly. That value reachessave_env_value;hermes_cli/config.py:7538removes only CR/LF before theos.environassignment at line 7602.
Suggested changes
- Consume the scan-code byte after each
\x00/\xe0prefix and change the paired-input assertion to expectsk-test-abc. - Put the durable credential sanitation at
save_env_valueand test a NUL-containing input, covering direct readers such as the WhatsApp Cloud wizard. The timeline’s related #55336 targets that persistence choke point.
Automated hermes-sweeper review.
| feed the value through additional sanitization (e.g. paste cleanup) | ||
| may want the raw, control-char-free string. | ||
| """ | ||
| return getpass.getpass(prompt).translate({i: None for i in range(32)}) |
Contributor
There was a problem hiding this comment.
This removes the \x00 prefix but leaves the printable scan-code byte (K in the documented left-arrow sequence), so the corrupted secret is still modified. Consume the following character when the input contains a Windows \x00 or \xe0 special-key prefix; the paired-sequence test should then expect sk-test-abc.
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.
Summary
On Windows, getpass.getpass() uses msvcrt.getwch() which emits \x00 (or \xe0) followed by a scan code when a special key is pressed (arrow keys, function keys, etc.) instead of filtering them out. An inadvertent arrow keypress just before/during paste therefore injects e.g. \x00K (Left Arrow) into the returned value.
When that value lands in an API-key prompt and is then written via save_env_value(), reloading the .env crashes with:
ValueError: embedded null character
…from python-dotenv's os.environ[k] = v call. The same value also fails when sent as an HTTP header (httpx ASCII-encodes headers, so any non-ASCII byte raises).
Reproduction
Fix
Add read_secret_line() in hermes_cli.cli_output — a thin wrapper that strips \x00\x1f from the getpass.getpass() return value — and route all 19 secret-input call sites across the CLI through it.
Test plan
ValueError: embedded null character) and confirmed the fix resolves it.