Assembling core
Skip to content
Open source · Node.js secrets

ENVShield: the dotenv alternative that protects your secrets.

ENVShield replaces dotenv with a typed, validated configuration object. Secrets become Secret<T> values that print as [REDACTED] in logs, errors and JSON, and freeze() deletes them from process.env, so code that reads the environment afterwards, including child processes, gets nothing.

v0.1.1MITTypeScript, Node 20+Zero runtime dependencies
Terminal demo: envshield audit flags a secret that is not wrapped, a Node.js session shows the config printing API_KEY as Secret([REDACTED]) and JSON output redacted, process.env.API_KEY is undefined after freeze(), and envshield check fails on a missing variable.
Built from ENVShield’s own CLI messages and documented redaction behaviour. Tap the terminal to open it full size.

What ENVShield is

ENVShield is an open-source configuration and secrets library for Node.js that replaces dotenv. It loads .env files and other providers, validates every variable against a schema at startup, wraps secrets in a Secret<T> type that redacts itself everywhere except an explicit .reveal(), and can delete secrets from process.env once they are loaded.

What it is not

  • It does not stop a .env file being committed. envshield audit warns when one is missing from .gitignore.
  • It cannot wipe a secret from memory: JavaScript’s garbage collector gives no such guarantee.
  • It is not a drop-in import. envshield() is async, and a secret needs .reveal() at the point of use.
  • It does not expand ${VAR} interpolation, by design: no shell expansion means no injection.
At a glance

ENVShield in eight facts.

Type
Open-source node.js secrets tool
Licence
MIT
Language
TypeScript
Runs on
Node.js 20 or newer, ESM and CommonJS
Latest release
v0.1.1, 4 Apr 2026
Status
Released

The problem

dotenv copies every key into process.env, a process-wide, untyped object that every package in node_modules can read. One compromised dependency, or one console.log of the config, is enough to leak every API key the app holds. Supply-chain worms such as Shai-Hulud, in September 2025, spread by harvesting credentials like these from developer machines and CI pipelines.

How ENVShield approaches it

ENVShield moves configuration into a typed object you control. Values are validated at startup against any Standard Schema validator, such as Zod, Valibot or ArkType, so a bad deploy fails on boot. Secrets live in a native private class field that JSON.stringify, template literals, util.inspect and error messages cannot reach, and freeze() removes them from process.env before workers or child processes start.

How it works

From input to decision.

ENVShield loads .env, .env.local, .env.{env}, .env.{env}.local and process.env in order, validates them against a schema, returns a typed config whose secrets print as [REDACTED], and freeze() removes the secrets from process.env.
01 .envShared base, no secrets
02 .env.localLocal overrides, gitignored
03 .env.{env}Per-environment values
04 .env.{env}.localLocal per-environment overrides
05 process.envCI/CD values win
06 Validate, freezeTyped config, secrets out of env
Capabilities

What it does.

Secret<T> redaction

JSON.stringify, template literals, console.log, Object.keys and error messages all see [REDACTED]. Only .reveal() returns the value.

freeze() for process.env

Deletes every secret key from process.env and leaves non-secrets in place for framework compatibility.

Fail-fast validation

A typed config from any Standard Schema validator, with one startup error that names every failing field.

Multi-environment loading

A predictable .env inheritance chain, with values from the CI environment taking the highest priority.

AWS Secrets Manager provider

Default credential chain only, in-memory TTL cache, prefix mapping and batched reads. Errors never include ARNs or values.

CLI: check, audit, generate-types

Verify required variables in CI, flag .env files missing from .gitignore, and generate a typed ProcessEnv declaration.

Quickstart

Running in five minutes.

Zod is optional: any Standard Schema validator works. Add @aws-sdk/client-secrets-manager only if you use the AWS provider. Node.js 20 or newer.

Install
npm install @thekaloliya/envshield zod
Load, validate and protect
import { envshield, s } from '@thekaloliya/envshield';
import { z } from 'zod';

