Vulnerabilities
.env.example vs .env on Production Origins
August 20, 2023
.env.example vs .env on production origins is two files that must not sit next to index.html. /.env (and /.env.local) is live credentials: database URLs, API secrets, APP_KEY. /.env.example is supposed to be placeholders so new developers know which names to set. Teams still copy real values into the example, or the example lists enough names to map the stack. Neither belongs in a public object store. RoastMyOpsec probes /.env and /.env.local with bounded GETs looking for signatures. It does not currently score /.env.example, does not parse dotenv into a loot list, and does not use leaked keys.
The practical difference
.env is the secret store a framework loads at boot. .env.example is documentation that hitchhiked into the static artifact. .env.backup and .env.bak are cousins. Git history of a public /.git is a third channel — see exposed .git vs .env.
A 200 on .env.example is not 'safe because it is an example.' Treat it as an information leak and deny the prefix.
How to choose what to publish
CI: fail if .env, .env.local, .env.example, or .env.* appear in a CDN artifact (keep examples in the private repo only). CDN: deny those names even if CI is perfect. Docs: describe required variables in an internal wiki, not on the marketing host. Staging hostnames that are guessable get the same deny list.
| File | Intended job | Public origin | Takeaway |
|---|---|---|---|
| /.env / .env.local | Runtime secrets | Never | Scored paths on the roast |
| /.env.example | Dev template | Never on the CDN | Not scored today; deny anyway |
| /.git/HEAD | VCS | Never | See .git vs .env |
| /package.json | JS inventory | Usually no | See public package.json |
When .env.example still wins (off the public origin)
It wins in a private repo so onboarding knows variable names with empty or obviously fake values. It never wins as a downloadable object on roastmyopsec.com's customers' CDNs. Pair with dump.sql if the same zip also held a database.
What the roast can prove
Signature hits on /.env and /.env.local can surface. .env.example is not a scored path. A 404 is not proof the file is gone from another prefix. Confirm in the bucket. Pair with framework debug if APP_DEBUG leaked from the same file.
Common mistakes
The first mistake is committing .env.example with yesterday's production URL still in it.
The second mistake is allowing .env* on the CDN because 'the example has no secrets.'
The third mistake is Disallow: /.env.example and calling it access control.
Free audit the URL you own
RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.
Free audit nowFAQ
- Is .env.example a vulnerability?
- On a public origin it is an information leak. Keep templates in the private repo. It is not the same as a live .env, but it is not harmless.
- Does RoastMyOpsec fetch .env.example?
- Not as a scored path today. It does probe .env and .env.local. Deny the whole .env* family at the edge.
- Should I put real-looking keys in the example so it 'works'?
- No. Use empty values or obvious placeholders. Never copy production strings into a template.
Sources
Related guides
Vulnerabilities
Exposed .git vs .env on Production WebsitesVulnerabilities
Public package.json vs Lockfile Advisories on ProductionVulnerabilities
.vscode vs .DS_Store on Production Origins