Skip to main content

Scan git history for secrets, API keys, and passwords — even ones deleted long ago.

Project description

secret-time-machine

"The Past is Not Private"

A Python CLI tool that scans the entire git history of a repository for secrets, API keys, passwords, and tokens — including ones that were "deleted" long ago. git rm does not erase history. Every secret ever committed is still there.

Why this exists

Developers often commit secrets accidentally and then delete them with git rm or a follow-up commit. The secret looks gone from the working tree, but it is permanently embedded in git history. Anyone who clones the repo — now or in the future — can read every commit, including the deleted one.

secret-time-machine time-travels through every commit and every diff to surface those forgotten credentials.

Installation

pip install secret-time-machine

Or from source:

git clone https://github.com/yourusername/secret-time-machine
cd secret-time-machine
pip install -e .

Quick start

# Scan the current directory's git history
secret-time-machine

# Scan a specific repo
secret-time-machine --repo /path/to/repo

# Output JSON for CI pipelines
secret-time-machine --json

# Show full secret values (default is to redact)
secret-time-machine --show-secrets

# Get remediation instructions
secret-time-machine --remediation

All options

Usage: secret-time-machine [OPTIONS]

Options:
  --repo PATH          Path to the git repository to scan.
  --branch TEXT        Scan only commits on this branch (default: all).
  --last N             Scan only the last N commits.
  --additions-only     Only report secrets in addition lines (+ lines).
  --json               Output results as JSON.
  --show-secrets       Show full secret values (default: redact).
  --redact             Explicitly redact secret values (this is the default).
  --remediation        Show instructions for cleaning secrets from history.
  --version            Show the version and exit.
  --help               Show this message and exit.

What it detects

Pattern Severity
AWS Access Key (AKIA...) HIGH
AWS Secret Key HIGH
GitHub Token (ghp_...) HIGH
GitHub OAuth (gho_...) HIGH
OpenAI API Key (sk-...) HIGH
Anthropic API Key (sk-ant-...) HIGH
Stripe Secret Key (sk_live_...) HIGH
Google API Key (AIza...) HIGH
Slack Token (xox...) HIGH
Private Keys (RSA, EC, OPENSSH) HIGH
SendGrid API Key HIGH
HuggingFace Token (hf_...) HIGH
NPM Token (npm_...) HIGH
Database URLs (postgres, mongo, redis) HIGH
Generic Password (password = "...") MEDIUM
Generic Secret (api_key = "...") MEDIUM
JWT Tokens MEDIUM
Heroku API Keys MEDIUM
And more...

Example output

╔══════════════════════════════════════════╗
║         SECRET TIME MACHINE              ║
║      "The Past is Not Private"           ║
╚══════════════════════════════════════════╝

Scanning: /Users/user/myproject
Commits scanned: 1,247 (across all branches)
Time range: 2021-03-14 to 2024-11-22

SECRETS FOUND IN HISTORY: 2

  x OpenAI API Key  HIGH
    Commit:  a4f8c2d  (2023-08-14 by jane@example.com)
    File:    config/settings.py
    Status:  DELETED in commit b9e3f1a — still in history, key may be compromised
    Value:   sk-••••••••••••••••••••••••XKBP

  x AWS Access Key  HIGH
    Commit:  3c7d9a1  (2022-11-30 by bob@example.com)
    File:    deploy/terraform.tf
    Status:  Still present in current codebase!
    Value:   AKIA••••••••••••MNPQ

How it works

  1. Runs git log --all --format="%H %ae %aI" to collect every commit hash across all branches.
  2. For each commit, runs git diff-tree --no-commit-id -p -r {hash} to get the full patch.
  3. Scans every line starting with + (additions) against all secret patterns.
  4. Checks whether each found secret is still present in HEAD or was later deleted.
  5. Reports findings sorted by severity, with optional JSON output for CI integration.

Remediation

Run secret-time-machine --remediation for the full guide. Short version:

  1. Use git filter-repo to purge secrets from history (or BFG Repo Cleaner for large repos).
  2. Force-push the rewritten history.
  3. Rotate every exposed credential immediately.
  4. Add .env files to .gitignore and install pre-commit hooks to prevent future leaks.

CI integration

Use the --json flag and check the exit code. The tool exits with code 1 if any secrets are found, 0 if the history is clean.

# GitHub Actions example
- name: Scan git history for secrets
  run: secret-time-machine --json --additions-only > scan-results.json
  continue-on-error: true

- name: Fail if secrets found
  run: |
    count=$(jq '.summary.total_findings' scan-results.json)
    if [ "$count" -gt 0 ]; then exit 1; fi

Development

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest -v

# Type checking
mypy src/

# Formatting
black .
isort .

Security note

This tool calls git via subprocess with a list of arguments (never shell=True) and uses shlex.quote() for any user-provided paths, preventing shell injection attacks.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

secret_time_machine-1.0.0.tar.gz (21.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

secret_time_machine-1.0.0-py3-none-any.whl (16.3 kB view details)

Uploaded Python 3

File details

Details for the file secret_time_machine-1.0.0.tar.gz.

File metadata

  • Download URL: secret_time_machine-1.0.0.tar.gz
  • Upload date:
  • Size: 21.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.6

File hashes

Hashes for secret_time_machine-1.0.0.tar.gz
Algorithm Hash digest
SHA256 5d623aaf153858db66e07461881afaff3aaec15e14dd029cc5cc7f03f55dc5c7
MD5 8f7bf550c83e0a4d20f07b2e29c7f5cc
BLAKE2b-256 a5d1664ce572cfb734593a64a51aea563a397245574cdd9e22cce70827b61302

See more details on using hashes here.

File details

Details for the file secret_time_machine-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for secret_time_machine-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e723dfd7106c1f31e1105a1352cdd496bf97be58829849454972870302b97764
MD5 e8aa566471d2a0828a50a9b587b1c928
BLAKE2b-256 d1884ecd4230c6ce4d900e9512fbd7c3309909783ba5f2de350f57b6022322a8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page