Description
When a web application is deployed by copying a Git repository directly to the web root without excluding the .git directory, the complete version control history becomes publicly accessible. An attacker who discovers the exposed .git directory can reconstruct the full source code, browse commit history, extract previously committed secrets (even those deleted in later commits), and enumerate internal paths, file names, and configuration details that are never exposed in normal operation.
CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor) applies because the .git directory contains information—source code, credentials, internal architecture—that was never intended to be public. A05:2021 Security Misconfiguration covers this as a deployment oversight: the web server is correctly configured to serve the application, but the deployment process has inadvertently included sensitive metadata alongside the application files.
The attack is particularly severe because git history is immutable—a secret committed at any point in the repository's history remains in the .git/objects directory forever, even after being deleted from the working tree or overwritten in a subsequent commit. Tools like gitjacker, git-dumper, and truffleHog automate both extraction and secret scanning of exposed repositories.
How It Works
An attacker discovers the exposed .git directory by requesting known Git metadata files:
# Check for .git exposure
curl -s https://example.com/.git/HEAD
# ref: refs/heads/main <- confirms exposure
curl -s https://example.com/.git/config
# [core]
# repositoryformatversion = 0
# [remote "origin"]
# url = git@github.com:example-corp/production-app.git
Once exposure is confirmed, git-dumper reconstructs the full repository:
# Install and run git-dumper
pip install git-dumper
git-dumper https://example.com/.git /tmp/extracted-repo
# Browse the extracted source
cd /tmp/extracted-repo
git log --oneline --all
The git log reveals historical commits:
a3f291c Remove AWS keys from config (oops)
b7e84d1 Add production database credentials
c91f20e Initial deployment configuration
Even though the AWS keys were "removed," they exist in the object store:
# Retrieve the content of a specific historical commit
git show b7e84d1:config/production.yml
# db:
# host: prod-db.example.com
# password: Sup3rS3cretProd!
git show a3f291c^:config/aws.py
# AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE"
# AWS_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
Testers can also directly read objects from the .git/objects directory if directory listing is enabled, or request packed objects from .git/objects/pack/:
# Direct object access
curl https://example.com/.git/objects/pack/pack-<hash>.idx
curl https://example.com/.git/objects/pack/pack-<hash>.pack
Impact
- Source code disclosure — Complete application source code is available for review, enabling vulnerability research without any access to the running application.
- Credential exposure — Historical commits containing API keys, database passwords, private keys, and cloud credentials are extracted and immediately exploited.
- Internal infrastructure mapping — Configuration files reveal database hostnames, internal service URLs, server IP addresses, and deployment scripts.
- Intellectual property theft — Proprietary business logic, algorithms, and data models are accessible without any authorization.
- Compliance violations — Source code containing PII, hardcoded customer data, or cryptographic keys in violation of regulatory requirements is exposed.
Detection
- Request
/.git/HEADand/.git/configdirectly against all in-scope web servers—a valid response confirms exposure. - Use
git-dumperto attempt a full repository reconstruction; measure coverage by checking whether the dumped repository has a validgit log. - Test for directory listing on
/.git/and/.git/objects/—listing enabled means all objects are directly accessible. - Run
truffleHogorgitleaksagainst any reconstructed repository to automatically identify secrets in current and historical commits. - Test for related exposures:
/.svn/,/.hg/,/.bzr/for other version control systems;/.env,/config.php,/web.configfor configuration file exposures.
Remediation
Exclude .git from web-accessible directories. Configure the web server to deny access to .git and all version control directories:
# Nginx
location ~ /\.(git|svn|hg|env) {
deny all;
return 404;
}
# Apache .htaccess
RedirectMatch 404 /\.git
Use build pipelines for deployment. Replace direct repository deployment with CI/CD pipelines that build artifacts and deploy only the compiled output—never the source repository—to web roots.
Rotate all exposed credentials. Any secret discovered in a .git exposure should be rotated immediately. Do not assume the secret was safe just because the commit was historical or the repository was briefly exposed.
Implement server-side directory listing restrictions. Disable directory listing globally and verify no web-accessible directories allow browsing.
