DEV Community

Cover image for Please don't commit .env

Please don't commit .env

Basti Ortiz on December 19, 2018

Let's face it. .env files are amazing. They have an easy-to-read syntax that stores all of our essential configurations into one file. Not only tha...
Collapse
 
bgadrian profile image
Adrian B.G. • Edited
  1. Install the operating system
  2. edit your user global gitignore vim ~/.gitignore
  3. paste:
.idea/
.vs/
.env
.pk
.pem
.pub
Enter fullscreen mode Exit fullscreen mode

Do not think you will not make a mistake, be proactive and presume you will, we are only humans.

Edit: this will prevent adding to your project your IDE config files, environment and private keys

Collapse
 
snowe2010 profile image
Tyler Thrailkill

You shouldn't ignore the idea folder. you're supposed to commit almost all of it to the repo.

intellij-support.jetbrains.com/hc/...
rider-support.jetbrains.com/hc/en-...

Collapse
 
bgadrian profile image
Adrian B.G.

Nope, thats what they say but is it a bad practice.

Each env had its own tweaks and sometimes diffenrent platforms, tasks, settings and folders. Each dev should have the liberty of using its own IDE in their own productive way.

Thread Thread
 
snowe2010 profile image
Tyler Thrailkill

Ah yes, let's not use the tool as instructed. That will go great.

Each env had its own tweaks and sometimes diffenrent platforms, tasks, settings and folders. Each dev should have the liberty of using its own IDE in their own productive way.

Yeah, and they tell you exactly which things to exclude in order to get that.

You should include the idea folder. End of story.

Thread Thread
 
bgadrian profile image
Adrian B.G.

No, sorry.

Do some research on the topic you will see that many other developers share my opinion. Do not blindly trust the IDE creators, for them is a business, for you is just a tool.

IDE's are local tools, they are not related to the project. A big project then will have

.vim
.idea
.eclipse
.atom
.vscode

folders. Where did you saw that?

You can also browse popular open source projects source code and see that most of them do not have IDE config files.

Thread Thread
 
dietergeerts profile image
Dieter Geerts

That's because devs want "clean" repos, but there is a JetBrains template, which will ignore USER settings, but you should still commit PROJECT setttings, as not all settings can be read from .editorconfig or linting etc.... This will help other devs that uses that IDE to not waste time on configuring the IDE to get auto-format correct etc... Also VSCode has files that should be committed.

Collapse
 
nickjj profile image
Nick Janetakis • Edited

That's pretty dangerous advice because it depends on how you configure your application.

I personally commit .env files because they don't contain sensitive information and typically having settings important to being able to start up my app in development. I have a feeling just about anyone using Docker Compose would also commit .env files too since it's used for setting your project name.

I reserve .env.prod or other environment specific files for sensitive API keys and other things I wouldn't want to commit.

Collapse
 
bgadrian profile image
Adrian B.G.

It is not dangerous and also .env.prod is very specific.

You can always commit the files from gitignore, but you have to do it explicitly, so you avoid mistakes --force.

Thread Thread
 
nickjj profile image
Nick Janetakis • Edited

I just mean putting it into your main .gitignore file is dangerous because you run the risk of not committing essential settings to make your project work if it depends on .env being around.

Using --force every time they want to add a file isn't a viable solution IMO. That's a command you might run 50 times a day.

In other words, you should add .env on a per project basis when your project may have .env files that contain sensitive info, just like you would want to ignore any other files that have sensitive data.

Collapse
 
codemouse92 profile image
Jason C. McDonald

Awesome, just did this in all my repos.

Collapse
 
somedood profile image
Basti Ortiz

We're glad to hear that!

Cheers! πŸ₯‚ *clink*

Collapse
 
emmanuelnk profile image
Emmanuel K

Best and most useful solution. prevention before cure.

Collapse
 
joelbonetr profile image
JoelBonetR πŸ₯‡ • Edited

Just to clarity all this text above, which is misleading, the issue is not to commit the .env file!

The issue is storing sensitive data in plain text -be it .env or any other kind of file- inside the repository, either be public (as an obvious security measure) or private (as a double security measure).

It's perfectly fine to have a .env that stores your DB user, password and model if that's meant to point to a local database in your computer (Docker-ized or not) for development purposes or an API key that's meant to work just in local environment within your app cluster. You can then override these values with the production -or any other public environment- ones in the pipeline with the sensitive data values stored in a vault or repository variables.

