diff --git a/pkg/action/package.go b/pkg/action/package.go index 1b7901f17..58d0250cb 100644 --- a/pkg/action/package.go +++ b/pkg/action/package.go @@ -206,11 +206,12 @@ func (p *Package) Clearsign(filename string) error { // promptUser implements provenance.PassphraseFetcher func promptUser(name string) ([]byte, error) { - fmt.Printf("Password for key %q > ", name) + // Prompts go to stderr so stdout stays clean for scripting. + fmt.Fprintf(os.Stderr, "Password for key %q > ", name) // syscall.Stdin is not an int in all environments and needs to be coerced // into one there (e.g., Windows) pw, err := term.ReadPassword(int(syscall.Stdin)) - fmt.Println() + fmt.Fprintln(os.Stderr) return pw, err } diff --git a/pkg/cmd/plugin_package.go b/pkg/cmd/plugin_package.go index 019ae6d4a..452695e06 100644 --- a/pkg/cmd/plugin_package.go +++ b/pkg/cmd/plugin_package.go @@ -172,9 +172,10 @@ func (o *pluginPackageOptions) run(out io.Writer) error { } func (o *pluginPackageOptions) promptUser(name string) ([]byte, error) { - fmt.Printf("Password for key %q > ", name) + // Prompts go to stderr so stdout stays clean for scripting. + fmt.Fprintf(os.Stderr, "Password for key %q > ", name) pw, err := term.ReadPassword(int(syscall.Stdin)) - fmt.Println() + fmt.Fprintln(os.Stderr) return pw, err } diff --git a/pkg/cmd/registry_login.go b/pkg/cmd/registry_login.go index bffc56445..325469f35 100644 --- a/pkg/cmd/registry_login.go +++ b/pkg/cmd/registry_login.go @@ -136,14 +136,17 @@ func getUsernamePassword(usernameOpt string, passwordOpt string, passwordFromStd // Copied/adapted from https://github.com/oras-project/oras func readLine(prompt string, silent bool) (string, error) { - fmt.Print(prompt) - if silent { + // Prompts go to stderr so stdout stays clean for scripting. + fmt.Fprint(os.Stderr, prompt) + if silent && term.IsTerminal(os.Stdin.Fd()) { fd := os.Stdin.Fd() state, err := term.SaveState(fd) if err != nil { return "", err } - term.DisableEcho(fd, state) + if err := term.DisableEcho(fd, state); err != nil { + return "", fmt.Errorf("failed to disable terminal echo for password input: %w", err) + } defer term.RestoreTerminal(fd, state) } @@ -153,7 +156,7 @@ func readLine(prompt string, silent bool) (string, error) { return "", err } if silent { - fmt.Println() + fmt.Fprintln(os.Stderr) } return string(line), nil