Safeguard
Security Guides•

Where should a Node.js app keep secrets: env vars, files or a manager?

A decision guide for Node.js secrets: what env vars, env files and a secrets manager each protect, and where child processes and logs leak them.

Safeguard Security Team
3 min read

Keep secrets outside the code and the repository, inject them at deploy time, and prefer a secrets manager when you can rotate and audit access. Environment variables are fine as the delivery mechanism, but know where they spread: child processes, crash output and logs.

The three options compared

OptionGood forWatch out for
Env vars set by the platformSimple deploys, containersInherited by child processes, easy to print by accident
Env file on diskLocal developmentGets committed or copied, file permissions
Secrets managerRotation, access logs, many servicesExtra moving part, its own credentials to protect

None of these is secure by itself. Each moves the problem somewhere you can control.

How environment variables spread in Node

Node's child process documentation says the env option defaults to process.env. So when your app spawns a subprocess without setting env, the child gets a copy of everything the parent had. If that child is a tool you do not fully control, a build script or a shelled out command, it sees your database password.

Pass only what the child needs:

const { execFile } = require('node:child_process');

execFile('convert', ['in.png', 'out.jpg'], {
  env: { PATH: process.env.PATH }
}, callback);

That one line limits what a compromised helper can read.

Loading from a file

Node can load a file at start with the --env-file flag. The documentation says a real environment variable wins over the same name in the file, and that a missing file raises an error unless you use the optional variant. That makes files a reasonable development default and a poor production one. Details are in the --env-file post.

Decision steps

  1. Is the secret ever committed? If yes, rotate it now, then fix the process. See your npm token leaked for the checklist mindset.
  2. Do you need rotation or per service access control? If yes, use a secrets manager and fetch values at startup or on a schedule.
  3. Is it a small single service? Platform injected environment variables are acceptable. Keep the values out of images and out of repository history.
  4. Do you spawn subprocesses? Set env explicitly on each call.
  5. Do you log configuration at startup? Redact before printing, and never log process.env wholesale.
  6. Scan for leaks before they ship. See pre commit secret scanning.

Mistakes worth naming

Printing config on boot for debugging, then leaving it on. Putting secrets into build arguments, where they can end up in image layers. Sharing one credential across environments, so a staging leak is a production leak. Giving the app a key with far more permissions than it uses.

Treat every secret as short lived. If rotation is painful, that is the thing to fix first, because you will need it on the day a secret escapes.

Safeguard's compliance and evidence automation can help record how secrets handling is controlled, and the free scan at gold.safeguard.sh/scan covers your dependencies.

Quick check

Are environment variables safe for secrets?

They are a common delivery method, not a safe store. Limit who can read them, avoid logging them, and set env explicitly for child processes.

Do I need a secrets manager for one small service?

Not always. If rotation and audit are easy with platform variables, that may be enough. Move when rotation or access control gets painful.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.