Skip to content
shellhacks.dev
Security

Read a secret from stdin

Read a secret in Bash with IFS= read -rs so it is not echoed or put in a command line. The prompt shows only on a terminal, and the variable stays unexported.

1 min read
Summarize in AI

A script needs a password, and taking it as an argument leaves it in ps and the shell history.

Shell
printf 'hunter2\n' | {
  IFS= read -rs -p 'Password: ' pw
  echo "read ${#pw} characters"
  bash -c 'echo "child sees: ${pw-nothing}"'
}
Text
read 7 characters
child sees: nothing

read -s turns off terminal echo while the value is typed, -r keeps backslashes and an empty IFS keeps leading and trailing spaces. The value lives in a shell variable that is not exported, so the child process printed nothing and no other program can read it from its environment. The options are in the Bash manual. Since the text never appears in a command line, it stays out of ps and out of the history.

-s only works on a terminal and -p prints its prompt only when the input is a terminal, so the piped test above shows no prompt. Unset the variable as soon as it is used, and do not pass it to a command with -p on the command line. A secret in a variable can still appear in a core dump or in set -x output, so turn tracing off around it.

Share

More snippets

Security

Validate input with a whitelist

Validate input against a list of allowed values with a case statement. A grep check with ^ and $ can be fooled by a value that holds a newline.

1 min read
Security

Quote variables passed to commands

Quote variables you pass to commands. An unquoted expansion splits on spaces and expands globs, and a value that starts with a dash becomes an option.

1 min read
Security

Avoid eval on input

Never pass input to eval. Run a command held in an array as "${cmd[@]}", or escape a value with printf %q when eval cannot be avoided.

1 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.