Best regards

Collapse
 
somedood profile image
Basti Ortiz

The issue is storing sensitive data in plain textβ€”be it .env or any other kind of fileβ€”inside the repository, either be public (as an obvious security measure) or private (as a double security measure).

I totally agree with this. I should have been clearer in emphasizing this point. Of course, hindsight is 20-20 five years later (when this article was first published). πŸ˜…

It's perfectly fine to have a .env... if that's meant to point to a local database in your computer (Docker-ized or not) for development purposes or an API key that's meant to work just in local environment within your app cluster. You can then override these values [in production]...

This is actually my current stance on the subject nowadays. However, strictly out of abundance of caution, I still avoid committing an .env file into any of my repositories. It's more about the fact that I know I will be working with other people, so I just outright .gitignore potentially sensitive files from the get-go. It is not to say that committing .env is inherently evil, but proactive measures are still better than reactive measures when it comes to computer security.

Collapse
 
joelbonetr profile image
JoelBonetR πŸ₯‡

true! 😁

Collapse
 
freecoderx profile image
FreeCoderX

When users access the front-end project, they can naturally capture all the content, so how can the front-end project prevent API key exposure? Is there no way?

Collapse
 
somedood profile image
Basti Ortiz

The most effective way to combat this is to just never embed API keys in the front end. Instead, we use API calls (e.g., fetch) so that some back-end server somewhere performs the API request on behalf of the front end. The API keys thus remain secret in the back end. This is an unfortunately cumbersome but necessary measure.

Collapse
 
freecoderx profile image
FreeCoderX

If so, access the API encryption interface through the fetch reappropriate back-end interface. So the API interface encryption on and from the front and back ends is meaningless.

Thread Thread
 
somedood profile image
Basti Ortiz

What do you mean by encryption, by the way? Are you referring to API keys that are embedded inside JWTs? Or are you referring to the general pattern of encrypting API secrets before sending to the front end?

Thread Thread
 
freecoderx profile image
FreeCoderX

general pattern of encrypting API secrets before sending them to the front end

Thread Thread
 
somedood profile image
Basti Ortiz

I suppose that is one possible way. Personally, though, I would still prefer just having a centralized server that acts as a proxy for privileged API calls.

Collapse
 
isaacdlyman profile image
Isaac Lyman • Edited

What's more alarming about this is that there are still some others who have not reverted their commits.

Just to clarify for anyone reading, a git revert will not solve the problem: you'll still have the .env file visible in your public git history. If you've accidentally committed a secret, you need to remove that commit completely.

If you catch the problem immediately, you can do a git reset HEAD^ followed by git push -f. This deletes the most recent commit and overwrites the remote Git history. If you realize too late what you've done, you'll need a slightly more complicated method (see this useful blog post for pointers).

Of course, on the Internet this is all pretty optimistic; someone could have scraped your secrets while they were publicly visible, even if only for a handful of seconds. The only way to really get your security back is to go change all your secret keys and passwords.

Collapse
 
somedood profile image
Basti Ortiz

Yup! That's true. If at any time you feel that you have been compromised, never hesitate to reset those keys and passwords. In fact, it should be the first thing you should do before messing up the commit history. The less time the API key is valid, the better it will be for everyone (except potential hijackers).

Collapse
 
jacobherrington profile image
Jacob Herrington (he/him)

Not to mention that git push -f opens the door to all kinds of accidents.

Collapse
 
somedood profile image
Basti Ortiz • Edited

Hm, I would recommend adding an .env.sample file in the repository. Instead of filling in the fields with real values, you can add placeholders, redactions, and "pseudo-values".

Then, of course, this would have to be documented and explained in the appropriate README.md.

Or perhaps, you could even forgo the .env.sample file and declare the environment variables in the README.md itself, but I personally prefer the former because it is more explicit.

# .env.sample
NODE_ENV=<production|development>
PORT=<open-port>
API_KEY=<github-key>

# And so on and so forth...
Enter fullscreen mode Exit fullscreen mode
Collapse
 
thomasjunkos profile image
Thomas Junkツ • Edited

I see no point in the general advice, not to commit a .env-file per se: I do it frequently and wondered what this post is about.
It is not about committing a standard configuration in your repo, which could be overriden e.g. by a .env.local. It is about not storing secrets in your repository. That's another topic and indeed best practice.

So my usage of .env seems to differ: providing a sane default configuration, which can and should be overridden and does not contain any secrets whatsoever.

