Article

Exposed .env and .git Files: How Attackers Find Leaked Secrets

A misconfigured server can serve .env, .git or backup files directly to anyone who requests them — no vulnerability required. Automated scanners probe for these paths within hours of a server going live. The fix is server config plus rotating anything that was ever exposed.

By Paul Rudenko, Security ResearcherUpdated Aug 26, 20267 min read

A misconfigured web server can serve files it was never meant to: the .env file holding database and API credentials, the .git folder with your entire commit history, or a backup.sql someone left in the web root. None of these require a vulnerability to exploit — they are just files sitting where a browser (or a scanner) can request them directly. This guide covers what commonly leaks, how attackers actually find it, and how to close it off in minutes.

How attackers find these files

Almost none of this is targeted. Mass scanners continuously sweep large blocks of the public internet requesting a fixed list of paths — /.env, /.git/config, /.git/HEAD, /wp-config.php.bak, /backup.sql, /docker-compose.yml — against every IP that answers on port 443. A new server can be probed within hours of first going live, long before a human ever finds it deliberately. Search-engine dorking (filetype:env DB_PASSWORD) finds the rest: sites that were exposed briefly and got indexed before anyone noticed.

None of this is sophisticated. It is closer to someone trying every door on a street than picking a lock — which is exactly why it is worth closing: the cost to an attacker is close to zero, so anything left open gets found.

What commonly ends up exposed

  • .env — database passwords, API keys, mail credentials, signing secrets, third-party service tokens. The single highest-value leak on this list.
  • .git/ — the entire commit history, not just the current state. A secret removed from the latest commit is often still readable in an earlier one; a public .git folder can be reconstructed into a full source-code checkout with widely available tools.
  • Database dumps and backups — backup.sql, dump.sql.gz, .bak files left by a manual backup or a migration script, often containing real customer data.
  • Framework config leftovers — wp-config.php.bak, settings.py.orig, editor swap files (.swp) — a save-as or an editor crash can drop a readable copy of a config file next to the real one.
  • docker-compose.yml / Dockerfile — frequently embed environment variables or registry credentials inline.
  • Source maps (*.js.map) — not a secrets leak on their own, but they unminify your entire front-end source, handing an attacker a readable map of your application logic and any client-side assumptions it makes.
Severity here tracks what the file actually contains, not just that something was found. An exposed .env with live database credentials is critical — treat it as an active breach. A stray .js.map is a lower-urgency hardening gap. Don't let a scanner that flags every hit as "CRITICAL" desensitise you to the ones that actually are.

How to close it off

The fix is almost always server configuration, not application code. Deny the paths at the web server, then confirm the files are also not being deployed into the web root in the first place:

# nginx — block dotfiles and common backup extensions
location ~ /\. { deny all; return 404; }
location ~* \.(sql|bak|swp|orig|env)$ { deny all; return 404; }

# Apache — .htaccess in the web root
<FilesMatch "(^\.|\.(sql|bak|swp|orig|env)$)">
  Require all denied
</FilesMatch>

Better than blocking at the edge: don't ship these files at all. Keep .env, .git and backup files outside the directory your web server serves from, and add them to .gitignore and your deploy tool's exclude list so a routine deploy can't reintroduce them.

If something was already exposed

Deleting the file is not the fix — rotating what it contained is. Treat every credential in an exposed .env as compromised: rotate database passwords, API keys and signing secrets, then remove the file. If .git was exposed, assume the full history was copied before you noticed; purging it from the live repo after the fact does not undo that, so the same rule applies — rotate anything that ever appeared in a commit, not just the current HEAD.

Check whether your site is serving .env, .git or backup files right now — free and passive.

Run the free security scan

What a passive check can and can't see

A passive exposure check requests a curated list of known-sensitive paths over plain HTTP(S) — no login, no exploitation, nothing beyond what any visitor's browser could also request. That covers the common misconfigurations above, but it can't enumerate every possible path on a large or unusual site; a clean result means the paths we checked came back blocked, not that the entire filesystem was audited.

This pairs with the wider posture check in the "why does my site say Not Secure" guide and the guide to raising your security score, where exposed files are one of five weighted signals.

Frequently asked questions

How do attackers find an exposed .env or .git file?

Almost always through mass automated scanning, not targeted attention. Bots continuously sweep large ranges of public IP addresses requesting a fixed list of known-sensitive paths — /.env, /.git/config, /.git/HEAD, /wp-config.php.bak, /backup.sql — against every server that answers. A newly launched site can be probed within hours. Search-engine dorking (queries like filetype:env DB_PASSWORD) catches sites that were briefly exposed and got indexed before anyone noticed. None of this requires skill or targeting a specific victim; the cost to try is close to zero, which is exactly why anything left open tends to get found quickly.

I deleted the exposed .env file — am I safe now?

No — deleting the file removes future access but does nothing about credentials that were already read. Treat every value in an exposed .env as compromised and rotate it: database passwords, API keys, mail credentials, signing secrets. If a .git directory was also exposed, assume the entire commit history was copied before you noticed, including any secret that ever appeared in an earlier commit even if it isn't in the current version — purging git history after the fact doesn't undo a copy an attacker already made, so the same rule applies: rotate anything that was ever committed, not just what's currently exposed.

Is an exposed .git folder as serious as an exposed .env?

It can be worse, because it exposes more than one point in time. Widely available tools reconstruct a full working source-code checkout from a public .git directory, including commit history — so a secret that was committed and later removed is often still recoverable from an earlier commit, and the attacker also gets your application logic, comments and any hardcoded assumptions. An exposed .env leaks whatever is in it right now; an exposed .git can leak everything that was ever in the repository.

What's the actual risk if a database credential leaks?

It's rarely limited to "the website gets hacked." A leaked database password or cloud API key is direct access to the underlying infrastructure — an attacker can read or exfiltrate customer data straight from the database, or use a cloud provider key to spin up resources, access other services under the same account, or pivot further into infrastructure that has nothing to do with the website's own code. This is why these findings are graded as critical rather than treated like a generic misconfiguration.

Does blocking the path at the web server fix this?

It closes the immediate hole, but it's a second line of defence, not the fix. A deny rule for dotfiles and backup extensions (nginx location ~ /\. { deny all; } or the Apache FilesMatch equivalent) is worth having, but the more durable fix is making sure these files are never deployed into the web root at all — keep .env and .git outside the served directory, and add backup and editor-swap extensions to your deploy tool's exclude list so a routine release can't reintroduce the problem.

Related guides

See your whole external attack surface

One page is a start. The full external scan covers TLS, headers, DNS, exposed files, open services and known-exploited CVEs across your whole domain.

See the full scan →