Shell Script Password Security of Command-Line Parameters

Shell script password security of command-line parameters

Command lines will always be visible (if only through /proc).

So the only real solution is: don't. You might supply it on stdin, or a dedicated fd:

./my_secured_process some parameters 3<<< "b@dP2ssword"

with a script like (simplicity first)

#!/bin/bash
cat 0<&3

(this sample would just dump a bad password to stdout)

Now all you need to be concerned with is:

  • MITM (spoofed scripts that eaves drop the password, e.g. by subverting PATH)
  • bash history retaining your password in the commandline (look at HISTIGNORE for bash, e.g.)
  • the security of the script that contains the password redirection
  • security of the tty's used; keyloggers; ... as you can see, we have now descended into 'general security principles'

Is it secure to use a password argument in a Windows command?

Windows historically didn't save command history between sessions, only within the session. This was true for the command prompt and for PowerShell.

As Bill Stewart pointed out, Windows PowerShell on Windows 10 and Windows 2016 includes PSReadline by default, which does save your command history between sessions. You can see this by looking at the file here: (Get-PSReadLineOption).HistorySavePath.

But even if it's set to off, or on an OS version that didn't offer the option, that doesn't mean entering a plaintext password as an argument is a good idea.

If you must offer that, you should also have a way to have the program prompt at run time.

For PowerShell and other .Net applications, you have another issue with accepting plaintext passwords: they linger in memory and there's no good way to explicitly clear them.

This issue is two-fold: strings are immutable in .Net, which means you cannot just modify the string with nulls or random characters to clear it in memory (you will actually be creating a brand new string), and on top of that you cannot control when a specific object will handled by garbage collection, so you can't explicitly remove it.

This is why the SecureString class exists, but not everything can use this.

In PowerShell, there is a PSCredential object which stores a user name in plain text and a password as a SecureString. This should always be used in PowerShell, and should be the preferred argument type (in lieu of a separate user name and password).

Most commands in PowerShell that require a credential take it as this type of object.

You can retrieve a plaintext version of the password easily with this object as well. Doing so then puts that into a managed string and you get the risks I mentioned above.

In my opinion though, it is still preferable to use a PSCredential object in these situations, right up until the point you need the plaintext version. It helps to maintain the standardization of this type in both a built-in/'official' capacity, as well as in user-defined commands.

This type is also easily serializable with Export-Clixml into a form that is encrypted. This can give you a really nice way of providing an automated option to use stored credentials in scripts, with nothing in plaintext, and no prompting or user intervention required.

Passing values that the commands in a shell script are going to expect

You need to use the "expect" command to send password.

Refer this answer
using expect in bash script

Hiding secret from command line parameter on Unix


  1. First, you can NOT hide command line arguments. They will still be visible to other users via ps aux and cat /proc/$YOUR_PROCESS_PID/cmdline at the time of launching the program (before the program has a chance to do run-time changes to arguments). Good news is that you can still have a secret by using alternatives:

  2. Use standard input:

     mySecret='hello-neo' printenv mySecret | myCommand
  3. Use a dedicated file if you want to keep the secret detached from the main script (note that you'd be recommended to use full disc encryption and make sure the file has correct chmod permissions):

     cat /my/secret | myCommand
  4. Use environment variables (with caveats). If your program can read them, do this:

     mySecret='hello-neo' myCommand
  5. Use temporary file descriptor:

     myCommand <( mySecret='hello-neo' printenv mySecret )

In the last case your program will be launched like myCommand /dev/fd/67, where the contents of /dev/fd/67 is your secret (hello-neo in this example).


In all of the above approaches, be wary of leaving the command in bash command history (~/.bash_history). You can avoid this by either running the command from a script (file), or by interactively prompting yourself for password each time:

read -s secret
s=$secret printenv s | myCommand # approach 2
myCommand <( s=$secret printenv s ) # approach 3
secret=$secret myCommand # approach 4
export secret && myCommand # another variation of approach 4

Sending passwords securely via command line without being exposed in ps/wmic (Windows,Unix)

This is not possible (at least not on Linux, in a reliable way) to pass program arguments securely.

A possible workaround is to pass the name of a file (or some other resource - e.g. some "reference" to some database entry) containing that password, or use some other inter-process communication facility (e.g. on Linux, fifo(7), shm_overview(7), pipe(7), unix(7), etc...) to pass these sensitive informations. You might also consider using environment variables (see environ(7) & getenv(3)).

On Linux look also into proc(5) to understand what it is able to show about processes - thru /proc/1234/ for the process of pid 1234. Maybe you want seccomp facilities.

On Unix, be aware of the setuid mechanism -tricky to understand-. Use it carefully (it is the basic block of most security or authentication machinery such as sudo and login) since a simple mistake could open a huge vulnerability.

For a software written to work both on Unix & Windows, I recommend passing the password in some file (e.g. in /tmp/secretpassword) and giving the name/tmp/secretpassword (or some D:\foo\bar on Windows) of that file thru some program argument, and make sure to use wisely the file permission mechanisms to ensure that file is not readable by those who don't need it.



Related Topics



Leave a reply



Submit