All guides
Critical severityMisconfigurations

Exposed .git directory: the source-code leak hiding in plain sight

When a web server serves the .git directory alongside your application files, an attacker can download enough objects to reconstruct your full source code — including every secret that was ever committed, even if it was removed in a later commit. AppSafe flags this as critical.

What it is

Git stores the complete repository — every file, every commit, every branch tip — in a hidden .git directory at the project root. If that directory ends up inside your web root and your server doesn't block access to it, the files at /.git/config, /.git/HEAD, and the object store under /.git/objects/ are publicly downloadable.

Reconstructing the full source from a leaking .git directory is straightforward. Tools like git-dumper fetch the index and then pull every referenced object, producing a fully working checkout. Attackers don't need shell access — only a browser.

Why it matters

Your source code almost certainly contains information that raises risk: hardcoded API keys (often in older commits), database schemas, internal endpoint paths, business logic, and auth flows. Even if no secret is currently committed, the history is full of material attackers can exploit.

Git history is permanent by design. A secret committed years ago and then removed still lives in the object store and is downloaded along with everything else. Rotating it is the only way to neutralise it.

How to fix it

Block .git in nginx

Deny all requests whose path starts with /.git/. Return 404 rather than 403 to avoid confirming the directory exists.

location ~ /\.git {
  deny all;
  return 404;
}
Keep .git outside the web root

The most reliable fix is to never deploy the .git directory into the document root in the first place. Structure your build so that compiled output goes to a separate public/ directory and deploy only that, not the project root.

Verify it's blocked

After deploying the fix, request https://yourdomain.com/.git/config in a browser. It should return 404, not the content of your Git config. AppSafe re-checks this on every scan.

Rotate any secrets that were ever committed

If the directory was accessible, treat every API key, password, and token that ever appeared in any commit as compromised. Rotate them — removing the commit is not enough, because the object still exists in the pack files an attacker may have already downloaded.

FAQ

I deploy to a managed platform (Vercel, Netlify, Fly.io) — am I at risk?

Managed platforms that build from source typically deploy only the build output, so the .git directory is not served. The risk is higher with VPS deployments, Docker containers built from the project root, or static-site exports where the whole working tree is copied.

What does AppSafe actually check?

AppSafe requests /.git/config and /.git/HEAD and checks whether the response body looks like a real Git file (matching [core] or ref: patterns). A generic 200 page that isn't Git content is not flagged.

Can I just delete the .git directory on the server?

Yes, if you only need the deployed files to run. But ensure your deployment process doesn't copy it back on the next push. Blocking it at the web server level is a belt-and-suspenders defence for when deployment scripts are inconsistent.

Is your app affected?

AppSafe checks for this and dozens of other issues in one free scan.

Scan my app free