Secrets in Git History

Deleting a secret from code and committing the removal does NOT remove the secret from git history. Every version of every file is preserved in .git/objects. A git clone gives anyone the complete history, including every password, API key, and private key ever committed.

Verified by Precogs Threat Research
githistorysecretsdata-leakUpdated: 2026-03-22

The Git History Problem

Developers frequently commit credentials during development, then remove them in a later commit. They believe the secret is gone — but it persists in git history forever. Tools like git log -p, trufflehog, and simple grep can extract these historical secrets. Force-pushing or rebasing local branches does not affect remote history in GitHub/GitLab.

Real-World Impact

Uber's 2016 breach (57M records) started with AWS credentials found in a GitHub repository. The credentials had been committed, then removed — but were still in git history. Attackers used them to access an S3 bucket with rider and driver data. Similar incidents have affected Samsung, Toyota, and thousands of startups.

Precogs AI Git History Scanning

Precogs AI scans every commit in git history — not just the current HEAD. We analyze diffs, blob objects, and deleted branches for credential patterns. Our scanning covers: full commit history, pull request branches, stash entries, and reflog entries that may contain secrets in orphaned commits.

Attack Scenario: The BGH (Buried Git History) Extraction

1

An enterprise mandates moving all repositories from an internal GitLab server to a cloud-hosted GitHub Enterprise organization.

2

During the migration, developers run `git push --all` to transfer the repositories.

3

The codebase currently passes all modern Static Analysis (SAST) and secret scanning checks.

4

However, an attacker who recently acquired read access to the GitHub org runs a tool like `trufflehog` or `gitleaks` configured to scan deep history.

5

The tool finds an RSA Private Key that was committed 4 years ago for a staging environment, but the key is still actively used in production.

6

The attacker extracts the old commit blob, imports the RSA key, and achieves root access to the production application servers.

Real-World Code Examples

Secret Persistence in Git Objects

Git is an immutable Merkle tree. Every change creates a new snapshot object. Deleting a secret in a subsequent commit does not erase the historical snapshot. Anyone who can clone the repository can traverse the entire historical object database (`.git/objects`) to extract the buried credentials.

VULNERABLE PATTERN
# VULNERABLE: Fixing a leak the wrong way
# 1. Developer accidentally commits a password
echo "DB_PASS=Sup3rS3cr3t" > config.ini
git add config.ini && git commit -m "Added config"

# 2. Oh no! Quick, remove it and commit again!
sed -i 's/Sup3rS3cr3t/REDACTED/g' config.ini
git add config.ini && git commit -m "Removed password"

# The password is now invisible in the current code, BUT...
# An attacker simply views the diff of the previous commit:
git show HEAD^ 
# + DB_PASS=Sup3rS3cr3t (STILL COMPROMISED!)
SECURE FIX
# SAFE: Cryptographic repository rewriting
# You cannot 'delete' a commit in Git normally. You must rewrite history.

# 1. Use an established tool like BFG Repo-Cleaner or git-filter-repo
git filter-repo --replace-text passwords.txt

# 2. Force push the rewritten history back to the origin
git push origin --force --all

# 3. CRITICAL: The secret is still considered burned.
# You MUST rotate the compromised password immediately on the database side
# because copies of the old repository may exist on attacker machines.

Detection & Prevention Checklist

  • Configure Secret Scanners to scan `--all` branches and the full depth of commit history during initial repository onboarding
  • Execute continuous, incremental scans specifically targeting the `.git/objects` directory differences on every pull request push
  • Develop an incident response playbook specifically detailing how to use `git filter-repo` to cleanly rewrite enterprise history without destroying developer workflows
  • Always operate under the assumption that if a secret touches a Git index for even a millisecond, it must be considered burnt and requires immediate cryptographic rotation
  • Understand that force-pushing removes commits from active tree logic but leaves "orphaned commits" in the reflog. Clean up remote GC (Garbage Collection) explicitly
🛡️

How Precogs AI Protects You

Precogs AI scans complete git history — every commit, branch, stash, and reflog entry — detecting credentials, API keys, and private keys that were committed and later removed but still exist in .git objects.

Start Free Scan

Can secrets be recovered from git history?

Yes — every file version is preserved in .git objects. Deleting a secret and committing the removal does NOT remove it from history. Precogs AI scans complete git history including deleted branches, stashes, and reflog entries.

Scan for Secrets in Git History Issues

Precogs AI automatically detects secrets in git history vulnerabilities and generates AutoFix PRs.