const config = await envshield({
  schema: {
    DATABASE_URL: z.string().url(),
    PORT: z.coerce.number().default(3000),
    API_KEY: s.secret(z.string()),
  },
});

console.log(config.API_KEY);   // Secret([REDACTED])
config.API_KEY.reveal();       // the only way to read the value
envshield.freeze(config);      // API_KEY is deleted from process.env
Comparison

ENVShield and dotenv, side by side.

dotenv loads files. ENVShield loads, validates and protects. Both read the same .env format.

ConcerndotenvENVShield
Type safetyEvery value is string | undefinedValidated, typed config object
Secret redactionSecrets appear in logs and errorsSecret<T> prints [REDACTED]
Child processesInherit every variablefreeze() deletes secrets first
ValidationFails at runtime, when code runsFails at startup, naming each field
Multiple environmentsManual file juggling.env to .env.{env}.local chain
AWS Secrets ManagerNot supportedBuilt-in provider with caching
Runtime dependenciesNoneNone in the core
Who it is for

Built for.

Node.js backend teams

Typed, validated configuration instead of string | undefined at every call site.

Apps holding payment and API keys

Secrets that cannot leak through a stray log line, error report or serialized response.

Services that spawn workers

Child processes started after freeze() inherit no secrets from the parent.

Teams running on AWS

Secrets Manager as a first-class provider, with local .env overrides for development.

Limitations

What it does not do yet.

Stated in the project’s own documentation, so you can decide where it fits.

  • Variable interpolation and the export prefix are intentionally not supported in .env files.
  • Code that already copied a secret from process.env before freeze() keeps its copy.
  • Memory zeroing is not possible in JavaScript; Buffer-based zeroing is only planned.
  • envshield audit checks .gitignore entries and variable names; it is not a secret scanner.
Maintainer

Built and maintained by Parth Kaloliya

Founder & Director, ZettaCore Labs. ENVShield is developed in the open: issues, pull requests and the full release history are on GitHub.

More open source

The other tools.

AI code provenancePython · Apache-2.0 · v0.1.7

Attest

Signs AI-authorship claims and human review evidence for every pull request with Sigstore, then gates the merge.

GitHub
LLM drift testingTypeScript · Apache-2.0 · v0.9.0-beta.1

AIDrift

Versions prompts and model settings, detects LLM behavior drift with statistics, and blocks regressions in CI.

GitHub

Cloud & Infrastructure

Cloud architecture, migration, DevOps and platform engineering - designed for predictable cost, fast recovery and deployments that are boring on purpose.

Software Engineering

Web, mobile, SaaS and enterprise systems built on durable foundations - clear domain models, typed boundaries and tested paths.

FAQ

Questions we get asked.

ENVShield is an open-source, type-safe replacement for dotenv in Node.js. It validates environment variables against a schema at startup, wraps secrets in a Secret type that prints as [REDACTED] in logs and JSON, and can delete secrets from process.env after loading.

dotenv loads .env files into process.env as untyped strings. ENVShield validates them into a typed object, wraps secrets so they cannot be logged or serialized by accident, and can remove them from process.env. It reads the same .env format, so migrating is mostly a change at startup.

Yes. Zod is an optional peer dependency. Any validator that implements the Standard Schema specification works, such as Valibot or ArkType.

After freeze(), any code that reads a secret from process.env, including dependencies and child processes started later, gets undefined. Non-secret variables stay in place, and the typed config object keeps working.

Not through normal JavaScript operations. Secret returns [REDACTED] from toString, toJSON and util.inspect, and keeps the value in a native private class field. Only .reveal() returns it.

Node.js 20 or newer. The package ships ESM and CommonJS builds with TypeScript declarations, and its core has no runtime dependencies.

Want these controls in your delivery pipeline?

We implement provenance gates, LLM regression testing and secrets hygiene for teams shipping AI and fintech systems. Tell us what you run today.