.env files are the most commonly used way to store environment variables, and hence, to keep secrets out of the source code. However, there are certain risks involved with storing secrets in .env files, that either many of the developers don’t know or choose to ignore.
In this article, we’ll discuss the threats that using .env files poses for secret management while application development and uncover the ways to combat them.
But before we move any further, let’s try to understand what are .env files and how they became the default way of storing secrets in modern-day development.
.env files are plain text files that are used to store environment variables and secrets away or out from the main source code, thus keeping us away from hardcoding any vital information. These variables could be anything from a secret key, database URL, port number, API Key, credentials, etc.
A .env file usually stores secrets in the following format:
Key=Value
For example, here’s an env file:
PORT="3000"
DATABASE_URL="psql://postgres@localhost/db_name"
AWS_KEY="rfiunb34fu93n49iufgn3o2o0ini2ef"
BUGSNAG_API_KEY="33dasdk34bsf23f35871as0fa27"
INTERCOM_KEY="ndeiovnkofrnij30490398u39RIBF39IOENIOWF3ENWKEWENVIO"
MAILGUN_KEY="fdjnbvjoenvlmswsdnjoelfv"
NEW_RELIC_LICENSE_KEY="b583d4eab955872122843a067faca9db5d4202af"
NEW_RELIC_LOG="stdout"
SALESFORCE_TOKEN="feojkvndfjkovnskfn3eni32one"
STRIPE_KEY="sk_test_ejidsfnvoiuebnfvoi3enjkdNCJSB"
These environment variables are parsed and injected into the main codebase while running the server using various tools and libraries. For example - python-dotenv is a python module used to read key-value pairs from a .env file and set them as environment variables in a python project.
The use of .env files for application config and secret management started increasing around 2013 and looking back, .env files have become quite inevitable and have been largely used in development since then. So, what made .env the best alternative for this long?
The major benefits of using a .env file are as follows:
.env.example
can be committed with version control with dummy values for the required environment variables and can be used as a reference for new members onboarding a project, thus reducing the time spent on figuring out the configurations and speeding up the development process.
An .env.example
file may look something like this -
# Environment variables.
STATUS=production
#Development port
DEV_PORT=7000
#Production port
PROD_PORT=8000
#DB CONFIG
HOST=db.host
USER=root
PASSWORD=db.password
DB=db.name
DIALECT=mysql
Despite having several benefits, .env files have some major risks involved. Here are some of the problems that brought .env files down:
There is no standardized schema for the libraries parsing env variables. For example - Parsing the following would give an error on bash while it would run without any error using tools like Foreman, Dotenv, etc because of the spaces around the equal to sign.
PORT = 8080
From the above points, it’s clear that .env files have various serious implications for security as well as development velocity. Teams lose a lot of valuable time and money due to interruptions caused by these files. However, there are now new alternatives emerging to solve these problems. Let’s take a look at these.
We should be thankful to .env files for bestowing us a simple and straightforward way of storing and managing environment variables and secrets, but moving forward, there are better solutions to this.
YAML and JSON are two of the most popular schemas for easily reading and writing data. YAML uses indentation and nesting for designating structure and colon instead of equal to signs. It also has native support for multi-line strings.
An example of a YAML file is as follows:
---
doe: "a deer, a female deer"
ray: "a drop of golden sun"
pi: 3.14159
xmas: true
french-hens: 3
calling-birds:
- huey
- dewey
- louie
- fred
xmas-fifth-day:
calling-birds: four
french-hens: 3
golden-rings: 5
partridges:
count: 1
location: "a pear tree"
turtle-doves: two
JSON on the other hand is even more widely used and strictly imposed. In JSON format, both key and value are enclosed within double quotation marks to denote them as strings and thus making it safe for notating both strings and numbers. Moreover, it uses the encoded \n
newline character which is a safer way to deal with multi-line environment variables.
An example of a JSON file is as follows:
{
"doe": "a deer, a female deer",
"ray": "a drop of golden sun",
"pi": 3.14159,
"xmas": true,
"french-hens": 3,
"calling-birds": [
"huey",
"dewey",
"louie",
"fred"
],
"xmas-fifth-day": {
"calling-birds": "four",
"french-hens": 3,
"golden-rings": 5,
"partridges": {
"count": 1,
"location": "a pear tree"
},
"turtle-doves": "two"
}
}
Secret management software is a new way to deal with secrets on the way, effortlessly as well as efficiently. There is software like Doppler, Consul, Vault, AWS Secrets Manager, etc that can be utilized for centralized secret management service.
Secret management is an essential part of the development process, and .env files are now an old way to do it. Thus, it is important to think meticulously and decide on an alternative to shifting your environment variables from .env files to a more systematic, organized, and well-managed space.
This was it for this article. I hope it was helpful.