How to Fix an Exposed .git Directory

Your .git directory is publicly accessible, allowing attackers to download your entire source code and commit history. Fix it now.

Critical severity Infrastructure Security Updated 2026-03-01 Markdown

The .git directory is the complete history of a repository — every file that was ever committed, every commit message, every branch, and every change ever made. What many developers don't realize is that this includes files that were committed and later deleted. If you committed your .env file six months ago and then added it to .gitignore, the credentials from that commit still exist in .git/objects and can be fully reconstructed by anyone with access to the directory.

Exploiting an exposed .git directory requires no special skills. The tool git-dumper (publicly available on GitHub) automates the entire process: it downloads the .git directory structure through normal HTTP requests, reconstructs the pack files and objects, and runs git checkout to restore the complete repository. The entire operation takes seconds to minutes depending on repository size. Security researchers include .git checks in their standard reconnaissance toolkit, and automated scanners test /.git/HEAD as one of their first probes against any new domain.

This vulnerability is particularly prevalent because it arises from a server misconfiguration — pointing the web server document root at the project root instead of /public — rather than a code error. The .git directory then becomes web-accessible alongside the application. In security research and bug bounty programs, an exposed .git directory is a critical finding because the full source code access it grants typically unlocks additional vulnerabilities: hardcoded credentials in commit history, internal API endpoints, business logic weaknesses, and specific package versions with known CVEs.

The Problem

An exposed .git directory allows attackers to reconstruct your entire source code repository, including every file, commit history, branch names, and potentially credentials that were committed and later removed. Tools like git-dumper can automatically download the .git directory and rebuild the full repository. This gives attackers your application code, configuration patterns, and any secrets that were ever committed.

How to Fix

  1. 1

    Block .git access in Nginx

    Add this location block to your Nginx server configuration:

    location ~ /\.git { deny all; return 404; }

    This blocks access to .git, .gitignore, .gitmodules, and all subdirectories. Reload Nginx:

    sudo nginx -t && sudo systemctl reload nginx
  2. 2

    Block .git access in Apache

    Add to your .htaccess or Apache configuration:
    RedirectMatch 404 /\.git

    Or using a more comprehensive rule:

    <DirectoryMatch "^\.git">
        Order allow,deny
        Deny from all
    </DirectoryMatch>
  3. 3

    Ensure document root is correct

    Your web server should serve from the /public directory, not the project root. If the document root is correct, the .git directory is one level up and not accessible.

    # Correct - serves from public/
    root /var/www/yourapp/public;
    # Wrong - serves from project root, exposes .git
    root /var/www/yourapp;

    Verify with: curl -I https://yourdomain.com/.git/HEAD

  4. 4

    Use deployment without .git on the server

    The safest approach is to not have .git on the production server at all. Deploy with rsync excluding .git:

    rsync -avz --exclude='.git' ./ user@server:/var/www/yourapp/
    Or use git archive to create a clean export:
    git archive --format=tar HEAD | ssh user@server "tar -xf - -C /var/www/yourapp/"
    CI/CD tools like Envoyer and GitHub Actions can deploy artifacts without the .git directory.

How to Verify

Test that .git is not accessible:

curl -I https://yourdomain.com/.git/HEAD
curl -I https://yourdomain.com/.git/config

Both should return 403 or 404. If you see a 200 response with content like "ref: refs/heads/main", the .git directory is still exposed.

Prevention

Configure your web server to block all dotfile access by default. Deploy without .git on the server. Add .git access checks to your deployment pipeline. Use StackShield to continuously monitor for exposed .git directories.

Frequently Asked Questions

What can an attacker do with my .git directory?

They can download and reconstruct your entire codebase including all historical commits. This reveals source code, configuration files, credentials that were committed and later removed, internal API endpoints, business logic, and vulnerability patterns in your code. Tools like git-dumper automate this process.

I removed secrets from my code. Are they still in .git?

Yes. Git stores all history, so secrets in previous commits remain accessible even after deletion. If your .git was exposed, assume any secret ever committed is compromised. You need to rotate all credentials and optionally rewrite git history with git filter-branch or BFG Repo Cleaner.

Should I use git pull on the production server or a proper deployment tool?

Avoid git pull on production for security and reliability reasons. It requires the production server to have git installed and keeps the .git directory on the server. Instead, use deployment tools like Envoyer, GitHub Actions with rsync, or git archive to deploy only the application files without the .git directory.

Are other dotfiles like .gitignore and .gitmodules also dangerous?

Yes. An exposed .gitignore reveals what files and directories exist in your project (by listing what is excluded), which aids reconnaissance. An exposed .gitmodules reveals the URLs of your private submodule repositories. The web server rule to block all dotfiles (location ~ /\. { deny all; }) covers all of these in a single configuration.

How do I scan git history for secrets that may have been committed?

Use tools like truffleHog (trufflesecurity/trufflehog) or git-secrets to scan your repository history for credential patterns: git log --all --full-history -- "*.env" shows commits that included .env files. Run: trufflehog git file://. to scan all branches and commits for high-entropy strings and known secret patterns.

Free security check

Is your Laravel app exposed right now?

34% of Laravel apps we scan have at least one critical issue. Most teams don't find out until something breaks. Our free scan checks your live application in under 60 seconds.

18% have debug mode on
72% missing security headers
12% have exposed .env
Scan My App Free No signup required. Results in 60 seconds.