When it comes to securing software, understanding how source control systems like Git handle sensitive information is crucial. A common mistake teams make is assuming that "deleted content" in a Git repository is gone forever. However, a vulnerability, identified as CVE-2022-24975 (dubbed "GitBleed"), highlights that this isn't always true, especially if you're not careful with how you clone repositories.

In this post, we’ll break down what GitBleed is, how it impacts your code, why the --mirror option matters, and how attackers could exploit this — so you can protect your codebase. Let’s make it simple.

What is CVE-2022-24975 ("GitBleed")?

GitBleed is not a bug in the code, but a lack of clarity in the documentation for the git clone command up through version 2.35.1. Specifically, the documentation did not make it clear that using git clone --mirror gives you access to _all_ objects (including deleted ones) in the Git repository, while a regular git clone may not.

Deleted content means files or data that have been removed from the project’s current state — but not from the repository’s full history. This matters because sensitive information (like old API keys or passwords) may be exposed, even though it appears "deleted".

Why does this matter?

Security teams or auditors might clone a repository (to scan for secrets, passwords, etc.) expecting that a regular clone will have all the content ever in the repository. But, unless you use --mirror, some content — especially "dangling" blobs, or objects not referenced by any branch/tag — might not be included.

So, "audit" tools relying on regular git clone [repo] can easily miss sensitive or private files that were "deleted" but still exist in the upstream repository history.

1. Create a test repository

git init test-repo
cd test-repo
echo "SECRET_KEY=hardcoded123" > secrets.env
git add secrets.env
git commit -m "Add secrets"

2. Remove the sensitive file and force a garbage collect

git rm secrets.env
git commit -m "Remove secrets"
git gc --prune=now # force object cleaning

3. Push to remote (simulated here by a bare repo)

cd ..
git clone --bare test-repo test-repo-bare.git

4. Delete local copy, clone with and without --mirror

rm -rf test-repo

# Regular clone
git clone test-repo-bare.git test-repo-clone
# Mirror clone
git clone --mirror test-repo-bare.git test-repo-mirror

In regular clone (test-repo-clone)

cd test-repo-clone
git log --all -- secrets.env
cat $(git rev-list -n 1 HEAD -- secrets.env):secrets.env
# Will often fail after gc/prune or be missing if not referenced

In mirror repo (test-repo-mirror)

cd ../test-repo-mirror
git cat-file --batch-all-objects | grep hardcoded123
# You may find the secret still present as a dangling blob!

Exploit: How an Attacker Could Take Advantage

An attacker who gets access to your Git remote (for example, a leaked repository link) could use git clone --mirror to harvest every object, including deleted files and secrets.

Tools like gittyleaks or custom scripts can scan the .git/objects database for high-entropy strings (potential passwords).

Example exploit code

git clone --mirror https://example.com/private.git
cd private.git
grep -obaR 'SECRET_KEY' objects/

This raw scan can expose sensitive variables that you thought were deleted, but remain in the repository data.

Why Was This a Vulnerability?

The vulnerability is misleading documentation in Git up to version 2.35.1, which did not clearly specify that --mirror gives you complete access to _all_ repository data, including deleted objects. Security teams relying on regular clones for their audits could miss private info left in the remote repository.

In other words, audits not using --mirror are not complete — so secrets or old files thought to be "gone" actually weren’t.

Mitigation and Best Practices

1. Always audit repositories with git clone --mirror to get all objects (not just the references).
2. Use BFG Repo-Cleaner or git filter-repo to rewrite history and delete sensitive data _permanently_.
3. After rewriting, force-push and perform a git gc --prune=now on both local and remote repositories.

References

- CVE-2022-24975 Details
- Original Git Issue Report
- Git Documentation - Cloning Repositories
- BFG Repo-Cleaner
- Gittyleaks

The Takeaway

Git is powerful, but deleted doesn’t mean gone — and what you see with a normal git clone isn’t everything that exists. For sensitive or regulated projects, make sure your audits go deep with --mirror, and consider rewriting history to truly clean old secrets. As always: Security through obscurity isn’t enough!

Timeline

Published on: 02/11/2022 20:15:00 UTC
Last modified on: 02/22/2022 20:19:00 UTC