Basis Lab

Answers · Keeping it safe

Are environment variables safe for storing passwords?

In shortNo: environment variables are convenient, but they are inherited by child processes, visible to process inspection and crash reports, and no record is kept when a password is read from them.

No. Environment variables are not safe for storing passwords. A password placed in one is inherited by every child process, visible through process inspection, readable from a crash dump, and read without any record, so the usual reason for choosing it, that it is hidden, is false.

r=g⋅nr = g \cdot n

Start with the first question: who can read the value. If the place holding it is granted to three groups of eight people, r=3×8=24r = 3 \times 8 = 24 people can read it today. That is already more than the two names a team would offer from memory. The formula is deliberately simple because the answer is usually larger than the estimate. Three groups of eight is twenty-four, and that is before counting administrators who can become the owner, people who can restore a backup, and processes running on the same host. An environment variable adds the last category whether or not anybody granted it.

Inheritance is the first leak

Every child process receives the whole environment. A service that spawns five helper processes has six processes holding the password: the service itself plus five children. Only the service needed the database password. The helpers now have it too, and so does anything a helper starts. This is not a rare configuration. Services shell out to tools constantly, and each tool inherits the entire environment, including every credential in it.

The hidden assumption

The natural guess is that the environment is private to the process. It is not. On many systems the environment of a running process is readable through the process filesystem by the owner and by administrators, and on some older systems and container setups it is readable more widely than that. It also shows up in whatever lists running processes. A crash handler, an error page or a monitoring agent that captures the environment as diagnostic context republishes every password into a third party that was never meant to hold it. None of these reads leaves a line anywhere.

The second question is the one that decides what an incident looks like six months later: is the read recorded. With an environment variable there is no fetch, so there is no moment to log. If somebody read the password an hour ago, there is no line saying who, when or from where, and no line to look at later. A secret service answers that question because every fetch is recorded against an identity. The environment answers it with silence.

What changes the answer

If the password unlocks very little and the only attacker you are defending against is somebody reading source code, a file with restrictive permissions is a better default: the operating system enforces the permission on every open, though reads are still unrecorded. If you need to know who read it, use a secret service with per-identity access and logged fetches. If the value must survive crash dumps and child processes, use the operating system key facility, which keeps it out of the environment. If a total compromise of the host must not yield the value, use hardware that never returns it. Every option except hardware still needs a bootstrap credential, so the question moves to whatever unlocks the chosen place. The choice is not between secure and insecure. It is between which attacker you are stopping and which one you are accepting.

The environment variable remains acceptable only for values that are not secrets, such as a log level or a port. For a password it fails both questions at once: too many readers and no record. Replacing it with a file is an improvement because it reduces the reader count. Replacing it with a secret service is a different kind of improvement because it creates the record.

Worth keeping

  • An environment variable is inherited by every child process, so a helper tool receives the password whether it needs it or not.
  • A read from an environment variable is recorded nowhere, so you cannot answer who read it six months later.
  • A file with restrictive permissions is a better default than an environment variable for a low-value credential.

Where this goes next

This question is one step of Keeping a Secret in Production, a course that works through its subject from the beginning. The page that teaches this part of it is Where It Can Live Instead, and it reads the whole way through whether or not you have an account.

What an account changes is the practice: problems standing under every idea, marked with a reason rather than a tick, in a copy of the course that is yours.

Read that pageThe whole course

Other questions people ask about this

  1. How do I stop one service from reading another service's password?Give every service its own identity, grant only the credentials it uses, and test that it cannot read another service's password.
  2. Is a TLS certificate itself a secret?No. The certificate is public and is sent to every client that connects. The private key kept beside it is the secret, and it is one of the highest value credentials you hold.
  3. How does text I saved in a comment end up running as JavaScript in someone else's browser?The comment stayed text in storage; a page that later pasted it into its own markup made the browser read it as code.
  4. Why does escaping the quotes in user input not stop SQL injection?Escaping quotes only cleans one context; SQL injection stops only when query text and values travel separately, so the value is never parsed as code.
  5. Why isn't encrypting the password enough to keep it safe if the database leaks?Because encryption can be undone by your own login code, so the key that lets you check a password usually sits near the database, and anyone who copies both can read every password.
  6. Is it actually OK to look at a risk and decide not to fix it?Yes, if the decision not to fix it is written down with a reason, a named owner and a date or trigger for looking again; otherwise it is just an oversight.

Read alongside