← Back to Blog

How to Detect Secrets in GitHub Repositories

Secrets committed to GitHub repositories are the number one cause of credential leaks. Whether it is an AWS key, a database password, or an API token, once a secret enters git history, it persists even after deletion. This guide covers every tool and technique for finding and preventing secret leaks in your repositories.

The Scale of the Problem

GitGuardian's 2025 State of Secrets Sprawl report found 12.8 million new secrets in public GitHub commits in a single year. That is a 28% increase from the previous year. And this only counts public repositories. Private repositories contain even more secrets because developers feel a false sense of security when code is not publicly visible.

The consequences are severe. Research shows that exposed secrets are discovered by automated bots within one to five minutes. AWS keys leaked on GitHub are exploited for cryptocurrency mining within minutes, with bills reaching tens of thousands of dollars. Stripe keys are used to issue fraudulent charges. Database credentials lead to full data exfiltration.

GitHub Native Secret Scanning

GitHub offers built-in secret scanning that detects over 200 secret patterns from 100+ service providers. It is free for public repositories and available with GitHub Advanced Security for private repositories.

Enabling Secret Scanning

  1. Go to your repository Settings
  2. Navigate to "Code security and analysis"
  3. Enable "Secret scanning"
  4. Enable "Push protection" to block commits containing secrets

Push protection is the most valuable feature because it prevents secrets from ever reaching the repository. When a developer tries to push a commit containing a detected secret, the push is blocked with a clear message explaining what was found and how to fix it.

Limitations of GitHub Secret Scanning

  • Only detects known patterns from partnered providers
  • Does not detect custom secrets, internal tokens, or generic passwords
  • Push protection requires GitHub Advanced Security for private repos ($49/user/month)
  • Does not scan existing git history retroactively (only new pushes)

TruffleHog: Deep Git History Scanning

TruffleHog is the most comprehensive open-source secret scanner. It scans the entire git history, including deleted commits, and supports both pattern matching and high-entropy string detection.

# Install TruffleHog
brew install trufflehog

# Scan a GitHub repository (including all history)
trufflehog github --repo=https://github.com/your-org/your-repo

# Scan a local git repository
trufflehog filesystem --directory=/path/to/repo

# Scan an entire GitHub organization
trufflehog github --org=your-org-name

# Scan only verified secrets (reduces false positives)
trufflehog github --repo=https://github.com/your-org/your-repo --only-verified

TruffleHog supports over 800 secret detectors and can verify whether detected secrets are still active by making safe API calls to the relevant service. This dramatically reduces false positives.

Gitleaks: Fast CI/CD Integration

Gitleaks is lightweight, fast, and designed specifically for CI/CD pipeline integration. It uses regex-based rules defined in a TOML configuration file.

# Install Gitleaks
brew install gitleaks

# Scan the entire repository
gitleaks detect --source=/path/to/repo --verbose

# Scan only new commits (ideal for CI/CD)
gitleaks detect --source=. --log-opts="HEAD~1..HEAD"

# Generate a JSON report
gitleaks detect --source=. --report-format=json --report-path=gitleaks-report.json

GitHub Actions Integration

name: Secret Scanning
on: [push, pull_request]
jobs:
  gitleaks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Check Your Web Infrastructure Too

Secrets leak through more than just git repos. Exposed .env files, config files, and debug endpoints on your web server are equally dangerous.

Scan Your Domain Free

Pre-commit Hooks: Stop Secrets Before They Enter Git

The best secret is one that never reaches the repository. Pre-commit hooks run locally before each commit and block commits containing detected secrets.

Using detect-secrets (Yelp)

# Install detect-secrets
pip install detect-secrets

# Create a baseline (existing secrets to ignore)
detect-secrets scan > .secrets.baseline

# Add pre-commit hook
cat >> .pre-commit-config.yaml << 'EOF'
repos:
  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.4.0
    hooks:
      - id: detect-secrets
        args: ['--baseline', '.secrets.baseline']
