GitHub Packages · MIT · Node ≥ 18

dotenv-sentinel

Validate .env files against .env.example or a schema, catch weak and default secrets, and keep .env files out of git, including its history.

  1. 1 Point the @mrlouiswright scope at GitHub Packages in .npmrc

    @mrlouiswright:registry=https://npm.pkg.github.com
  2. 2 Install

    npm i -D @mrlouiswright/dotenv-sentinel
Installing from GitHub Packages needs a token

Published to GitHub Packages, not npmjs.com. GitHub Packages needs a GitHub token with read:packages to install, even for public packages: add //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} to .npmrc or run npm login --registry=https://npm.pkg.github.com.

~/project — zsh
$ npx dotenv-sentinel appdotenv-sentinel — 3 target(s) app/.env.example  variables: 6  gitTracked: true  gitIgnored: false  CRITICAL app/.env.example:6  AWS_ACCESS_KEY_ID looks like a real AWS access key (AKI…LE (20 chars)) in an example file [example-contains-secret]           ↳ AWS_ACCESS_KEY_ID           ↳ fix: Rotate it and replace it with a placeholder.  LOW      app/.env.example:5  JWT_SECRET has an unquoted value with spaces; some loaders cut it off [unquoted-space]           ↳ JWT_SECRET           ↳ fix: Wrap the value in double quotes. ... 2 critical, 5 high, 5 medium, 9 low✖ Failing (fail-on: high).
Real output from running dotenv-sentinel locally on a test fixture.

Why it exists

dotenv-sentinel finds every .env, “.env.*” and “*.env” file in a project and checks three things: completeness (variables missing compared with .env.example or a JSON schema, empty required values, wrong types), secret hygiene (changeme, “<your-key>”, short secrets, debug mode in production files, real credentials left in example files) and git exposure (env files that are tracked, not covered by .gitignore, or present anywhere in history). Values are never printed: every secret is masked. CLI, library and GitHub Action. Node.js 18+, zero runtime dependencies (uses the git CLI when available).

Features

Against .env.example

(or .env.sample, .env.template, .env.dist, <file>.example, or --example): missing variables, undocumented extras.

Against a schema

(--schema env.schema.json): required, empty, type (string, number, integer, boolean, url, email, port, json, enum), pattern, enum, minLength, secret.

Secrets

variables named like secrets (*_SECRET, *_TOKEN, *_PASSWORD, API_KEY, APP_KEY…) holding well-known defaults or placeholders, or shorter than --min-secret-length (16). Example files holding real-looking credentials (AWS, GitHub, Stripe, Slack, private keys, passwords in URLs, high-entropy values).

Production files

(*prod*): DEBUG=true, NODE_ENV=development, http:// URLs to remote services.

Syntax

invalid lines, unterminated quotes, duplicate keys, unquoted values with spaces, ${VAR} references to undefined variables.

Git

tracked env files with values (committed-env), env files not matched by .gitignore, and env files added in any commit of any branch (env-in-history; rotate those secrets).

Usage

# current directory, including git checks

 npx dotenv-sentinel

# Example

 npx dotenv-sentinel apps/api --schema apps/api/env.schema.json

# Example

 npx dotenv-sentinel .env.production --example .env.example --fail-on medium

CI / GitHub Action

permissions:
  contents: read
  security-events: write   # only for the SARIF upload
steps:
  - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
    with: { persist-credentials: false }
  - uses: MrLouisWright/dotenv-sentinel@v1
    with:
      targets: '.'
      fail-on: high
      sarif: dotenv-sentinel.sarif
  - uses: github/codeql-action/upload-sarif@v3
    if: always()
    with: { sarif_file: dotenv-sentinel.sarif }

Options & flags

FlagDescription
--example <file>Compare every env file with this example
--schema <file>JSON schema: { "variables": { "PORT": { "type": "port" }, ... } }
--min-secret-length <n>Minimum length for secret variables (default 16)
--no-gitDo not ask git about tracked/ignored files
--no-historyDo not search git history for committed .env files
Policy and output
-c, --config <file>JSON config (default .dotenv-sentinel.json if present)
-f, --format <fmt>text (default) | json | sarif | markdown
--json/--sarif/--markdown <file>Also write that format to a file
--fail-on <sev>critical | high | medium | low | info | none (default high)
--list-rulesPrint rules and default severities
--no-colorDisable colours

Full reference, config file format and API in the README.

Support this project

Support open-source security tools

I build free, open-source tools that help developers ship safer websites. Every coffee helps keep them maintained, documented and free for everyone.

Buy me a coffee (opens Stripe in a new tab)

Secure checkout by Stripe

Portrait of Louis Wright

About the author

Louis Wright

Cyber security researcher and software engineer based in the UK.

More tools by Louis Wright

58 tools

Sentinels security scanners & CI gates · 19