Blog
3 min read

GitHub Secret Scanning and Push Protection: Stop Leaking API Keys

Secret scanning finds API keys, tokens and passwords committed to your repository; push protection blocks them before they're pushed. How both work on GitHub, what to do when one fires, why deleting the commit isn't enough, and local tools like gitleaks and pre-commit hooks.

Committing an API key to Git is one of the most common — and most expensive — mistakes in software. Bots scan public GitHub repositories continuously, and leaked cloud and AI keys are typically abused within minutes. Secret scanning is GitHub's defence against this.

Two features

Secret scanning

GitHub scans your repository's contents and history for patterns that look like secrets — AWS keys, Stripe keys, OpenAI and Anthropic API keys, GitHub tokens, database URLs and hundreds more — and raises an alert in the Security tab.

For many providers, GitHub also notifies the provider directly when a key appears in a public repository, and some (like GitHub's own tokens) revoke it automatically.

Push protection

Push protection checks your commits when you push and blocks the push if it contains a supported secret:

remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: - Push cannot contain secrets
remote:   —— Stripe API Key ——————————————————
remote:     locations:
remote:       - commit: 8a3f2c1  path: src/config.ts:4

This is the more valuable of the two — it stops the leak before it happens. It's on by default for public repositories; turn it on for private ones in Settings → Code security (availability for private repos depends on your plan).

When push protection blocks you

Don't bypass it. Remove the secret properly:

  1. Move the secret out of the code into an environment variable. (Environment variables explained)

  2. Remove it from the commit(s). If it's in the latest commit:

    # edit the file to remove the secret, then
    git add src/config.ts
    git commit --amend
    

    If it's in an earlier unpushed commit, use interactive rebase or reset and recommit. (git reset vs revert)

  3. Rotate the key anyway if there's any chance it was exposed elsewhere.

  4. Push again.

Only use "allow the secret" for genuine false positives, such as test fixtures that aren't real keys.

When an alert fires on something already pushed

Rotating the secret is the fix. Deleting it from Git is not.

Once pushed — especially to a public repo — assume it's been copied. Even if you rewrite history, it may exist in forks, clones, caches and the scanners' records.

  1. Revoke/rotate the key with the provider immediately.
  2. Check the provider's logs for unexpected use (and your bill).
  3. Update the new key in your environment.
  4. Then, optionally, clean history.

(I leaked an API key. What now?)

Catch secrets before they reach GitHub

Add a local check so secrets never leave your machine:

  • gitleaks or trufflehog — scan your repo and history.

    gitleaks detect
    
  • A pre-commit hook that runs a scanner on every commit.

  • .gitignore for .env and similar files from day one. (.gitignore explained)

  • .env.example with placeholder values, so others know which variables to set.

Why AI-built apps leak keys more often

AI tools sometimes paste keys straight into code to "make it work", especially in front-end files. And front-end variables (VITE_, NEXT_PUBLIC_) end up public in the browser even if they never touch Git. (Keep API keys out of an AI-built app)

Tell your AI tool explicitly: secrets come from environment variables, and secret keys never go in front-end code. Put that rule in your project instructions. (How to write a CLAUDE.md)


EasySpawn keeps your app's secrets as server-side environment variables, out of your repository and out of the browser — and Claude Code follows that rule when it writes code. See how it works or join the waitlist.

Related: I Leaked an API Key. What Now? · How to Keep API Keys Out of an AI-Built App · Secrets Management Beyond .env Files · GitHub Actions Secrets

Keep reading