feat(shell): opt-in sudo askpass flow (#1551)#3163
Merged
Conversation
Shell commands that run `sudo` had no controlling terminal, so an interactive sudo would hang until the command timed out and the agent fell back to printing manual instructions. This adds an opt-in `sudo_askpass: true` option on the shell toolset that bridges sudo's standard SUDO_ASKPASS mechanism to the agent's elicitation prompt. When enabled and a command runs `sudo`, the toolset starts a private unix-socket server (0700 dir) plus a SUDO_ASKPASS wrapper script, injects the bridge env, and forces `sudo -A` via a shell function. The hidden `__askpass` subcommand dials the socket and returns the password to sudo on stdout. The password is requested through a masked elicitation prompt; it only transits the local socket (0700 dir, crypto/rand token compared in constant time) and the helper's stdout, and is never logged, stored, or placed on the command line. The flow is Unix-only, opt-in, and declines automatically in non-interactive runs (sudo then fails as before). The `__askpass` helper is forced onto the standalone command path even under the docker CLI plugin reexec env, so its stdout carries only the password and is never corrupted by plugin usage output.
- Detect sudo with a word boundary (\bsudo\b) instead of a substring, so the bridge env is no longer injected for commands that merely mention "pseudo", "sudoers", etc. - Serialize password prompts (one at a time) so two parallel sudo calls in one command do not open two dialogs at once. - Document that the bridge env vars are visible to all child processes of a sudo command, and the concurrent-prompt serialization. - Clarify the watchConn no-leak invariant and the gosec suppression comment.
|
❌ PR Review Failed — The review agent encountered an error and could not complete the review. View logs. |
dgageot
approved these changes
Jun 19, 2026
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.
Closes #1551.
Problem
Shell commands that run
sudoget no controlling terminal, so an interactivesudohangs until the command times out and the agent falls back to printing manual instructions.Approach
Opt-in
sudo_askpass: trueon theshelltoolset, bridging sudo's standardSUDO_ASKPASSmechanism to the existing elicitation prompt. Nothing changes unless the flag is set and a command actually runssudo.Flow when a
sudocommand runs:0700temp dir, writes aSUDO_ASKPASSwrapper script, and injects the bridge env (SUDO_ASKPASS,CAGENT_ASKPASS_SOCKET,CAGENT_ASKPASS_TOKEN) only into that command.sudo() { command sudo -A "$@"; }function is prepended (POSIX shells) so sudo uses askpass instead of a TTY.__askpasssubcommand dials the socket; the server asks the user via a masked elicitation prompt and returns the password to sudo on stdout.Security
0700dir, single-user; request carries acrypto/randtoken compared withsubtle.ConstantTimeCompare.__askpassstdoutLimitations (documented)
sudo ...in a POSIX shell is intercepted (/usr/bin/sudo,env sudo, nested scripts, and non-POSIX shells likefishare not).Tests
pkg/tools/builtin/shell: socket round-trip, decline, bad token, missing env, helper-death cancellation,shQuote, sudo wrapping, Elicitable discovery through the toolset wrappers.pkg/config:sudo_askpassvalidation (shell only) plus schema parity.pkg/tui/dialog: password field masked and not trimmed.cmd/root:__askpassrouting and management-invocation gating.Verified end to end with the built binary in both standalone and docker-plugin invocation, plus cross-compile for windows and js/wasm.