For managing secrets in a repo there is an interesting approach by stackoverflow: github.com/StackExchange/blackbox
which unfortunately I had not the time trying, but looks interesting.

Collapse
 
nathanheffley profile image
Nathan Heffley

The only thing I don't like about doing this is that when I change the defaults, they now show up as a diff. On some of my smaller projects I SSH onto the server and just pull the latest changes, so if I've made a change to my default .env file I have to worry about conflicts. I can avoid this problem in production by having the defaults be my production settings, but then I constantly have a dirty file in development.

The best solution to this in my opinion is to not commit .env and instead commit a .env.example. Then all you have to do is cp .env.example .env and you have the exact same things as before but without a dirty file when you change settings.

Collapse
 
thomasjunkos profile image
Thomas Junkツ

Hmmm. Interesting. I came into first contact with .env files via vuejs. It seems there, that you have a .env file which acts like your ".env.example" and could have a .env.local which contains overrides.

But doing some research that seems an uncommon practice πŸ€”

Mostly there is one .env and it isn't committed.

Collapse
 
somedood profile image
Basti Ortiz

Yes, it's definitely okay to commit the .env file if and only if they contain general and not-so-sensitive information. Otherwise, the point of this article is to remind people that they should think twice before they commit .env files because of the serious ramifications that come with it.

Collapse
 
bauripalash profile image
Palash Bauri πŸ‘»

There's sooooooo... many unaware user be out there , anybody can literally bring their whole business to an end! πŸ˜“

I tried to talk with some of them and make them aware, but got no response for months..πŸ˜‘

Seems like they're like,

What! I don't care about a small .env file, I'm Rich, I don't care!πŸ˜‘

Collapse
 
somedood profile image
Basti Ortiz

You could always show them a demo of the amount of damage you can do if you had access to that "small" .env file. I'm sure they'll be alarmed after that.

Collapse
 
tadman profile image
Scott Tadman

Be very careful when doing this as some wildly misguided company may accuse you of hacking and try and prosecute.

Thread Thread
 
somedood profile image
Basti Ortiz

I'm sure he'll be informing them about the demo beforehand. πŸ˜‰

Thread Thread
 
bauripalash profile image
Palash Bauri πŸ‘» • Edited

@somedood , Yes Yes!

Collapse
 
bauripalash profile image
Palash Bauri πŸ‘»

Will Do.

I've seen many juicy leaks there such as Google Cloud Platform Keys , Facebook Credentials , GitHub Credentials and even someone's phone number πŸ˜‚

Thread Thread
 
somedood profile image
Basti Ortiz

Hack responsibly! πŸ˜‰

Thread Thread
 
bauripalash profile image
Palash Bauri πŸ‘»

Just Proof-Of-Concept πŸ˜„

Collapse
 
ajinkyax profile image
Ajinkya Borade

I need the .env file during build on CI how do I make sure GCP receives my .env file if I have not committed it on github ?

  1. I can use Github /settings/secrets
  2. I can pass them to .env file
  3. But how do I read the (/settings/secrets) same in local setup ?
Collapse
 
somedood profile image
Basti Ortiz

To be honest, I am not exactly versed in the Google Cloud Platform. However, I do know they provide a (paid) Secrets Manager service that does exactly what you need in a secure manner. Otherwise, there doesn't seem to be a "free" workaround.

But that doesn't mean other cloud platforms have this limitation. Heroku, for example, allows you to directly set environment variables in the app itself.

So at the moment, I can't offer you any solutions with GCP. I'm unfortunately not familiar with it.

Collapse
 
ajinkyax profile image
Ajinkya Borade

cool. thanks

Collapse
 
gidsg profile image
Gideon Goldberg

Why have it in your git directory at all? Most frameworks let you override the config location so set it to ~/.app-name/.env or similar. If you need to provide an example dummy config you can check in an .env.sample file.

Collapse
 
somedood profile image
Basti Ortiz

Yes, that's true. At least for me, I think it's just easier to have a .env file because it requires minimal setup and messing around with global configurations.

At least in Node.js, all you have to do is npm install and require the dotenv package. Then in your code, just invoke the dotenv.config() and it should all be running smoothly via the process.env object. This way just saves you from the little extra effort you have to do with the nitty-gritty configurations.

But to each its own. Whatever workflow works the best for you, you should apply it, not because everyone does it but because you feel productive with it.

Collapse
 
rman profile image
Arman

