Introduction

Accidentally committing API keys, tokens, or secrets to a public GitHub repository is one of the most common security incidents. Bots scan public repositories within seconds of commit, and leaked credentials can be used for unauthorized access, data theft, resource abuse (crypto mining on your cloud account), and financial fraud. Simply deleting the file in a new commit is not sufficient because the secret remains in the repository's git history.

Symptoms

  • API key or token found in a public repository commit
  • GitHub secret scanning alert or third-party tool (git-secrets, truffleHog) detection
  • Unusual API usage or billing spike after the secret was exposed
  • Cloud provider alert for unauthorized resource creation
  • Bot activity detected using the leaked API key

Common Causes

  • Hardcoded API key in source code committed to version control
  • .env or config file with secrets not added to .gitignore
  • Copy-paste of configuration containing secrets
  • Automated commit script including environment variables with secrets
  • Forked repository containing secrets from the original repo

Step-by-Step Fix

  1. 1.Immediately revoke the leaked API key:
  2. 2.```bash
  3. 3.# AWS
  4. 4.aws iam delete-access-key --access-key-id AKIAIOSFODNN7EXAMPLE --user-name myuser

# Stripe curl -X POST https://api.stripe.com/v1/keys/keys/sk_live_XXXX/roll \ -u sk_live_YYYY:

# GitHub token curl -X DELETE -H "Authorization: token ghp_XXXX" \ https://api.github.com/applications/CLIENT_ID/grants/TOKEN

# Google Cloud API key # Disable in Google Cloud Console > APIs & Services > Credentials ```

  1. 1.Assess what the leaked key could access:
  2. 2.```bash
  3. 3.# For AWS keys, check what was done with them
  4. 4.aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAIOSFODNN7EXAMPLE

# Check billing and resource usage aws ce get-cost-and-usage --time-period Start=2026-04-01,End=2026-04-09 --granularity DAILY ```

  1. 1.Remove the secret from git history:
  2. 2.```bash
  3. 3.# Use git-filter-repo (recommended over BFG)
  4. 4.pip install git-filter-repo
  5. 5.git filter-repo --replace-text <(echo "AKIAIOSFODNN7EXAMPLE==>")

# Or use BFG Repo-Cleaner java -jar bfg.jar --replace-text secrets.txt my-repo.git cd my-repo.git git reflog expire --expire=now --all git gc --prune=now --aggressive ```

  1. 1.Force push the cleaned repository:
  2. 2.```bash
  3. 3.git push origin --force --all
  4. 4.git push origin --force --tags
  5. 5.# Note: All collaborators must re-clone the repository
  6. 6.`
  7. 7.Scan all repositories for other leaked secrets:
  8. 8.```bash
  9. 9.# Install and run gitleaks
  10. 10.gitleaks detect --source=/path/to/repo -v

# Or use truffleHog trufflehog --regex --entropy=False /path/to/repo

# Scan entire GitHub organization gitleaks detect --source=https://github.com/myorg -v ```

  1. 1.Implement pre-commit hooks to prevent future leaks:
  2. 2.```bash
  3. 3.# Install detect-secrets pre-commit hook
  4. 4.pip install detect-secrets
  5. 5.detect-secrets scan > .secrets.baseline

# Or use gitleaks as a pre-commit hook # .pre-commit-config.yaml # repos: # - repo: https://github.com/gitleaks/gitleaks # rev: v8.18.0 # hooks: # - id: gitleaks ```

Prevention

  • Use environment variables or secret management systems (Vault, AWS Secrets Manager) instead of hardcoded keys
  • Add .env, *.key, *.pem, config.json to .gitignore
  • Implement pre-commit hooks with gitleaks or detect-secrets
  • Use GitHub secret scanning and push protection
  • Rotate API keys on a regular schedule
  • Use short-lived credentials (IAM roles, OIDC) instead of long-lived API keys where possible