Skip to content

raksbisht/secret-history

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

secret-history

npm version downloads license node

Secrets you deleted are still in your git history.

Scans your entire git commit history for accidentally committed secrets, tokens,
and credentials — even ones that were removed long ago but still live in old commits.


Why this matters

Deleting a secret from your codebase does not remove it from git history. Anyone who can clone your repo can run git log -p and read every secret you've ever committed. This tool finds them before someone else does.


Install

npm install -g secret-history

or run instantly with no install:

npx secret-history

Demo

  secret-history

  Scanned:  1,247 commits  (all 1,247 commits)
  Found:    2 critical  ·  1 high  ·  4 low

  ⚠  2 SECRETS STILL IN YOUR CODEBASE
  Rotate these credentials immediately.

  ──────────────────────────────────────────────────────────────

    CRITICAL    ●  AWS Access Key ID
    File:     config/aws.js
    Commit:   a3f2c1d8  Jay Smith  Mar 04, 2024
    Message:  add s3 upload support
    Value:    AKIA************MPLE
    Status:   ⚠  still in HEAD

  ··············································

    CRITICAL    ●  Database URL with credentials
    File:     .env.production
    Commit:   b7e91a23  Jay Smith  Jan 15, 2024
    Message:  initial setup
    Value:    post************5432
    Status:   ⚠  still in HEAD

  ──────────────────────────────────────────────────────────────

  1 secret removed from code but still in git history
  These are readable by anyone who clones this repo.

  ──────────────────────────────────────────────────────────────

    HIGH    ●  GitHub Token
    File:     scripts/deploy.sh
    Commit:   c9d12e45  Jay Smith  Dec 02, 2023
    Message:  automate deployment
    Value:    ghp_****************************4f2a
    Status:   ✓  removed from code

  ──────────────────────────────────────────────────────────────

  How to purge secrets from history:

  Option 1 — git-filter-repo (recommended):
  pip install git-filter-repo
  git filter-repo --path <file> --invert-paths

  Option 2 — BFG Repo Cleaner:
  java -jar bfg.jar --delete-files <filename>
  https://rtyley.github.io/bfg-repo-cleaner/

  After purging, force-push all branches and have collaborators re-clone.

Usage

# Scan full history
secret-history

# Scan only the last N commits (faster for large repos)
secret-history --depth 500
secret-history --depth 100

# Help
secret-history --help

What it detects

Severity Patterns
🔴 Critical AWS Access Key & Secret, Private Keys (RSA/EC/DSA/OpenSSH), GitHub Tokens, Stripe Live Keys, Database URLs with credentials
🟠 High Google API Keys, Slack Tokens, SendGrid API Keys, Twilio Account SIDs, NPM Tokens, Mailchimp API Keys
🟡 Medium JWT Tokens, .env variable assignments (API_KEY=, SECRET_TOKEN=, etc.)
Low Generic quoted assignments — password=, secret=, api_key=, access_token=

What it shows

For each finding:

Field Description
File The file the secret appeared in
Commit Short hash, author name, and date
Message The commit message for context
Value Redacted preview — e.g. AKIA****MPLE
Status ⚠ still in HEAD (needs rotating) or ✓ removed (needs purging from history)

Results are grouped: still-exposed secrets first, then secrets only in history. Within each group, sorted by severity.


How it works

git log --all -p    →  stream full patch history (all branches & tags)
       ↓
  parse + lines     →  only scan lines added in each commit diff
       ↓
  match patterns    →  17 regex patterns across 4 severity levels
       ↓
  deduplicate       →  one finding per (file, pattern, value)
       ↓
  check HEAD        →  is the secret still present right now?
       ↓
  render            →  grouped, colored, redacted output

Memory efficient: history is streamed line-by-line via readline — works on repos with hundreds of thousands of commits without running out of memory.


What to do when you find something

If the secret is still in HEAD (⚠ still in HEAD)

  1. Rotate/revoke the credential immediately with the service provider
  2. Remove it from the codebase
  3. Purge it from history (see below)

If the secret is only in history (✓ removed)

The file no longer contains it, but the secret is still readable in old commits:

# Option 1 — git-filter-repo (recommended, Python-based)
pip install git-filter-repo
git filter-repo --path <file> --invert-paths

# Option 2 — BFG Repo Cleaner (Java-based)
# Download from: https://rtyley.github.io/bfg-repo-cleaner/
java -jar bfg.jar --delete-files <filename>

# After either option — force-push all branches
git push --force --all
git push --force --tags

⚠ After purging history, all collaborators must re-clone the repository. Existing clones still contain the old history.


Requirements

Node.js >= 18
Git Installed and on your PATH (git log is used internally)
Location Must run from inside a git repository

FAQ

Will this find secrets on other branches too?

Yes — secret-history uses git log --all which includes all local branches and tags. If a secret was committed anywhere in the repo's reachable history, it will be found.

It's slow on a large repo

Use --depth to limit the scan to recent commits:

secret-history --depth 200

For a full scan, let it run — history is streamed line-by-line so memory usage stays flat regardless of repo size.

Too many false positives from test files

The low severity findings (generic password=, secret= patterns) often fire on test fixtures with placeholder credentials. Focus on critical and high findings first — those use strict, format-specific patterns that rarely produce false positives.

Is the actual secret value stored or transmitted anywhere?

No. secret-history only displays a redacted preview (e.g. AKIA****MPLE) and never writes the raw value to disk or sends it anywhere. Everything runs entirely locally.

I purged the secret — is my repo safe now?

Only if everyone re-clones. Existing clones still have the old history. Also check:

  • GitHub/GitLab cached views of the file
  • Any forks of the repo
  • CI logs that may have printed the secret

Author

Made by Rakesh Bisht


License

MIT

About

Scans your entire git commit history for accidentally committed secrets, tokens, and credentials — even ones that were removed long ago but still live in old commits.

Topics

Resources

License

Stars

Watchers

Forks

Contributors