Is Your API Key Already Public? How to Stop Secret Leaks
How API keys leak through git, CI logs, bundles and AI agents, and how to stop it with gitleaks, push protection, OIDC and a tested incident playbook.

Most leaked API keys are not stolen by hackers. They are published by developers, one ordinary commit at a time.
A forgotten .env file, a debug print, a key pasted into an AI chat, or a token baked into a frontend bundle is all it takes.
The scale is real: GitGuardian's State of Secrets Sprawl 2026 report counted 28.65 million new hardcoded secrets in public GitHub commits in 2025, a 34% jump year over year.
The same report found that more than 64% of valid secrets it detected in 2022 were still valid when retested in January 2026.
In this guide, you'll learn how to:
Spot the six most common ways keys escape
Catch secrets before they land with gitleaks and GitHub push protection
Set up a pre-commit hook in under ten minutes
Replace long-lived keys with a secret manager and OIDC short-lived credentials
Run a calm, ordered playbook when a key does leak
Let's start with the threat itself.
Quick Answer
Threat in one line: any credential that touches a file, log, bundle, or chat can be copied, and git remembers it forever.
Fix in one line: block secrets at commit and push time, keep them out of code entirely, and when one leaks, revoke it first and clean up second.
The defence layers look like this:
Developer laptop → pre-commit hook (gitleaks)
↓
git push → GitHub push protection
↓
Repository / CI → secret scanning + CI scan
↓
Runtime → secret manager + short-lived OIDC credentials
↓
Leak happens → revoke → rotate → audit → purge history
How Secret Leaks Actually Happen
Leaks rarely look dramatic.
They look like normal work.
1. Git history
Deleting a key in a new commit does not remove it.
The old commit still contains it, and anyone who clones the repository gets the full history.
2. Committed .env files
A missing .gitignore entry plus git add . is the classic leak.
GitHub's own guidance on removing sensitive data recommends avoiding catch-all commands like git add . and reviewing staged changes with git diff --cached.
3. CI logs
Build steps that echo environment variables, run with verbose flags, or print failed HTTP requests can write a token straight into a log that many people can read.
Masking helps, but GitHub's secure use reference for Actions warns that redaction relies on exact matches, so structured values like JSON or YAML blobs can slip through.
4. Client bundles
Anything shipped to the browser is public.
Build tools make this explicit: Vite only exposes variables prefixed with VITE_ to client code, precisely because those values end up in the bundle.
A secret key behind a VITE_ or NEXT_PUBLIC_ prefix is a published key.
5. AI agent context
Coding agents read your files, terminals, and config.
If a key sits in a prompt, an MCP config, or an agent-generated commit, it can travel further than you expect.
The GitGuardian report found commits co-authored by Claude Code leaked secrets at about 3.2%, versus a 1.5% baseline, and counted 24,008 unique secrets in MCP-related configuration files.
We saw a related agent privacy slip recently in Is Claude Code Handing Your Email to Every Site It Visits?.
6. Breaches at hosting platforms
Sometimes you do everything right and the platform storing your environment variables gets breached.
That is exactly what happened in Northflank Breach Exposes AI Keys: Have You Rotated Your Secrets Yet? and Trigger.dev Breach Exposes Env Vars: Are Your Secrets Already Out?.
Long-lived keys turn a vendor breach into your breach.
Who Is at Risk?
Short answer: every team that ships code.
The highest-risk setups are:
Solo developers and side projects pushing to public repos
Startups with shared
.envfiles passed around in chatTeams using AI coding agents with broad file and terminal access
CI pipelines that store cloud keys as long-lived repository secrets
Frontend apps calling paid APIs (LLMs, maps, payments) directly from the browser
Private repositories are not a safe place either.
GitGuardian found internal repositories roughly six times more likely than public ones to contain hardcoded secrets.
How to Detect Leaked Secrets
Detection works best in layers: on your laptop, at push time, and across history.
Gitleaks
Gitleaks is an open-source scanner for passwords, API keys, and tokens in git repos, files, and stdin.
Install it on macOS or Linux with Homebrew:
brew install gitleaks
Scan the full history of the current repository:
gitleaks git -v
Scan a folder that is not a git repo (or your working files):
gitleaks dir -v .
Note: since v8.19.0, the older detect and protect commands are deprecated in favour of git, dir, and stdin.
GitHub secret scanning and push protection
GitHub push protection blocks pushes that contain supported secrets before they reach the repository.
Two flavours exist:
Push protection for users is on by default on GitHub.com and stops you pushing secrets to public repositories.
Push protection for repositories must be enabled by an admin, requires GitHub Secret Protection, and records bypasses as alerts.
Bypasses are allowed with a reason, so treat a bypass alert as a real event, not noise.
TruffleHog
TruffleHog is useful for checking whether a found credential is still live.
Scan a local repo and show only verified secrets:
trufflehog git file://. --results=verified
A verified result means the key still works, which moves it to the top of your incident list.

