Stephen Last
Stephen Last

Reputation: 5781

Encrypt passwords stored in environment variables

I have a NodeJS app which accesses several databases. At the moment I've used dotenv to store the database passwords in environment variables to avoid saving them in source code (and avoid committing them to the repo).

However, this still stores the passwords in plain text in the .env file, which sits on the server in the app root. If the server was ever compromised the passwords would be there for someone to use to connect directly to the databases.

Is the way to solve this problem, by somehow encrypting the passwords, saving the encrypted string in the environment variables, and have the server (Node) decrypt them before they're used in the connection strings..?

I believe that when something is encrypted, it can always be decrypted. However, doing this avoids storing the passwords in plain text, so they couldn't be used as-is to connect to the database.

Recommendations for npm modules would be great. I've found crypto-js and forge, but I don't know what I should be using.

Is this a professional solution..? What type of encryption should I be using..?

Upvotes: 4

Views: 10035

Answers (2)

Luke Celitan
Luke Celitan

Reputation: 340

You are correct, You are not supposed to use dotenv in production at all. Move all the "secret keys" to the machine you running. Most deployment services use something called environment variables (heroku, AWS, Azure, Netlify) where you can mark them as sensitive. Some services like azure have special services like Azure Key Vault where the keys are encrypted and can be injected into the project via dev ops build or directly into vps or app service.

If you are using custom VPS or something like that, then you set up those like any regular linux machine vars, either add env vars to server start method or edit your bashrc.

Now the main reason to do this way is to actually protect you from Repository security breach. Thats why its imperative never to store any keys or save .env file to repo. Even if you encrypt the keys they will be stored in plain text somewhere in the code / repo.

When someone gains root privileges by escalation or any other method, there is nothing you can do stop them from reading bashrc or look into the server code, so basically game over.

If you are worried about your databases, most probably you can whitelist / blacklist IPs or any other means to limit traffic from external sources, encrypt the database, make sure you have no known vulns in the project, use ssl connection, cors settings (basically properly secure your server).

Important topics to cover here is to learn is the difference between build and runtime variables. Runtime vars will be injected called from the envs vars, and build will be injected into the final code.

You could add encryption as another layer of security but only if the secret and password are kept separately. Dotenv file should be used for local development only.

Upvotes: 1

Jay Kukadiya
Jay Kukadiya

Reputation: 686

Simply first encrypt your password and store in env file then decrypt it whenever you need using crypto-js.

var CryptoJS = require("crypto-js");
var data = "password";

var encrypted = CryptoJS.AES.encrypt(data, "my-secret");
console.log(encrypted.toString());

copy encrypted string and past in env.

Decrypt password

var decrypted = CryptoJS.AES.decrypt(process.env.PASS, "my-secret");
var object = decrypted.toString(CryptoJS.enc.Utf8);

It can be decrypt only if secret key is match like JWT.

Upvotes: 1

Related Questions