You Leaked an API Key—Now What? Emergency Response Guide

Written by the Rafter Team

You pushed a commit. Maybe it was a .env file that wasn't in .gitignore. Maybe a hardcoded Stripe key in a config file. Maybe an OpenAI key pasted into a Jupyter notebook you shared publicly. However it happened, a secret is now exposed—and automated scanners are already looking for it.
Honeypot research from Truffle Security and GitGuardian consistently shows that leaked credentials on public GitHub repositories are tested by automated bots within 1-5 minutes of exposure. A 2023 experiment by Truffle Security demonstrated that even credentials in deleted repositories remain accessible through dangling commits.
This is not a "fix it this weekend" situation. This is a "stop what you're doing right now" situation.
If you're reading this because you just leaked a key: skip to the Emergency Checklist below. Revoke first, read later. Every minute the credential remains active is a minute an attacker can use it.
Emergency Checklist: The First 15 Minutes
Time matters more than thoroughness in the first response. Follow this sequence:
Minute 0-2: Revoke the Credential
Go to the provider's dashboard and revoke or deactivate the leaked key immediately. Don't assess impact first—revoke first.
| Provider | Where to Revoke |
|---|---|
| Stripe | Dashboard → Developers → API Keys → Roll key |
| OpenAI | platform.openai.com → API Keys → Delete key |
| AWS | IAM Console → Users → Security Credentials → Deactivate |
| GitHub | Settings → Developer settings → Personal access tokens → Delete |
| Google Cloud | Console → APIs & Services → Credentials → Delete key |
| Supabase | Project Settings → API → Regenerate keys |
| Anthropic | console.anthropic.com → API Keys → Revoke |
| Twilio | Console → Account → API Keys → Delete |
If the credential is for a service not listed here, search "[provider name] revoke API key" and act immediately. Provider-specific revocation processes vary, but the principle is universal: kill the credential before investigating. For a broader overview of credential types and the full security lifecycle, see Secrets and Credential Security: The Complete Developer Guide.
Minute 2-5: Generate a New Credential
Create a replacement credential with the minimum required permissions. Apply these improvements over the old key:
- Scope it down. If the old key had admin access, the new one should have only the permissions your application actually uses
- Set an expiration. If the provider supports it, set a TTL (30-90 days)
- Use a different naming convention. Name keys by purpose (
prod-payment-processor, notmy-key-2)
Minute 5-10: Deploy the New Credential
Update every system that used the old credential:
# Update your secret manager or environment
export STRIPE_SECRET_KEY=sk_live_new_key_here
# Or update in your secrets manager
vault kv put secret/stripe api_key=sk_live_new_key_here
# Or update in Doppler
doppler secrets set STRIPE_SECRET_KEY=sk_live_new_key_here
If you're using a secret manager (Vault, Doppler, AWS Secrets Manager), the update propagates automatically. If you're using environment variables or .env files, you'll need to redeploy every service that references the old key.
Minute 10-15: Verify the Old Key Is Dead
Confirm that the revoked credential no longer works:
# Test that the old Stripe key is revoked
curl https://api.stripe.com/v1/charges \
-u sk_live_OLD_REVOKED_KEY: \
2>&1 | grep -i "invalid"
# Test that the old OpenAI key is revoked
curl https://api.openai.com/v1/models \
-H "Authorization: Bearer sk-OLD_REVOKED_KEY" \
2>&1 | grep -i "invalid"
If the old key still works, something went wrong with revocation. Go back to step 1.
After the Emergency: Investigation (Hour 1-24)
Once the immediate threat is contained, investigate what happened.
Audit Provider Logs
Every major provider logs API usage. Check for activity you didn't authorize:
Stripe:
- Dashboard → Logs → Filter by the leaked key
- Look for unfamiliar charge attempts, customer data exports, or refund operations
- Check the Events tab for webhook-related activity
OpenAI:
- platform.openai.com → Usage → Filter by date range of exposure
- Look for usage spikes, unfamiliar model calls, or high token consumption
- Check billing for unexpected charges
AWS:
- CloudTrail → Event History → Filter by access key ID
- Look for
CreateUser,AttachUserPolicy,RunInstances, orCreateBucketevents - Check for resource creation in unfamiliar regions—attackers often spin up crypto miners in every available region simultaneously
GitHub:
- Settings → Security log → Filter by token
- Look for repository clones, branch deletions, or permission changes
Determine Blast Radius
Answer these questions:
- What could the credential access? Map the permissions the leaked key had
- Was the key actually used by an attacker? Provider logs will show unauthorized requests
- Was data exfiltrated? Look for bulk read operations, exports, or unusual data transfer patterns
- Are downstream systems affected? If the leaked key accessed a database, were those records modified?
- How long was the key exposed? Check git history for when the secret was first committed
# Find when a secret was first committed to git history
git log --all --full-history -p | grep -n "sk_live_" | head -5
# Check if the secret exists in any branch
git branch -a --contains $(git log --all --oneline -S "sk_live_" | tail -1 | cut -d' ' -f1)
Remove from Git History
Deleting the file containing the secret doesn't remove it from git history. Use git filter-repo (recommended over the deprecated git filter-branch):
# Install git-filter-repo
pip install git-filter-repo
# Remove a specific file from all history
git filter-repo --path .env --invert-paths
# Force push the cleaned history
git push --force --all
Force-pushing rewritten history is destructive. Coordinate with your team before rewriting shared branches. Any forks created before the rewrite still contain the secret—the credential must be rotated regardless.
Even after rewriting history, consider the secret permanently compromised. GitHub caches commits, forks preserve history, and web archives may have captured the page. Rotation is non-negotiable.
Blast Radius by Key Type
Not all leaked keys are equally dangerous. Here's what attackers do with each type:
Stripe sk_live_ Keys
Immediate risk: Financial. Attackers can create charges, issue refunds to external accounts, export customer data (names, emails, payment method fingerprints), and modify webhook endpoints to intercept future events.
Time to exploit: Minutes. Stripe keys are high-value targets with well-known exploitation patterns.
Recovery: Roll the key in Stripe Dashboard → Developers → API Keys. Review all charges and refunds for the exposure window. Check webhook endpoint configurations for unauthorized changes. For details, see Stripe API Keys: Test vs Live and Secure Use.
OpenAI sk-proj- Keys
Immediate risk: Financial + data. Attackers consume your token quota (often thousands of dollars in hours), access fine-tuned models, and may retrieve training data or file uploads associated with your account.
Time to exploit: Minutes. Automated scanners specifically target OpenAI key patterns.
Recovery: Delete the key at platform.openai.com, set billing hard limits to prevent runaway charges, and review usage logs for the exposure period. See OpenAI API Key Exposure: Risks and Recovery for the full playbook.
AWS Access Keys (AKIA...)
Immediate risk: Infrastructure. With sufficient permissions, attackers can launch EC2 instances for crypto mining, access S3 data, create new IAM users with backdoor access, and modify security groups.
Time to exploit: Under 2 minutes. AWS keys are the most aggressively scanned credential type.
Recovery: Deactivate the key in IAM. Check CloudTrail for unauthorized actions—especially RunInstances in all regions, CreateUser, and PutBucketPolicy. AWS has a compromised key runbook in their documentation.
GitHub PATs
Immediate risk: Code and supply chain. Attackers clone private repositories, inject malicious code, modify CI/CD workflows (inserting backdoors into build pipelines), and access organization secrets.
Time to exploit: Hours (less aggressively scanned than cloud keys, but still automated).
Recovery: Delete the token in GitHub Settings. Audit the security log for the token's activity. Review recent commits and workflow changes across all repositories the token could access.
Why Deleting the Commit Isn't Enough
A common mistake: developers delete the file or the commit and assume the problem is solved. It's not.
Git preserves everything. Every commit—including deleted ones—exists in the repository's history until explicitly purged with tools like git filter-repo. Even after purging:
- Forks retain the original history. Anyone who forked your repo before the cleanup has the secret
- GitHub caches dangling commits. Research from Truffle Security demonstrated that commits from deleted forks and deleted repositories can still be accessed via their SHA hash on GitHub
- CI/CD logs may contain the secret. If the secret was used in a build step, it may appear in build logs
- Web archives and search engine caches may have indexed the page
The only safe assumption: once a secret has been pushed to a remote repository, it's compromised. Rotate it.
Prevention: Making This the Last Time
The best incident response is the one you never need. After recovering from a leak, implement these defenses:
1. Pre-Commit Hooks
Install a secret scanner that runs on every commit:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.0
hooks:
- id: gitleaks
pip install pre-commit
pre-commit install
This catches secrets before they enter git history—the cheapest point in the lifecycle to catch a leak. For the full setup guide, see Pre-Commit Hooks for Secret Detection.
2. CI/CD Scanning
Add secret scanning to your CI pipeline so leaked credentials block merges:
# .github/workflows/security.yml
- name: Run gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3. Secret Managers
Stop storing credentials in .env files and environment variables. Use a dedicated secret manager (Vault, Doppler, AWS Secrets Manager) that provides access control, audit logging, and automatic rotation. See Secrets and Credential Security: The Complete Developer Guide for a comparison of options.
4. Automated Rotation
Set rotation schedules so that even if a key leaks, the exposure window is bounded:
- High-value keys (payment, database, cloud IAM): Rotate monthly
- Standard API keys (third-party SaaS): Rotate quarterly
- Development keys: Rotate on team member offboarding
Incident Response Template
Use this template to document the incident for your team and for compliance:
## Incident Report: Credential Leak
**Date detected:** YYYY-MM-DD HH:MM UTC
**Credential type:** [Stripe sk_live / OpenAI / AWS / etc.]
**How it leaked:** [Committed to public repo / CI logs / shared in chat / etc.]
**Exposure duration:** [When committed] to [when revoked]
**Actions taken:**
1. Credential revoked at [time]
2. New credential generated and deployed at [time]
3. Provider logs audited — [findings]
4. Git history cleaned with git filter-repo
5. [Additional remediation]
**Blast radius:** [What the credential could access]
**Evidence of exploitation:** [Yes/No — details]
**Prevention measures added:** [Pre-commit hooks / CI scanning / etc.]
Conclusion
A leaked API key isn't a career-ending event. It's a recoverable incident—if you move fast. The response sequence is always the same: revoke, rotate, audit, remediate.
The gap between "leaked" and "exploited" is measured in minutes. The gap between "exploited" and "contained" depends entirely on how prepared you are.
Your action plan:
- Bookmark this page as your incident response reference
- Install gitleaks as a pre-commit hook today—before you need it
- Identify every credential your application uses and verify each one is stored in a secret manager, not in code
- Run a historical scan of your repositories to find secrets already in git history—tools like gitleaks and TruffleHog can sweep full commit history
- Write a one-page incident response runbook for your team
Rafter integrates credential scanning into broader code security workflows. If you want automated detection across your repositories, start a scan at rafter.so.
Related Resources
- Secrets and Credential Security: The Complete Developer Guide
- Secret Scanning in CI/CD: detect-secrets vs gitleaks vs TruffleHog
- Exposed API Keys: The Silent Killer of Projects
- API Keys Explained: Secure Usage for Developers
- Stripe API Keys: Test vs Live and Secure Use
- OpenAI API Key Exposure: Risks and Recovery
- GitHub Secret Scanning: What It Catches and What It Misses
- Pre-Commit Hooks for Secret Detection