Passing secrets (password) to a program via environmental variable is considered "extremely insecure" according to MySQL docs and as poor choice (from security aspect) across other resources.

I would like to know why - what is it that I'm missing? In the mentioned MySQL manual(I'm using this as an example), passing password via -p option in command line is considered as "insecure" and via env var as "extremely insecure", bold italic font.

I'm not an expert but I do know the fundamentals: simple ps command, even issued by unprivileged user reads every program alongside with command parameters while only the same user (and root, of course) may read environment of the process. So, only root and johndoe may read environment of the johndoe - started process, while hacked www-data script reads all via ps.

There must be some big deal here that I'm missing - so please explain me what am I missing?

My objective is to have a mean of transferring secret from one program to other, generally, non-interactive.

  • 1
    Using mysql -ps3cret puts your password into your shell history file in plain text. Using a script or other means to put your password into an environment variable means that the password (or the means to expose it) is in that script, or if you export mysqlpasswd=s3cret, that will again simply add your password in plain text to your shell history. – DopeGhoti Jun 6 '17 at 18:26
  • @DopeGhoti if you place the export command into a script and source the script the password would at no time be in your history. The script could only be readable by your user. Using an environment variable properly will keep it out of your command history. The concern is not your command history, it's that the process itself might expose the evaluated argument to tools like ps. – Centimane Jun 6 '17 at 18:31
  • 3
    Besides the everyone-can-see-env problem on some systems, environment variables are passed on down to child processes. Did you remember to always unset all important environment variables before forking something that shouldn't be able to read those values? – thrig Jun 6 '17 at 18:32
  • 1
    You place the export into a script and your password is now in plaintext on disk, which is also a very poor choice. – DopeGhoti Jun 6 '17 at 18:32
  • 2
    @DopeGoti: If we're talking automated stuff, not storing the passphrase anywhere in plain text is kinda hard; you'd need a smartcard/HSM and software that can work with that. – dom0 Jun 7 '17 at 8:46

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]

  • Thanks. I hope "classic UNIX" behavior is dead, at leas on modern distros. – Miloš Đakonović Jun 6 '17 at 18:44
  • If this is trouble only on "classic UNIX" systems I see no big deal in that. Still that drives me to the beginning of my question... Upvote for answer, of course – Miloš Đakonović Jun 6 '17 at 18:45
  • @Miloshio edited to add dates for known versions. – sourcejedi Jun 6 '17 at 18:48
  • @Miloshio You should still see it as a big deal. FYI, read heap exploits are much easier than, say, bypassing file permissions. – Satō Katsura Jun 7 '17 at 6:21
  • 1
    AIX 6100-09 and 7200-00 both prohibit non-root users from seeing other users' environments via ps ewwwax. I don't know when that changed. Additional info: AIX 5.3 went end of support 30 April 2012 – Jeff Schaller Oct 20 '17 at 17:29

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.