git-dumper is a tool that downloads and reconstructs an entire Git repository — full source code and commit history — from a .git directory that a web server has accidentally left publicly accessible. If a deployment ever copies the .git folder into a web-served directory, an attacker running git-dumper against your site can often walk away with your complete codebase, including secrets in old commits you thought were gone. It is one of the most consequential misconfigurations on the web precisely because it is so easy to make and so easy to exploit.
The tooling is mature and public. The most widely used implementation is arthaud/git-dumper, a Python tool, alongside the shell-based gitdumper.sh from the GitTools project and several rewrites. This is defensive knowledge: understanding exactly how git-dumper works is what lets you verify you are not exposed.
Why an exposed .git directory is so damaging
When you run git init, Git creates a hidden .git directory that holds everything — every version of every tracked file, the full commit graph, branch and tag references, and configuration. Your working files are just a checkout of that database. If someone obtains the .git directory, they do not get a snapshot; they get the entire history.
That distinction is what makes the leak severe. Removing a hardcoded API key in a later commit does not remove it from history. The credential still lives in the earlier object, and reconstructing the repository resurrects it. Real incidents have exposed database passwords, cloud provider keys, signing keys, and proprietary source, all from a single web-accessible .git folder. For a closed-source application, it also hands an attacker a perfect map: they can read your authentication logic, find your validation gaps, and craft targeted attacks against code they can now study offline.
The exposure usually happens one of two ways. Either a deployment process copies the whole project directory — .git included — into the web root, or a developer clones a repository directly onto a production server inside a served path. Both are common, and both are silent until someone checks.
How git-dumper reconstructs the repository
Understanding the mechanism makes the defense obvious. The tool works differently depending on how the server is configured, which is why it succeeds so often.
The easy case is directory listing enabled. If the web server returns an index page for /.git/, the tool simply recurses through it and downloads every file, then runs a normal git checkout to reconstruct the working tree. This is the fastest path and requires nothing clever.
The harder — and more interesting — case is when directory listing is disabled, so you cannot browse /.git/. Attackers cannot see the file list, but Git's internal structure is predictable, and that predictability defeats the "you can't list it" defense. The tool starts from known fixed paths that always exist in a repository: /.git/HEAD, /.git/config, /.git/index, and the packed-refs and logs files. From HEAD it learns the current branch; from the index and refs it learns object hashes. Each Git object is stored at a path derived from its SHA-1 hash (/.git/objects/ab/cdef...), so once the tool knows an object's hash, it knows the exact URL to fetch it from — no listing required. It then parses each downloaded object, discovers references to more objects (a commit points to a tree, a tree points to blobs and subtrees), and fetches those in turn, walking the graph until it has everything reachable.
The result is the same in both cases: a full local clone of your repository, reconstructed from nothing but HTTP requests to individual predictable URLs. One safety note worth repeating from the tools' own documentation — pulling down a repository controlled by an attacker can itself be dangerous, since Git hooks and configuration in a malicious .git can lead to code execution, so researchers run these tools in isolated environments.
Checking whether you are exposed
You do not need the attacker's toolkit to test yourself. The single most useful check is a request for the one file that always exists in a real repository:
curl -s -o /dev/null -w "%{http_code}\n" https://your-site.example.com/.git/HEAD
A response of 404 is what you want — the file is not served. A 200 with contents like ref: refs/heads/main means your .git directory is exposed and an attacker can likely reconstruct the whole repository. Also test /.git/config, which frequently reveals the remote URL and sometimes embedded credentials.
Run this check against every environment, not just production. Staging and internal-but-reachable hosts leak just as readily, and they often run with looser configuration. Fold the check into your monitoring so a future misconfigured deploy is caught automatically rather than discovered by someone else.
Closing the hole for good
Fixing the immediate exposure and preventing recurrence are two separate jobs, and you want both.
Stop serving the directory at the web server. For nginx, deny access to any dotted Git path:
location ~ /\.git {
deny all;
return 404;
}
For Apache, a matching rule in configuration (preferred over .htaccess, which can itself be disabled) blocks the path. This is a defense-in-depth layer, not the root fix — but it is the fast one, and you should have it regardless.
Fix the root cause in deployment. The .git directory should never reach the server in the first place. Build artifacts, not clones: your pipeline should produce a deployable package that excludes version-control metadata entirely. If you deploy by syncing files, exclude .git explicitly (rsync --exclude='.git'), and if you must clone on a server, clone outside the web root and symlink only the public assets in. The principle is that the web-served directory contains only what needs to be served, never the repository that produced it.
Rotate anything that was exposed. If a .git directory was public for any window, treat every secret that ever lived in that history as compromised and rotate it. This is exactly why secrets belong in a secrets manager or environment configuration rather than committed to a repository at all — a lesson software composition analysis and secret-scanning tooling reinforce by flagging credentials before they land in history. An exposed .git turns a committed secret from a bad habit into an active breach.
FAQ
Is git-dumper illegal to use?
The tool itself is legal and is a standard part of security testing. Running it against systems you do not own or lack written authorization to test is illegal in most jurisdictions, exactly like any other unauthorized access. Use it only against your own assets or within a scoped engagement.
Does disabling directory listing protect my .git directory?
No. git-dumper's main technique specifically defeats disabled directory listing by fetching Git's predictable internal files (HEAD, index, refs) and then walking the object graph by SHA-1 hash. You must block access to the .git path entirely, not just hide the listing.
How do I know if my .git directory is exposed?
Request /.git/HEAD on your site. A 404 means you are safe; a 200 returning something like ref: refs/heads/main means the directory is exposed and the repository can likely be reconstructed. Check every environment, not only production.
What should I do if my .git directory was publicly accessible?
Block the path at the web server immediately, fix your deployment so .git never reaches the server again, and rotate every secret that ever appeared anywhere in the repository's history — not just current files, since git-dumper recovers the full history including deleted values.