How a leaked key gets stopped before GitHub
How to Prevent Secret Leaks
Detection catches mistakes.
Prevention removes the reason to make them.
1. Ignore secret files from day one
Add .env, *.pem, and local credential files to .gitignore before the first commit, and commit an .env.example with fake values instead.
2. Stage deliberately
Use git add <file> or git add --interactive, and check git diff --cached before every commit.
3. Run a scanner on every commit
A pre-commit hook makes scanning automatic (walkthrough below).
4. Turn on push protection
Enable it at the repository or organization level so the server is your second net.
5. Keep secrets out of the browser
Route paid API calls through your backend or an edge function, and expose only publishable keys to the client.
6. Move secrets into a secret manager
The OWASP Secrets Management Cheat Sheet recommends centralising secrets, automating rotation, and keeping access auditable.
Options include AWS Secrets Manager, Azure Key Vault, Google Secret Manager, HashiCorp Vault, and Doppler or Infisical for smaller teams.
7. Prefer short-lived credentials
The best secret is one that expires before anyone can misuse it.
GitHub Actions OIDC lets a workflow exchange a signed identity token for a cloud access token valid only for that job, so no cloud key is stored in GitHub at all.
A minimal AWS deploy job looks like this:
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: aws-actions/configure-aws-credentials@v6.3.0
with:
role-to-assume: arn:aws:iam::123456789012:role/github-deploy
aws-region: ap-south-1
- run: aws sts get-caller-identity
The role's trust policy decides which repo, branch, or environment may assume it, as described in the configure-aws-credentials README.
Hands-On Setup: Gitleaks Pre-Commit Hook
This takes about ten minutes and protects every future commit.
1. Install pre-commit
Install the pre-commit framework:
pip install pre-commit
2. Add the config file
Create:
.pre-commit-config.yaml
Add the gitleaks hook from the official README:
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaks
v8.30.1 was the latest gitleaks release when this guide was written.
3. Update to the latest version
Bump the pinned rev automatically:
pre-commit autoupdate
4. Install the git hook
Wire it into .git/hooks:
pre-commit install
5. Scan what already exists
Run every hook against all files once:
pre-commit run --all-files
6. Test it
Commit a file containing a fake token and you should see:
Detect hardcoded secrets.................................................Failed
The commit is stopped before it exists.
7. Handle false positives properly
For a known test fixture, add a gitleaks:allow comment on that line.
For repos with old findings, create a baseline once and scan against it:
gitleaks git --report-path gitleaks-report.json
Avoid SKIP=gitleaks git commit as a habit; it disables the check entirely for that commit.
8. Add the CI safety net
Hooks live on laptops and can be skipped, so also scan in CI with the official Gitleaks GitHub Action:
name: gitleaks
on: [pull_request, push, workflow_dispatch]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Organization accounts also need a GITLEAKS_LICENSE secret, per the action's README.
Incident Response Playbook: When a Key Leaks
Speed matters more than elegance.
Work in this order.
1. Revoke or rotate the key immediately
GitHub's guidance is explicit: if the sensitive data is a credential, revoking or rotating it is the first step, and that may be enough on its own.
Deleting the commit first only buys attackers time.
2. Deploy the replacement
Issue a new key with the narrowest scope possible, store it in your secret manager, and redeploy.
3. Audit usage
Check the provider's logs, billing dashboard, and access history for activity between the leak time and the revocation time.
For cloud keys, look for new users, new access keys, unusual regions, and spikes in compute or LLM spend.
4. Decide whether to purge history
If the repo is public, or the data is more than a revocable key, rewrite history with git-filter-repo.
Remove a file from every branch and tag:
git-filter-repo --sensitive-data-removal --invert-paths --path config/.env
Or replace leaked strings listed in a local file (one per line, replaced with ***REMOVED*** by default):
git-filter-repo --sensitive-data-removal --replace-text ../passwords.txt
The --sensitive-data-removal flag needs git-filter-repo 2.47 or newer.
5. Force-push and clean up copies
Push the rewritten history:
git push --force --mirror origin
Then ask collaborators to re-clone, coordinate with fork owners, and contact GitHub Support to remove cached views and pull request references.
6. Prevent the repeat
Add the missing .gitignore rule, install the pre-commit hook, enable push protection, and write a two-line post-mortem.

