Fix mnemonic input to not echo to screen
Changed mnemonic input to use secure non-echoing input like passphrases: - Use secret.ReadPassphrase() instead of readLineFromStdin() - Add newline after hidden input for better UX - Remove unused stdin reading functions from cli.go This prevents sensitive mnemonic phrases from being displayed on screen during input, matching the security behavior of passphrase input.
This commit is contained in:
parent
377b51f2db
commit
e5d7407c79
@ -2,21 +2,11 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"git.eeqj.de/sneak/secret/internal/secret"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// Global scanner for consistent stdin reading
|
||||
var stdinScanner *bufio.Scanner //nolint:gochecknoglobals // Needed for consistent stdin handling
|
||||
|
||||
// Instance encapsulates all CLI functionality and state
|
||||
type Instance struct {
|
||||
fs afero.Fs
|
||||
@ -67,33 +57,3 @@ func (cli *Instance) SetStateDir(stateDir string) {
|
||||
func (cli *Instance) GetStateDir() string {
|
||||
return cli.stateDir
|
||||
}
|
||||
|
||||
// getStdinScanner returns a shared scanner for stdin to avoid buffering issues
|
||||
func getStdinScanner() *bufio.Scanner {
|
||||
if stdinScanner == nil {
|
||||
stdinScanner = bufio.NewScanner(os.Stdin)
|
||||
}
|
||||
|
||||
return stdinScanner
|
||||
}
|
||||
|
||||
// readLineFromStdin reads a single line from stdin with a prompt
|
||||
// Uses a shared scanner to avoid buffering issues between multiple calls
|
||||
func readLineFromStdin(prompt string) (string, error) {
|
||||
// Check if stderr is a terminal - if not, we can't prompt interactively
|
||||
if !term.IsTerminal(syscall.Stderr) {
|
||||
return "", fmt.Errorf("cannot prompt for input: stderr is not a terminal (running in non-interactive mode)")
|
||||
}
|
||||
|
||||
fmt.Fprint(os.Stderr, prompt) // Write prompt to stderr, not stdout
|
||||
scanner := getStdinScanner()
|
||||
if !scanner.Scan() {
|
||||
if err := scanner.Err(); err != nil {
|
||||
return "", fmt.Errorf("failed to read from stdin: %w", err)
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("failed to read from stdin: EOF")
|
||||
}
|
||||
|
||||
return strings.TrimSpace(scanner.Text()), nil
|
||||
}
|
||||
|
@ -60,14 +60,17 @@ func (cli *Instance) Init(cmd *cobra.Command) error {
|
||||
mnemonicStr = envMnemonic
|
||||
} else {
|
||||
secret.Debug("Prompting user for mnemonic phrase")
|
||||
// Read mnemonic from stdin using shared line reader
|
||||
var err error
|
||||
mnemonicStr, err = readLineFromStdin("Enter your BIP39 mnemonic phrase: ")
|
||||
// Read mnemonic securely without echo
|
||||
mnemonicBuffer, err := secret.ReadPassphrase("Enter your BIP39 mnemonic phrase: ")
|
||||
if err != nil {
|
||||
secret.Debug("Failed to read mnemonic from stdin", "error", err)
|
||||
|
||||
return fmt.Errorf("failed to read mnemonic: %w", err)
|
||||
}
|
||||
defer mnemonicBuffer.Destroy()
|
||||
|
||||
mnemonicStr = mnemonicBuffer.String()
|
||||
fmt.Fprintln(os.Stderr) // Add newline after hidden input
|
||||
}
|
||||
|
||||
if mnemonicStr == "" {
|
||||
|
Loading…
Reference in New Issue
Block a user