EOF

# Install the pre-commit hook
pre-commit install

Using git-secrets (AWS)

# Install git-secrets
brew install git-secrets

# Initialize in your repository
cd /path/to/repo
git secrets --install
git secrets --register-aws

# Add custom patterns
git secrets --add 'sk_live_[a-zA-Z0-9]{24}'
git secrets --add 'ghp_[a-zA-Z0-9]{36}'

# Scan existing history
git secrets --scan-history

What to Do When You Find a Secret

  1. Revoke the secret immediately. Go to the provider's console and disable the key. Do not wait until you have cleaned up the repository.
  2. Generate a new secret. Create a replacement and update your application configuration.
  3. Remove the secret from git history. Use BFG Repo-Cleaner (faster) or git filter-repo:
# Using BFG Repo-Cleaner
java -jar bfg.jar --replace-text passwords.txt repo.git
cd repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive

# Using git filter-repo
git filter-repo --invert-paths --path config/secrets.yml
  1. Force push the cleaned history. All collaborators must re-clone the repository after history rewriting.
  2. Audit access logs. Check the provider's logs for unauthorized usage during the exposure window.
  3. Implement prevention. Add pre-commit hooks and CI/CD scanning to prevent recurrence. Move secrets to a proper secrets manager. See our guide on securing environment variables.

Building a Complete Secret Detection Strategy

No single tool catches everything. Build a layered defense:

  • Layer 1: IDE plugins that highlight secrets as you type (GitLens, detect-secrets VS Code extension)
  • Layer 2: Pre-commit hooks (detect-secrets, git-secrets) that block commits containing secrets
  • Layer 3: CI/CD pipeline scanning (Gitleaks GitHub Action) that catches secrets that bypass pre-commit hooks
  • Layer 4: GitHub secret scanning with push protection for known patterns
  • Layer 5: Regular full-history scans (TruffleHog) to catch secrets from before scanning was implemented
  • Layer 6: Web surface scanning (SecureBin Exposure Checker) to catch secrets exposed through web server misconfigurations

Frequently Asked Questions

Does making a repository private remove the risk of exposed secrets?

No. Private repositories reduce the attack surface but do not eliminate it. Anyone with read access to the repository (employees, contractors, CI/CD systems) can see the secrets. If a private repository is accidentally made public even briefly, all secrets in its history are exposed. Additionally, GitHub Advanced Security is required for secret scanning on private repos. Treat private repositories as "less exposed" not "secure."

How do I handle secrets that were committed months ago?

First, revoke and rotate the secret. Then use TruffleHog to scan the full git history and identify all exposed secrets. Use BFG Repo-Cleaner to remove them from history. Even if a secret has been in the repository for months without incident, it should still be rotated because you cannot know whether it was accessed by unauthorized parties. Finally, implement pre-commit hooks and CI/CD scanning to prevent future leaks.

Which tool should I start with?

Start with Gitleaks for CI/CD integration because it is fast, easy to configure, and has excellent GitHub Actions support. Add detect-secrets as a pre-commit hook for local development. Use TruffleHog for periodic full-history scans of your organization. For web-facing secrets (exposed .env files, config files), run the SecureBin Exposure Checker weekly. This combination covers the most common secret exposure vectors.

Secrets Leak Through More Than Git

Exposed .env files, backup files, and debug endpoints on your web server can leak credentials too. Check your domain with SecureBin Exposure Checker.

Scan Your Domain Free

The Bottom Line

Secret detection is not optional. With 12.8 million secrets leaked annually on GitHub alone, the question is not whether your organization will commit a secret, but when. The combination of pre-commit hooks, CI/CD scanning, and regular full-history audits creates a safety net that catches secrets before they become breaches. Start with one tool today and build your detection layers over time.

Related reading: How to Check if API Key is Exposed, How Hackers Find Exposed API Keys, Secure Environment Variables in Production, How to Secure API Keys in Code.