Leaked key playbook: contain, investigate, clean up
Common Mistakes
Mistake 1: Purging history before revoking
A rewrite takes time and coordination, while a live key can be abused within minutes of being pushed.
Mistake 2: Assuming a private repo is safe
Private repos get cloned to laptops, CI runners, and AI tools, and they become public by accident.
Mistake 3: Trusting log masking
Redaction relies on exact matches, so encoded or reformatted values can still appear in logs.
Mistake 4: Hardcoding "temporary" keys
Temporary keys become permanent, and once a key ships inside an app binary or bundle, anyone can extract it.
Mistake 5: One key for everything
A single all-powerful key turns any leak into a full compromise; scope keys per service and environment.
Security Checklist
Before your next release, confirm:
.envand key files are in.gitignore, with an.env.examplecommittedgitleaks pre-commit hook installed for every contributor
Gitleaks or secret scanning running in CI with full history
Push protection enabled on all repositories
No secret keys behind
VITE_orNEXT_PUBLIC_prefixesCI deploys use OIDC instead of stored cloud keys
Secrets live in a secret manager with rotation
A written leak playbook with owners and provider revoke links
Get Security Alerts in Your Inbox
New breaches, leaked-key incidents, and hands-on fixes land every week.
Subscribe to the free TheTechLane newsletter and get them before they hit your stack.
FAQ
Is deleting the commit enough after leaking a key?
No. The key is still in history, forks, clones, and possibly in scraper caches. Revoke it first, then decide whether to rewrite history.
Does GitHub push protection replace a pre-commit hook?
Not fully. Push protection catches secrets at push time on GitHub, while a local hook stops them before a commit exists and works with any remote.
Should I use gitleaks or TruffleHog?
Many teams use both: gitleaks for fast pre-commit and CI blocking, TruffleHog to verify whether a found credential is still live.
Are environment variables secure enough?
They beat hardcoding, but they are still long-lived and readable by anything in the process or platform. Combine them with a secret manager and short-lived credentials.
What about keys in AI coding tools?
Keep keys out of prompts and agent-readable config, use per-tool scoped keys, and run the same scanners on agent-generated commits.
Key Takeaways
Remember these points:
Most leaks come from ordinary workflows: git history,
.envfiles, logs, bundles, and AI contextA pre-commit gitleaks hook plus GitHub push protection catches most mistakes before they spread
Secret managers and OIDC short-lived credentials shrink what a leak can do
When a key leaks: revoke, rotate, audit, then purge history
A leaked key is an access problem first and a git problem second.
Related Reading on TheTechLane
Northflank Breach Exposes AI Keys: Have You Rotated Your Secrets Yet?: what a platform env-var breach means for your keys.
Trigger.dev Breach Exposes Env Vars: Are Your Secrets Already Out?: a rotation checklist from a real incident.
Is WordPress 7.2 Finally Ending Plain-Text API Keys in Plugins?: how platforms are moving keys out of plain text.
Sources
Gitleaks README, GitHub
Gitleaks GitHub Action, GitHub
About push protection, GitHub Docs
Removing sensitive data from a repository, GitHub Docs
Secure use reference for GitHub Actions, GitHub Docs
OpenID Connect in GitHub Actions, GitHub Docs
pre-commit, pre-commit.com
git-filter-repo, GitHub
TruffleHog README, Truffle Security
Env variables and modes, Vite
The State of Secrets Sprawl 2026, GitGuardian
Follow TheTechLane
Keep learning AI, development, and modern developer technologies with TheTechLane.
Learn • Build • Share
Follow @thetechlanehq for more developer guides, tutorials, and practical technology content.