Is there a way to pass sensitive data in bash using a prompt, for any command?

Ideally, you never type a clear-text password on the command line as an argument to a command. Doing so makes the password an argument to the command, and command line arguments may be seen in the process table by using simple tools like ps or logged into some audit logs.

Having said that, there are certainly ways of hiding the actual password from the shell's command history.

sha1pass "$( head -n 1 )"

Then type in the password and press Enter. The head command used here accept exactly one line of input and the last newline that you type will not be part of the data that is passed to sha1pass.

To prevent the characters from echoing:

sha1pass "$( stty -echo; head -n 1; stty echo )"

The stty -echo command turns off echoing of the typed characters on the terminal. The echoing is then restored with stty echo.

To pass on standard input, that last command could be altered (you would have done this if sha1pass accepted data on standard input, but appears as if this particular utility is ignoring its standard input):

{ stty -echo; head -n 1; stty echo; } | somecommand

If you need multi-line input (the above assumes a single line should be passed, with no newline character at the end), then replace the whole head command with cat and terminate the input (assuming somecommand itself reads until end-of-file) with Ctrl+D (following Return if you want to include a newline character in the input, or twice if not).

This would work regardless of what shell you were using (as long as it was a Bourne-like or rc-like shell).

Some shells may be made to not save the typed-in commands in their history files if the command is preceded by a space. This usually involves having to set HISTCONTROL to the value ignorespace. This is supported by at least bash and ksh on OpenBSD, but not by e.g. ksh93 or dash. zsh users may use the histignorespace option or their HISTORY_IGNORE variable to define a pattern to ignore.

In shells that support reading with read without echoing characters to the terminal, you may also use

IFS= read -rs password     # -s turns off echoing in bash or zsh
                           # -r for reading backslashes as-is,
                           # IFS= to preserve leading and trailing blanks
sha1pass "$password"

but this obviously still has the same issue with potentially revealing the password in the process table.

If the utility reads from standard input, and if the shell supports "here-strings", the above could be changed to

IFS= read -rs password
somecommand <<<"$password"

Summary of comments below:

  • Executing a command with a password given on the command line, which all of the commands above does, except the one that pipes the data to the command, will potentially make the password visible to anyone running ps at the same time. None of the commands above will however save the typed-in password in the shell's history file if executed from an interactive shell.

  • Well behaved programs that reads clear-text passwords do so by reading from their standard input, from a file, or directly from the terminal.

  • sha1pass does requires the password on the command line, either typed in directly or using some form of command substitution.

  • If at all possible, use another tool.


If using the zsh or bash shell, use the -s option to the read shell builtin to read a line from the terminal device without it echoing it.

IFS= read -rs VARIABLE < /dev/tty

Then you can use some fancy redirection to use the variable as stdin.

sha1pass <<<"$VARIABLE"

If anyone runs ps, all they'll see is "sha1pass".

That assumes that sha1pass reads the password from stdin (on one line, ignoring the line delimiter) when not given any argument.


If you set HISTCONTROL like so:

HISTCONTROL=ignorespace

and start the command with a space:

~$  mycommand

it won't be stored in the history.