free cybersecurity audit · from the varlock security team

Free .env security review

Paste your .env (or .env.*) file below and our proprietary cybersecurity scanner runs a comprehensive audit: structure, how exposed each secret is, and exactly how to fix it. No signup, no cost, results in seconds. This will help keep your secrets safe.

.env files audited
paste any .env or .env.* file — free security audit
🔒 Security & privacy
Processed in your browser Zero data retention Bank-grade encryption Zero knowledge

Your file is analyzed locally and is never written to disk. We don't log inputs, retain data, or share anything with third parties — all processing happens in-memory and is discarded the moment the audit finishes. Enterprise-grade security, privacy by design. Your secrets are safe with us.

Any env file works — .env, .env.local, .env.production, .env.example, .env.schema, or any KEY=value text. Written for the coding agents that read these files, and the developers they answer to; the audit runs the instant you click.

the problem

An example file is a rumor. A schema is a contract.

The reason a real .env is dangerous to paste anywhere is that nothing marks its values as secret. The committed .env.example that ships alongside it has the same blind spot, plus a few of its own. Here is the same configuration done both ways.

.env.example — graded F
# .env.example

NODE_ENV=development
PORT=3000
DATABASE_URL=postgres://postgres:postgres@localhost:5432/app
API_URL=
STRIPE_SECRET_KEY=sk_live_51H8xQ2KpL9mNvRt3WxYzAbCdEfGhIjKl
NEXT_PUBLIC_STRIPE_SECRET_KEY=
SESSION_SECRET=changeme
# REDIS_URL=redis://localhost:6379
SMTP_PASSWORD=your-password-here
.env.schema — graded A
# @currentEnv=$APP_ENV
# @defaultSensitive=false
# @defaultRequired=infer
# @generateTsTypes(path=env.d.ts)
# ---

# Which deployment this process belongs to.
# @type=enum(development, staging, production)
APP_ENV=development

# Public origin of the API. Different per environment.
# @type=url
API_URL=if(eq($APP_ENV, production), https://api.acme.com, http://localhost:4000)

# Server port. Coerced to a number, must be a valid port.
# @type=port
PORT=3000

# Primary Postgres connection string, including credentials.
# @sensitive @required
DATABASE_URL=

# Stripe secret key. Required everywhere except local dev.
# @sensitive @required=not(forEnv(development))
# @docs(https://docs.stripe.com/keys)
STRIPE_SECRET_KEY=op(op://engineering/stripe/secret-key)

# Publishable key. Safe in the browser bundle - and now that is stated, not assumed.
# @public @type=string(startsWith=pk_)
STRIPE_PUBLISHABLE_KEY=pk_test_51ExampleOnly

What the example file cannot do

It cannot fail your build when a var is missing. It cannot say which vars are secrets, so nothing can mask them in logs or keep them out of an agent's context. It cannot say which are required in production but not locally. It cannot coerce PORT to a number. It cannot stop NEXT_PUBLIC_ from shipping a secret to every browser. And it silently rots the first time someone adds a var and forgets to update it.

What the schema does

One committed file declares types, required-ness, sensitivity, per-environment logic and where each credential comes from. Values load from .env.local, 1Password, AWS, Vault or a prompt. varlock load validates everything up front and masks anything sensitive — in your terminal, your logs, and in what your coding agent gets to see.

varlock.dev →

migrating

Three commands, and the example file is gone

npx varlock init      # reads your .env.example, writes .env.schema
npx varlock load      # validates everything, masks the secrets
npx varlock run -- npm dev   # injects them into your app

Then delete .env.example and stop maintaining a file that lies to you.