Secrets Management

API Key Leaked on GitHub: Immediate Steps and Prevention

Accidentally pushed an API key to GitHub? Learn what to do immediately, how to prevent future leaks, and what tools can automatically scan your repos for secrets.

January 27, 20265 min readShipSafer Team

It happens to almost every developer at least once: you accidentally commit an API key, database password, or private token to a public GitHub repository. Within minutes, automated bots are scanning GitHub for exactly this — and they will find it.

This guide walks through what to do immediately, how to prevent future leaks, and what tools to put in place so it never happens again.

Why This Is Urgent

Automated scanners continuously monitor GitHub's public event stream. Projects like truffleHog, GitGuardian, and even AWS itself monitor for leaked credentials. The window between a push and a credential being compromised can be measured in minutes.

In one well-documented incident, a developer committed an AWS key to GitHub and received an email from AWS about suspicious charges for EC2 instances in multiple regions within 4 minutes of the push.

Immediate Response: What to Do Right Now

Step 1: Revoke the key immediately

Before anything else, revoke or rotate the compromised credential:

  • AWS: Go to IAM → Users → Security Credentials → Deactivate the access key
  • Stripe: Dashboard → Developers → API Keys → Roll key
  • SendGrid: Settings → API Keys → Delete
  • GitHub PAT: Settings → Developer Settings → Personal Access Tokens → Revoke
  • Google Cloud: Console → IAM → Service Accounts → Delete the key

Do not remove the commit first. Removing it from GitHub does not remove it from history, and it doesn't prevent automated scanners that already found it from using it. Revoke first.

Step 2: Check for unauthorized usage

After revoking, audit what was done with the key:

  • AWS CloudTrail logs for suspicious API calls
  • Your service's audit log for unusual access patterns
  • Check for new resources (EC2 instances, S3 buckets, database users) you didn't create

Step 3: Remove from Git history

Even after revoking, removing the secret from history is good practice to prevent confusion. Use git-filter-repo (the modern replacement for git filter-branch):

pip install git-filter-repo

# Remove a file containing the secret from all history
git filter-repo --path path/to/secrets-file.env --invert-paths

# Or replace the specific string everywhere in history
git filter-repo --replace-text <(echo 'sk_live_abc123==>REVOKED_KEY')

Then force-push all branches:

git push --force --all
git push --force --tags

Note: GitHub caches repository data and it may take time to propagate. Contact GitHub support if the commit still appears in search results.

How Secrets Get into Repositories

Understanding the failure modes helps prevent them:

  1. Hardcoded in source filesconst API_KEY = "sk_live_..." directly in code
  2. Committed .env files.env not in .gitignore
  3. Configuration filesconfig.json, settings.py, application.properties
  4. Test files — Secrets in test fixtures, mocks, or seed data
  5. Shell history.bash_history or .zsh_history accidentally committed
  6. IDE config files — Some editors store project settings with credentials
  7. Docker images — Build args baked into layers

Prevention: Environment Variables

The correct pattern is to never put secrets in source files. Use environment variables:

// ❌ Wrong
const stripe = new Stripe('sk_live_abc123');

// ✅ Correct
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

For local development, use a .env file — but always add it to .gitignore:

# .gitignore
.env
.env.local
.env.*.local
*.env

For production, use your platform's secrets management:

  • Vercel: Environment Variables in project settings
  • AWS: Secrets Manager or Parameter Store
  • GitHub Actions: Repository Secrets
  • Kubernetes: Secrets or external secret operators (External Secrets Operator)

Prevention: Pre-commit Hooks with gitleaks

Install gitleaks to scan every commit before it's pushed:

# Install gitleaks
brew install gitleaks  # macOS
# or download binary from GitHub releases

# Scan the current repo for any historical leaks
gitleaks detect --source . --verbose

# Install as a pre-commit hook
gitleaks protect --staged  # scan staged files before commit

Using the pre-commit framework:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

GitHub's Built-in Secret Scanning

GitHub automatically scans public repositories for secrets from 100+ service providers (AWS, Stripe, GitHub tokens, Twilio, etc.) and notifies the service provider when a match is found.

For private repositories, Secret Scanning is available on GitHub Advanced Security. You can also enable Push Protection, which blocks pushes that contain detected secrets before they reach the repository.

To check if secret scanning is enabled:

  1. Go to your repository → Settings → Security & Analysis
  2. Enable "Secret scanning" and "Push protection"

Scanning Your Entire Org History

If you're doing a retrospective audit:

# Scan all branches of a repo
gitleaks detect --source . --verbose --log-opts="--all"

# With truffleHog (also checks for high-entropy strings)
trufflehog git file://. --only-verified

# Scan a GitHub org (requires GitHub token)
trufflehog github --org=your-org --only-verified

Building a Secrets Management Policy

Beyond tooling, establish a team policy:

  1. No secrets in code, ever — use environment variables or secret stores
  2. Rotate keys regularly — at least annually, or immediately on team member offboarding
  3. Use short-lived credentials — IAM roles with temporary credentials instead of long-lived keys
  4. Principle of least privilege — each API key should only have the permissions it needs
  5. Audit regularly — scan your repos quarterly even if you have pre-commit hooks

The fundamental rule: treat secrets like passwords. You wouldn't commit a password to source control. Apply the same standard to every API key, token, and credential.

api-keys
github
secrets
security
devops

Check Your Security Score — Free

See exactly how your domain scores on DMARC, TLS, HTTP headers, and 25+ other automated security checks in under 60 seconds.