Every git repository has a hidden .git folder with the full project history. When a site is deployed with git pull directly into the web root, that folder often ends up public at https://yoursite.com/.git/. An exposed .git directory lets anyone rebuild your source code, read every past commit and find passwords or API keys that were committed at any point, even ones deleted later. Free tools that download a whole repository from an exposed .git directory have existed for years.
Why an Exposed .git Directory Is Critical
- Full source code. Attackers can read your code to find vulnerabilities instead of guessing.
- Full history. A secret removed from the code is still in an older commit. See secrets in git history.
- Credentials in the config.
.git/configsometimes contains a remote URL with a username and access token in it. - Names and emails of everyone who committed, from
.git/logs/HEAD, which helps with targeted phishing.
Directory listing does not need to be on. The attacker requests known file names such as HEAD, config and index, then follows the object references inside them to download everything else.
Step 1: Confirm the Exposure
A 403 or 404 is what you want. A security scan checks /.git/HEAD, /.git/config, /.git/index and /.git/logs/HEAD and only reports a finding when the content matches real git metadata, such as a ref: refs/ line or a [core] section, so a catch-all page that returns 200 does not trigger a false alarm. Check every app and subfolder you deploy separately, for example /blog/.git/HEAD.
Step 2: Block /.git/ on the Server
Returning 404 instead of 403 avoids confirming that the folder exists. On IIS, add a request filtering rule that hides the .git segment. Request /.git/HEAD again and confirm it no longer returns the file.
Step 3: Assume the Code and History Were Copied
Bots scan for an exposed .git directory constantly, so plan as if someone already has the repository.
- Search the history for secrets. Run a scanner such as Gitleaks or TruffleHog against the full history, not just the latest commit. The Gitleaks vs. TruffleHog comparison explains the options.
- Rotate every secret you find and revoke the old values: database passwords, API keys, tokens in
.git/configremote URLs and anything in old.envfiles. - Check access logs for requests to
/.git/that returned200to see when the exposure started and from where. - Review the code for vulnerabilities an attacker could now find more easily, such as hidden admin routes or weak checks.
Rewriting git history to remove a secret is optional and does not help once it has leaked. Rotation is what matters.
Step 4: Change How You Deploy
- Do not deploy with
git pullinto the web root. Build the site and copy only the output, or check out the repository outside the web root and point the server at apublic/or build folder. - Use deploy tools that exclude
.git, such asgit archive,rsync --exclude .gitor your CI pipeline's artifact step. - Keep the server rule from step 2 as a permanent safety net, along with rules for other hidden files.
- Scan regularly. Scheduled security scans catch it if a new server or subfolder app is deployed the old way.
Other Files That Leak the Same Way
The same deploy mistake often exposes more than git. Check for .env files, backups such as backup.zip or database.sql, editor folders like .vscode/sftp.json, and public JavaScript source maps. See how to fix an exposed .env file and how to fix hardcoded secrets in code. To catch secrets before they are committed at all, scan the repository with the repo scanner or in your editor with the VS Code extension.