fix(fleet): the sudo password was being executed as a command - #19
Merged
Conversation
Reported from the desktop, and reproducible in one line:
/bin/sh: 1: <the password>: not found
`sudo -S` reads the password from stdin **only when it actually needs one**.
Under NOPASSWD, a still-valid sudo timestamp, or a login that is already
root, it reads nothing at all — and the password, which was prepended to the
script on the same stream, falls through to `sh -es` and runs as command
number one. Which also puts it in an error message.
That is not a corner case. It is what happens on every deploy account
configured the way deploy accounts are configured, and it is why the feature
looked fine in review: the mechanism is correct exactly when sudo challenges
you, and silently wrong when it does not.
The fix is to stop sharing the stream. With a sudo password the script now
travels as a quoted argument (`sh -ec '<script>'`) and stdin carries the
password alone, so there is no ordering to get right. `withSudoPassword`
throws rather than proceeding if it is ever handed a command whose stdin is
already occupied, and rejects a password containing a newline — which cannot
be escaped, only refused, since the newline would end the line sudo reads and
hand the remainder to the command.
Everywhere else is untouched: with no sudo, or `sudo -n`, the script still
goes on stdin, where nothing is quoted so nothing can be misquoted and a
script is not bounded by the command-line length limit.
Also: a refused password now says so. sudo emits both "Authentication failed,
try again" and "authentication required but not attempted" on a failed
attempt, and matching the second told someone who *had* supplied a password
to supply one.
Verified against real hosts rather than by reading, using root@localhost
(passwordless sudo, the broken case) and anthony@localhost (sudo does
challenge):
- password mode where sudo wants nothing: script runs, password is not
executed, nothing leaks to stderr
- password mode with a WRONG password where sudo does challenge: refused, the
script does not run, the password is not echoed back
- a script of quotes, backticks, `$VAR`, pipes and redirects survives the
quoted argument byte for byte
- `sudo off` and `sudo -n` unchanged
Two tests asserted the old behaviour and were codifying the bug; they now
assert the invariant instead — in password mode `stdin` is the password and
only the password.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UeSWg1Czsb2Lwxj8vHUnA4
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.
Reported from the desktop, and reproducible in one line:
Cause
sudo -Sreads the password from stdin only when it actually needs one. UnderNOPASSWD, a still-valid sudo timestamp, or a login that is already root, it reads nothing at all — and the password, which was prepended to the script on the same stream, falls through tosh -esand runs as command number one. Which also puts it in an error message.That is not a corner case. It is what happens on every deploy account configured the way deploy accounts are configured, and it is why this looked fine in review: the mechanism is correct exactly when sudo challenges you, and silently wrong when it does not.
Fix
Stop sharing the stream. With a sudo password the script now travels as a quoted argument (
sh -ec '<script>') and stdin carries the password alone, so there is no ordering to get right.withSudoPasswordthrows rather than proceeding if handed a command whose stdin is already occupied.sudo -n, the script still goes on stdin, where nothing is quoted so nothing can be misquoted and a script is not bounded by the command-line length limit.Also: a refused password now says so. sudo emits both
Authentication failed, try againandauthentication required but not attemptedon a failed attempt, and matching the second told someone who had supplied a password to supply one.Verified against real hosts
Not by reading.
root@localhosthas passwordless sudo — the broken case — andanthony@localhostdoes challenge:$VAR, pipes, redirectssudo offandsudo -nReproduced the original failure first, confirmed the fix clears it, then checked the reverse case so the fix cannot have simply disabled authentication.
Two existing tests asserted the old behaviour and were codifying the bug. They now assert the invariant instead: in password mode
stdinis the password and only the password.491 tests across 40 files, full typecheck, green.
🤖 Generated with Claude Code
https://claude.ai/code/session_01UeSWg1Czsb2Lwxj8vHUnA4