Security Scanner

May 18, 2026 · View on GitHub

dotenv-diff scans your source files and .env.example for hardcoded secrets using three complementary techniques.

Table of Contents


1. Provider Pattern Matching (high severity)

Detects known credential formats from popular providers:

ProviderExample pattern
AWS access keyAKIA + 16 uppercase alphanumeric chars
AWS temporary keyASIA + 16 uppercase alphanumeric chars
GitHub tokenghp_ + 30+ alphanumeric chars
Stripe live secretsk_live_ + 24+ alphanumeric chars
Stripe test secretsk_test_ + 24+ alphanumeric chars
Google API keyAIza + 20+ alphanumeric chars
Google OAuth tokenya29. + alphanumeric chars
Firebase token21-char ID + : + 140-char token
JWTThree base64url segments separated by . starting with eyJ
Twilio Account SIDAC + 32 hex chars
Ethereum address0x + 40 hex chars

2. Suspicious Key Name Detection (medium severity)

Flags literal string assignments where the variable or attribute name matches a sensitive pattern:

password, pass, secret, token, apikey, api_key, client_secret, access_token, access-token

Only triggers when all of the following are true:

  • The value is 12+ characters long
  • The value does not contain spaces (space → likely a human-readable label, not a secret)
  • The attribute name is not a known harmless UI prop (label, placeholder, name, title, aria-label, type, autocomplete, inputmode, role, method, enctype, form, etc.)
  • The line does not read from an env accessor (process.env, import.meta.env, SvelteKit $env/*)
  • The value is not a pure interpolation template (e.g. `${a}:${b}`)

3. High-Entropy String Detection (medium / high severity)

Uses Shannon entropy to detect randomly-generated secrets — strings that are statistically too random to be written by hand.

String lengthEntropy thresholdSeverity
32–47 chars≥ 0.85 (normalized)medium
48+ chars≥ 0.85 (normalized)high

In test files (*.spec.ts, *.test.ts, __tests__/, fixtures/, etc.) the threshold is raised to 0.95 to reduce false positives.


Example File Scanning

.env.example files are scanned separately with relaxed rules, since example files are expected to contain placeholder values. Entries are skipped when the value:

  • Is empty
  • Equals example or placeholder (case-insensitive)
  • Contains your_ or CHANGE_ME
  • Contains < (typical for <your-value-here> style templates)

Remaining values are still checked against provider patterns and entropy (threshold ≥ 0.8 for values ≥ 24 characters).


False Positive Protections

The scanner automatically skips values that are clearly not secrets:

PatternExample
UUIDs550e8400-e29b-41d4-a716-446655440000
Hex hashesMD5, SHA-1, SHA-256 (32–128 hex chars)
Short base64 IDs16–20 char base64 strings
Data URIsdata:image/png;base64,...
Relative paths./assets/image.png
SVG path dataM10 20 L30 40 Z
Character set literalsabcdefghijklmnopqrstuvwxyz0123456789 (used with nanoid etc.)
UI label stringsAny value containing spaces
Minified linesLines over 500 characters are skipped entirely
Comment-only linesLines starting with //
Env accessorsprocess.env.MY_KEY, import.meta.env.MY_KEY

Suppressing False Positives

If a finding is a known false positive, suppress it with an ignore comment on the same line.

Single line

const apiKey = 'safe_value_for_tests_123123'; // dotenv-diff-ignore
<a href="https://legacy.internal.com"> <!-- dotenv-diff-ignore -->

Block

<!-- dotenv-diff-ignore-start -->
<img src="https://cdn.safe-service.com/image.png" />
<!-- dotenv-diff-ignore-end -->

Ignore markers are case-insensitive and support //, /* */, and <!-- --> comment styles.

For broader suppression across files or URL patterns, see Ignore Comments and Configuration and Flags.