← All articles

API Key Rotation: A Practical Checklist for When You Suspect a Secret Has Been Exposed

June 9, 2026

When "Maybe It's Fine" Is the Most Dangerous Thought in Security

You're reviewing a pull request and notice a Stripe secret key committed three days ago. Or a teammate mentions they accidentally pushed a .env file to a public fork. Or a monitoring alert fires on an unusual spike in API usage at 3 a.m.

The instinct — especially under pressure — is to quietly fix the code, remove the secret, and hope nobody noticed. That instinct is wrong, and it's exactly how small leaks turn into large breaches.

This checklist is designed to walk you through a fast, systematic response when a credential is suspected or confirmed exposed. Work through it in order; don't skip steps to save time.

Step 1: Assume Compromise Immediately

The moment you have evidence a secret may have been exposed — even briefly, even in a private repo — treat it as compromised. Attackers use automated scanners that continuously harvest GitHub, GitLab, and npm for leaked credentials. A secret visible for five minutes can be collected and tested within seconds of the push.

Do not wait for proof of misuse before revoking. Revoke first, investigate second.

Step 2: Identify the Full Blast Radius

Before touching anything, answer these questions:

  • What service does this key access? (e.g., AWS, Stripe, Twilio, a third-party data API)
  • What permissions does it carry? Read-only? Write? Admin-level? Billing?
  • Where else is this key used? CI/CD pipelines, other repos, staging environments, a teammate's local machine?
  • How long has it been exposed? Check git history with git log --all --full-history -- path/to/file to find the exact commit.
  • Was the repo public at any point? Even a brief window of public visibility is enough.

Mapping the blast radius before you rotate prevents you from revoking a key and discovering five dependent services are now broken with no replacement ready.

Step 3: Generate the Replacement First

Create the new credential before revoking the old one. This minimizes downtime and ensures you have a working replacement ready to deploy atomically. In most platforms:

  1. Log in to the provider's dashboard (AWS IAM, Stripe Dashboard, Twilio Console, etc.).
  2. Generate a new key or token with the minimum required permissions — this is a good forcing function to right-size access you may have over-provisioned previously.
  3. Store the new secret immediately in your secrets manager (AWS Secrets Manager, HashiCorp Vault, 1Password Secrets Automation, etc.) — never in a file, chat message, or email.

Step 4: Rotate and Revoke

With the replacement staged, revoke the exposed credential:

  • AWS: Go to IAM → Users → Security credentials → Deactivate or delete the access key. Then delete it entirely — deactivated keys can be reactivated.
  • Stripe: API keys → Roll key. Stripe supports a grace period where both keys work briefly, which is useful for zero-downtime rotation.
  • GitHub Personal Access Tokens: Settings → Developer settings → Personal access tokens → Revoke.
  • Generic pattern: Most providers have a "Revoke" or "Delete" button in their API/credentials section. When in doubt, delete rather than deactivate.

After revoking, deploy the new secret to every service that depended on the old one and verify each one resumes normal operation.

Step 5: Audit Access Logs for the Exposure Window

Now that you've stopped the bleeding, look at what happened during the exposure window. This step is uncomfortable but non-negotiable.

  • AWS: CloudTrail logs — filter by the access key ID for the exposure period. Look for AssumeRole, CreateUser, PutBucketPolicy, or any write/admin actions you didn't initiate.
  • Stripe: Dashboard → Logs — filter by API key. Look for unusual charge volumes, new webhook endpoints, or payout changes.
  • GitHub token: Check for unexpected repository forks, webhooks, OAuth app authorizations, or collaborator changes.
  • Generic: Any provider worth using has an audit log. Export it, filter by time window, and look for actions that don't match your application's normal behavior.

If you find suspicious activity — especially any resource creation or privilege escalation — escalate to a full incident response process. You're no longer in "rotation mode," you're in "breach mode."

Step 6: Purge the Secret from Version Control History

Removing a file or reverting a commit does not remove the secret from git history. Anyone who cloned the repo before the revert still has it. You need to rewrite history.

# Using git-filter-repo (recommended over filter-branch)
pip install git-filter-repo
git filter-repo --path path/to/secret/file --invert-paths

# Or redact a specific string across all history
git filter-repo --replace-text replacements.txt

After rewriting, force-push to all remotes and notify collaborators to re-clone. Also check whether the secret appears in any GitHub/GitLab issue comments, PR descriptions, or CI/CD logs — these are separate from git history and need to be manually redacted.

Practically speaking: because history rewriting is disruptive and incomplete (forks, CI caches), you should treat the secret as permanently compromised regardless. Revocation is the real protection; history cleanup is hygiene.

Step 7: Prevent Recurrence with Pre-Commit Controls

Rotation is reactive. The goal is to never need it. Add at least one of these preventive controls:

  • Pre-commit hooks: Tools like Gitleaks or TruffleHog run locally before a commit lands and block secrets from ever reaching the remote.
  • CI/CD scanning: Run a secret scanner on every PR. Fail the build if a new secret pattern is detected.
  • Repo-wide historical scanning: Run a full scan across your entire codebase and git history to catch secrets that pre-date your new controls. This is often where the real surprises live.
  • Environment variable enforcement: Lint your codebase for hardcoded strings matching common secret patterns (high-entropy strings, known prefixes like sk_live_, AKIA, ghp_).

If you want a fast baseline picture of what's already exposed across your repos, run a free GhostCred scan — it checks for exposed API keys, tokens, and IAM misconfigurations in about 60 seconds, with findings mapped to SOC 2 and HIPAA controls so you know what actually needs remediation.

The Rotation Mindset: Make It Boring

The teams that handle credential exposure best are the ones who've made rotation a routine operation rather than a crisis. That means:

  • Short-lived credentials wherever the platform supports them (AWS STS temporary tokens, OIDC-based CI authentication).
  • Documented runbooks for each credential type so any engineer can rotate without tribal knowledge.
  • Regular scheduled rotation even without a suspected leak — quarterly at minimum for long-lived keys.
  • Alerting on credential usage anomalies, not just on the leak itself.

A leaked secret doesn't have to become a breach. The difference is almost always speed and process — knowing exactly what to do in the first fifteen minutes while an attacker is still probing what they've found.

See what's exposed in your own code.

Run a free scan