Got a question probably a dumb one :D. Let's say the configs in our .env are just for a client side application like react and it includes api keys and such (no database or backend user pass stuff). Why would we care about committing since after the build all the keys are going to be somewhere inside the built file as well? and its visible through the browser when user is working with the website?

Collapse
 
somedood profile image
Basti Ortiz

First and foremost, that's not a dumb question! πŸ˜‚
You are correct that it shouldn't really matter if the environment variables are truly meant to be deployed with the file bundles.
However, the real issue here is the fact that sensitive keys are publicized in the first place. Needless to say, this is not exactly a secure deployment strategy. Even if the bundles are minified and such, this is a potential attack surface nonetheless.
API keys must be stored and indirectly served via some in-house server-side API, never directly through the client-side code. Potential security risks include (but are not limited to) denial-of-service attacks, impersonation, and backdoor access to app internals. That's no fun!
Though, if the environment variables only include non-sensitive static build configurations and such (i.e. theming options, CSS variables, etc.), perhaps it may be alright to publicize them. Otherwise, you should be extra wary about this deployment strategyβ€”if not reconsider it altogether.

Collapse
 
acroyear profile image
Joe Shelby

Oh, and this doesn't just apply to auth and application keys from cloud providers. It can also apply to the credentials you use for demo and testing servers for your client-side app, and database credentials for server-side apps.

Collapse
 
luk707 profile image
Luke Harris

Take a look at a package I wrote on NPM: (envup). It allows you to version control the structure of your environment as a separate file making it easy for others to setup their own .env file without commiting any of the data to git.

Collapse
 
alyson profile image
aly quey

I add on ~/.gitignore_global. 🐣🐣

Collapse
 
somedood profile image
Basti Ortiz

That's good and all, but as @matthias mentioned, it's still important to add them to your repositories because other people will also work on them. They might not have configured their global .gitignore like you have, which might cause them to accidentally commit the .env file.

Itβ€˜s a good idea to put such things into your global .gitignore.

But keep in mind that you mostly work in projects with other people, so you have to put those things into your repositories .gitignore too, to avoid that your co-workers commit secrets.

Collapse
 
alyson profile image
aly quey

oh thank you. :) I care this.

Collapse
 
itachiuchiha profile image
Itachi Uchiha

I faced the same issue because of our intern. He published .env file for everyone on the internet.

The .env file contains mail, google cloud and bank API keys. It was really terrible.

Collapse
 
somedood profile image
Basti Ortiz

How did you guys manage the situation? Did everyone scramble to reset the API keys while others scrambled to clean up the working tree and commit history?

Collapse
 
itachiuchiha profile image
Itachi Uchiha

I regenerate the mail and bank API keys. I also bank added IP limit to bank API portal.

Our lead was so angry. I created a script to remove critical commit histories before we faced this situation (about 2 years ago). I ran that shell script.

But it was so dangerous. Normally we don't have published repositories.

I can say this was our fault.

Thread Thread
 
somedood profile image
Basti Ortiz

I take it that the intern didn't stay there for long...

Collapse
 
buphmin profile image
buphmin

I agree 100% in any real project.

That said I have a repo on github right now, symfony4-impressions, that I explicitly intended to commit the .env and give to people. In this case I wanted people to have the foobar password for the docker mysql container so they can easily run the performance benchmarks to see for themselves if they wanted.

Collapse
 
acroyear profile image
Joe Shelby

I noted this a few years ago, before ".env" became the norm, but the effect was the same. People were putting their OAuth keys into configuration files, committing them to git, and a bot search came across several thousand exposed keys just looking for Amazon's. Similar numbers probably would have been found with google and others.

In that case, I wanted to make sure that my users knew where to put their stuff, so I created a credentials.template file that showed the format, and that got committed, but my own credentials did not. One could do the same here by having a README.env.txt file to document what to do, and cat that file to the console in an npm post-install hook.

The negative of that, though necessary, is it means you're not distributing running code. They can't just pull your files down and npm start and everything works. They have to finish the init by creating their own files. It may also complicate automated testing systems that would have to be configured to provide that file before running.

If you have made this mistake already, one possible way to fix it is to interactive rebase back to the sha that introduced the problem, wipe the file and add the .gitignore line there, and then deal with the merge conflicts as it pushes the rest up if you ever had to touch that file again (either in format or in updating the data in it).

Of course, how much work that is depends on the age of your code (how many commits and how many branches).

Collapse
 
