Repository navigation
Conversation
joe0BAB
force-pushed
the
feat/ls
branch
6 times, most recently
from
October 8, 2026 13:12
5dca2ea to
ac50fca
Compare
`docker pass set <id>` used to block on STDIN whenever no value was given, echoing whatever the user typed. It now detects an interactive terminal and shows a masked prompt instead, so the value neither lands in shell history nor on screen, and nobody has to pipe it from a file. Pipes and redirects still read STDIN to the end as before. The prompt is a small raw-mode line reader on top of x/term. Raw mode is entered with tcsetattr(TCSAFLUSH), as getpass(3), sudo and readpassphrase do, so input typed before the prompt appeared, which the still-cooked tty echoed in plaintext, is discarded rather than taken as the secret. Printable runes and tab are appended and echoed as '*', Backspace removes the last rune, ctrl+u clears the line, and Enter or a bare LF (ctrl+j) ends it, as with getpass(3). An empty Enter is an error, and so is input ending before Enter: Ctrl-D, or Ctrl-Z on a Windows console, which the console reader in os reports as EOF. Unlike getpass(3), a line that was not entered is never stored. Ctrl-C, which raw mode delivers as a key press rather than a signal, is reported as context.Canceled so the root exits 130 silently. Cancelling the context, as the root does on a signal, ends the read loop so its buffers are zeroed, restores the terminal and returns; the root ends the prompt line when it reports the signal. The tty is read only once poll(2) reports input, so no read is left in flight when the prompt returns: a blocking tty read cannot be cancelled, and one left behind would take the line typed next, meant for the shell, while the store is still busy. A pipe written on cancel is polled alongside. On Windows the console handle is waited on with WaitForMultipleObjects and its records taken with ReadConsoleInput, since any unread record, a key release among them, signals the handle while ReadConsole would swallow it and block again. Escape sequences are skipped whole, cursor keys, mouse reports and stray terminal replies among them, so they never leak into the value; a control byte inside one ends it, so Enter and Ctrl-C get through regardless. Each byte of a sequence gets 50 ms to arrive, as with vim's ttimeout, and a longer gap ends the burst ESC began. ESC alone is the Escape key and ignored, though a '[' or 'O' within 500 ms of it is still taken for the tail of its sequence, split by a slow link. Printable bytes that complete no sequence or trail one within the burst are an error rather than dropped: Alt+h, Escape coalesced with typing by ssh latency, or a chord like Alt+[ that would otherwise park the reader inside the sequence parser eating the keys typed next all look alike, and a masked prompt cannot show which character went missing. A paste has no such timeout, since it streams at the pace of the link. The read buffer and the collected runes are zeroed when the prompt returns. Pastes are taken through bracketed paste mode only; the prompt never reads the clipboard. A pasted trailing newline is trimmed, and a value spanning several lines, or holding control characters other than tab, is rejected with a pointer to STDIN rather than stored mangled. So is a byte that is not UTF-8, typed or pasted, rather than left out of the value with nothing but a missing '*' to show for it. Ctrl-C cancels inside a paste too, the way out should its end marker never arrive. When the terminal does not bracket pastes, a multi-line paste arrives as keystrokes; input trailing the line end within 50 ms, faster than anyone types, gives it away whether or not a read ended at the line end, and it is rejected rather than stored as its first line. Type-ahead that a busy host or ssh coalesced with Enter looks the same, so that error names what was seen, input past the line end, not a paste. The terminal is restored and the input still queued in it discarded in one tcsetattr(TCSAFLUSH) ioctl (TIOCSETAF on Darwin, TCSETSF on Linux; SetConsoleMode then FlushConsoleInputBuffer on Windows), as getpass(3) does, deferred so that a panic restores too; a restore that fails is an error even after a value was read, as a terminal left raw must not pass for success. Restoring first and flushing second would leave a window on BSD-derived ttys: turning ICANON back on sets PENDIN, and the next byte to arrive has the queued remainder retyped with ECHO on, printing the rest of the paste in plaintext. Pastes larger than the pty input queue can still reach the shell, as they do with sudo and ssh prompts. Cobra hands the subcommands docker's stream wrappers, which hide the terminal file behind File(); unwrapFile reaches it to switch the terminal to raw mode. Signed-off-by: Johannes Großmann <grossmann.johannes@t-online.de>
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.
docker pass set <id>used to block on STDIN whenever no value was given, echoing whatever the user typed. It now detects an interactive terminal and shows a masked prompt instead, so the value neither lands in shell history nor on screen, and nobody has to pipe it from a file. Pipes and redirects still read STDIN to the end as before.The prompt is a small raw-mode line reader on top of x/term. Printable runes are appended and echoed as '*', Backspace removes the last rune, ctrl+u clears the line, and Enter or a bare LF (ctrl+j) ends it, as with getpass(3). An empty Enter is an error, and so is input ending before Enter: Ctrl-D, or Ctrl-Z on a Windows console, which the console reader in os reports as EOF. Unlike getpass(3), a line that was not entered is never stored. Ctrl-C, which raw mode
delivers as a key press rather than a signal, is reported as context.Canceled so the root exits 130 silently. Cancelling the context, as the root does on a signal, ends the read loop so its buffers are zeroed, restores the terminal and returns; the root ends the prompt line when it reports the signal. The blocked read of the tty itself cannot be interrupted and is left to end with the process. Escape sequences are skipped whole, cursor keys, mouse reports and stray terminal replies among them, so they never leak into the value; a control byte inside one ends it, so Enter and Ctrl-C get through regardless. A sequence split after its ESC gets 50 ms to arrive before ESC counts as the Escape key, as in vim and bubbletea.
The read buffer and the collected runes are zeroed when the prompt returns.
Pastes are taken through bracketed paste mode only; the prompt never reads the clipboard. A pasted trailing newline is trimmed, and a value spanning several lines, or holding control characters other than tab, is rejected with a pointer to STDIN rather than stored mangled. Ctrl-C cancels inside a paste too, the way out should its end marker never arrive. When the terminal does not bracket pastes, a multi-line paste arrives as keystrokes: the value is exactly the first line, and the terminal is restored and the input still queued in it discarded in one tcsetattr(TCSAFLUSH) ioctl (TIOCSETAF on Darwin, TCSETSF on Linux; SetConsoleMode then FlushConsoleInputBuffer on Windows), as getpass(3) does. Restoring first and flushing second would leave a window on BSD-derived ttys: turning ICANON back on sets PENDIN, and the next byte to arrive has the queued remainder retyped with ECHO on, printing the rest of the paste in plaintext. Pastes larger than the pty input queue can still reach the shell, as they do with sudo and ssh prompts.
Cobra hands the subcommands docker's stream wrappers, which hide the terminal file behind File(); unwrapFile reaches it to switch the terminal to raw mode.