← Back to the Dotenv Exposure Checker
A dotenv file only becomes a problem when a production deployment leaves it publicly reachable. There are four common, independent ways that happens, and each has its own fix — fixing one does not fix the others.
Frameworks that read a project-root .env by convention (Node.js via
dotenv, Next.js, Laravel, Django, Rails) expect it to sit beside the application
code — not inside whatever directory the web server serves as static files. If the web server's
document root is the project root itself, .env is servable like any other file.
# Wrong: the web server's document root is the project root
document_root: /var/www/myapp/ # myapp/.env is right there, servable
# Right: serve only the build output, one level below
document_root: /var/www/myapp/dist/ # myapp/.env is outside the served tree entirely
Even with a separate web root in mind, a cp -r . or rsync -a ./ deploy
script copies everything in the working directory — .env included — to wherever it
is pointed. Copy only the built output, or exclude it explicitly:
# rsync example
rsync -a --exclude='.env*' ./ user@host:/var/www/site/
Most hosting platforms — a PaaS dashboard, a container orchestrator's secret store, a systemd
unit's Environment= directives — let you set environment variables directly on the
running process, with no file on disk at all. Relying on always having a correctly-placed
.env file in every environment is both more fragile and strictly riskier than this.
Defense in depth: even with the deploy step fixed, a server or CDN rule that denies any request for a dotfile means a stray copy — a one-off manual deploy, a misconfigured mirror — is not actually reachable.
# nginx example
location ~ /\.env { deny all; return 404; }
# Apache example (.htaccess in the document root)
<Files ~ "^\.env">
Require all denied
</Files>
Fix the deploy cause first (steps 1–3 above), then treat every value that file held as compromised and rotate it immediately — an API key, a database password, a session secret, a third-party token. Rotation is the only remedy once a credential has been served publicly, even once: there is no way to know for certain it was not already fetched by an automated scanner before you found it.
Run the Dotenv Exposure Checker against your production URL to see which of these, if any, apply to your deployment right now. Only run it against a site you own or are authorised to test.