Why is passing the secrets via environmental variables considered "extremely insecure"?

extremely insecure and should not be used. Some versions of ps include an option to display the environment of running processes. On some systems, if you set MYSQL_PWD, your password is exposed to any other user who runs ps.


Elaborated on here (via):

Background: in the process image argv[] and envp[] are stored in the same way, next to each other. In "classic" UNIXes /usr/bin/ps was typically setgid "kmem" (or similar group), which allowed it to dig around in /dev/kmem to read information about the active processes. This included the ability to read the process arguments AND the environment, of all users on the system.

These days these "privileged ps hacks" are largely behind us: UNIX systems have all come up with different ways of querying such information (/proc on Linux, etc) I think all(?) of these consider a process's environment only to be readable by its uid. Thus, security-sensitive data like passwords in the environment aren't leaked.

However, the old ways aren't 100% dead. Just as an example, here's an example from an AIX 5.2 machine I have access to, running as a non-root user

[End-of-lifed: 2009. Anyone know about more recent AIX?]

...

For the record, some while back we discovered (on IRC?) that OpenBSD 5.2 has this exact security exposure of leaking the environment to other local users (it was fixed shortly after that release, though).

[Release year: 2012]


This advice in the MySQL documentation is poorly worded.

Passing a password in an environment variable is not less secure than passing it on the command line, on the contrary. Most modern unices expose command line arguments of processes, but not their environment, to all users through the ps command and other similar software. There are exceptions, but I've never heard of a system where it is the opposite (exposing the environment without exposing the arguments).

Including a password in a command that is typed in an interactive shell is a bad idea because the password ends up in the shell history. It's fine if shell history is turned off but you have to remember to do that. This applies whether the password is passed as an argument or in the environment.

What can be more dangerous with environment variables is if the variable is passed to other processes. For example, setting a database password in .profile would be a very bad idea, since it would be visible to all programs. Likewise running a script with export MYSQL_PWD=… near the top that runs many commands beyond mysql would be a bad idea. But if the environment variable is only passed to mysql commands then there's nothing wrong with that.

The MySQL documentation should not use language that rates passing a password through an environment variable as less secure than passing it through a command line argument. It's the other way round. (Unless the environment is set for more than the mysql command but that isn't the scenario described in the documentation.)


The main issue with passing secrets in environment variables is to properly scope that environment to the process that use this secret, and to not give it to processes that should not have it.

It is secure to set an environment variable only for starting a given process that uses it.

But it is not secure to set secrets in environment globally in your shell (for the current session) (and even worse in the global startup files of the shell (.bash_profile, .bashrc, .profile)) because all process launched from that shell will have this secret in their environment. Some may leak them, either on purpose (malware) or not (think about the shell command history or a crash reporting module that dumps the full content of the environment in a log file or on a remote server).

Unfortunately from an application developer point of view, it is impossible to enforce that users of your application will properly scope the environment. I have personally seen so many secrets stored in ~/.profile.

So to avoid bad use of the environment by users, it is safer to not load secrets directly in the environment (to reduce the impact of a leak), and instead use environment variables to pass links to where the secret is really stored: use an additional layer of indirection.