arturoaviles profile image
Arturo AvilΓ©s

If .env files are so popular, git should warn before such file is commited. Writing a validation could help millions of developers

Collapse
 
somedood profile image
Basti Ortiz

Now that you mentioned it, I'm surprised that it hasn't been implemented yet.

Collapse
 
revskill10 profile image
Truong Hoang Dung

.env is an anti-pattern to me, because it requires overhead to keep it secure.

Collapse
 
somedood profile image
Basti Ortiz

It seems to be quite a popular anti-pattern nowadays. πŸ˜…

Besides, adding one line to the .gitignore file shouldn't be that much of an overhead.

Collapse
 
sobolevn profile image
Nikita Sobolev

And you can also use dotenv-linter to lint your .env files for consistency and best practices: github.com/wemake-services/dotenv-...

 
somedood profile image
Basti Ortiz

No problem, Rajesh! Thanks for reading the article! πŸ˜‰

Collapse
 
msameerbm profile image
Mohamed Sameer

is it ok to commit on private repos?

Collapse
 
somedood profile image
Basti Ortiz

Yes, it could be okay to commit there. At least it's not public. As long as you really trust the cloud service hosting your repository, then it should be fine. No guarantees, though. It's a risk you take when you put something in the internet.

Collapse
 
ondrejs profile image
Ondrej

Here's a relevant article.

Collapse
 
somedood profile image
Basti Ortiz

This is really intricate and interesting. Thanks for sharing! It was a great read (yet very disturbing 😬 from a security standpoint).

 
somedood profile image
Basti Ortiz

Yup, pretty much! The best part about adding a sample file is the fact that it can also serve as documentation for environment variables. One can simply annotate and comment on the sample file.

Collapse
 
david_j_eddy profile image
David J Eddy

110% this. Thank you for sharing Some Dood. And nice GitHub search results to boot! :)

Collapse
 
somedood profile image
Basti Ortiz • Edited

Thank you! I appreciate it. On the note of the GitHub search results, I was really disturbed by how many commits are being made with a similar title. I just felt the need to write about it as a PSA and a friendly reminder to all that they shouldn't commit the .env file unless it's there for a justifiable reason, such as the case with @buphmin .

I agree 100% in any real project.

That said I have a repo on github right now, symfony4-impressions, that I explicitly intended to commit the .env and give to people. In this case I wanted people to have the foobar password for the docker mysql container so they can easily run the performance benchmarks to see for themselves if they wanted.

Collapse
 
ptejada profile image
Pablo Tejada

Thank you for the tip on how to get my projects to the top of the search results...

Collapse
 
jamezrin profile image
Jaime MartΓ­nez RincΓ³n

As if it was fault of Mailgun... It's your friends fault and yours for giving him these credentials.

 
somedood profile image
Basti Ortiz

Wow. It makes me wonder what the hijacker did to rack up a bill of $600.

Collapse
 
somedood profile image
Basti Ortiz

Oh, no. That's just really unfortunate. Do they still remind you to this day or did they terminate the service?

 
somedood profile image
Basti Ortiz

How typical of them. Hays... πŸ€¦β€β™‚οΈ

Collapse
 
ben profile image
Ben Halpern
Collapse
 
tiguchi profile image
Thomas Werner

I looked into this for a project a while ago. I think it's an interesting solution for securely sharing secrets among people who are authorized to configure production servers.

But I also believe that those secrets shouldn't be shared across the entire team to avoid disaster mentioned in some of the anecdotes in this thread, specifically the one about the intern publishing production keys in an .env file. That intern and other devs shouldn't have ever access to those keys in the first place.

I feel that anyone who needs to have access to 3rd party API credentials for local development should just try to generate their own, by signing up developer accounts with those 3rd party web services and registering their own API clients.

It's overhead. But it only needs to be done once and makes absolutely sure that a leak of such credentials is not going to cause any major issues.

In case there is no easy way to sign up yourself (e.g. payment processor APIs) an encrypted store via Git like that makes sense for sharing sandbox environment credentials.

Ideally I believe that .env files and similar configuration files that contain confidential production credentials should be stored in the (encrypted) storage of the CI server and only bundled on build & deploy. A single source of truth, and a single possible point of failure.

Collapse
 
somedood profile image
Basti Ortiz

I agree with the post. It really comes down to resetting and revoking the validity of compromised API keys. Never mind messing up with the commit history; just leave it as is and reset those keys ASAP.