Many OS tools need login credentials or other secrets to perform their tasks. There are a few ways to provide this information but one that is often recommended as a secure method is to use environment variables. Two important reasons are that the OS does not write environment variables to logs and only privileged users can see the variable values for processes started by the others.
Web developers also need to pass secrets to their server-side programs. The search for security recommendations of how to do this normally leads to the same advice given for OS tools: use environment variables. This advice is so common that the Rails community created a library to make the process easier and many other languages copied that library.
The operating environment and expectations for OS tools and web apps differ significantly even though both run on the same server. OS tools’ user interface is local to the server. It interacts via the console and through disk files. When it does communicate over the network it does so with a remote program that also interacts locally on the remote server. To interact with these programs a user must have access and permission do so. When such a program encounters an internal error it reports the debugging information1 on the console or to log files, all of which are local2.
On the other hand, a web server’s main interface is an untrusted remote computer in a format designed for easy human consumption. When such a program encounters an internal error suddenly the main interface is completely the wrong place to report sensitive debugging information.
With such wildly different operating assumptions it is not a good idea to blindly apply security advice intended for OS tools to web servers and web apps. That is not to say it is always the wrong advice, just that one should consider the situation before implementing the advice.
The pros and cons of passing secrets in environment variables may guide your decision.
- The method is easy and well understood, it is a common practice and there are many tools to deal with it.
- For many hosted services like CI and app hosting it is the main or only method to pass secrets to your app.
- Many web frameworks run in debug mode by default and most frameworks dump the whole environment to the browser when an error occurs while in debug mode. Debug mode is now a security risk.
- It is an easy and frequent mistake to deploy production in debug mode and you may not be aware of your exposure until it is too late.
- Many developers don’t treat the environment as secret because they expect it to contain only non-secret values.
- All the libraries in your application also have access to the complete environment and you don’t know how they use it.
- If secrets are unexpectedly set in the environment the app may use the wrong environment’s credentials and cause data loss.
As always, your particular circumstance will determine whether secrets in the environment is a problem or not. If you do consider them a problem two easy options to consider are: read the secrets as early as possible after app start and then delete them from the environment, or let the deployment process put a file, which is not committed with the source code, containing the secrets on the server and read the secrets from there.