Part of the AI coding agent security checklist
An AI agent saw my API key. What now?
Rotate it at the provider first. Cleaning the transcript, the logs and git comes second, and none of it brings the key back.
Checked against the provider documentation and the ranwhat source listed under Sources. Published .
Work out where the key went.
An agent that reads a key sends it to the model as part of the conversation, and Claude Code also writes it to disk. Those are two copies, and a third and fourth appear if the key was committed or printed in CI.
To find which transcripts hold it without installing anything, search for a name or the first characters of the value:
grep -rl 'STRIPE_SECRET_KEY' ~/.claude/projects
grep -rl 'sk_live_' ~/.claude/projects
git log --all -S'sk_live_' --oneline commits whose diff adds or removes itThis guide is written for Claude Code, whose files it describes. Other agents keep their own history, and the steps from section 02 on are the same. Reading the transcripts by hand is covered in Claude Code history, and how the file got read in the first place in Blocking .env reads.
Assume the key is known
You cannot prove who has read a copy you do not control, and a retention window is not a deletion you can check. Treat any value an agent has seen as exposed, and decide what to do about it by what the key can reach, not by how likely a leak seems.
Rotate before you clean.
A revoked key is worthless to everyone who holds a copy. Every other step in this guide only shrinks the number of copies.
GitHub's own guidance on leaked secrets says the same: revoke or rotate the secret first, and that alone may solve the problem. Cleaning first costs you time you may not have, and the key keeps working while you do it.
Replace, then revoke, unless it is already abused
Most providers let you create a second key while the first still works, so you can move your applications and switch the old one off without an outage. That is the right order when nothing looks wrong. If the key may already be in someone else's hands, skip the migration: revoke at once, accept the downtime, and put the new key in afterwards. A grace period that keeps the old key alive is also a grace period for whoever else has it.
Give the new key a safer path
Do not paste the replacement into the same chat, and do not leave it in a file the agent can read. Put it in your platform's secret store or an environment variable that is set outside the agent's session, and scope it as narrowly as the provider allows. The token scopes guide shows how to find out what a given token can do.
Revoke it at the provider.
The steps below come from each provider's current documentation. Menu names move, so if one has changed, the page under Sources will have the new one.
GitHub
AWS access keys
AWS recommends deactivating before deleting, so you can switch the key back on if something breaks. For a leaked key, do the first two now and the third once you have read the logs in section 04.
aws iam update-access-key --access-key-id OLD_KEY_ID --status Inactive --user-name NAME
aws iam create-access-key --user-name NAME the new key, active at once
aws iam delete-access-key --access-key-id OLD_KEY_ID --user-name NAMEIn the console: IAM, Users, the user, Security credentials, then under Access keys choose Actions and Deactivate. A user holds at most two keys. If the leaked value starts with ASIA it is a temporary credential that expires by itself, but its session can still act until it does, so look at what it did.
Google Cloud API keys
This covers API keys. A service account key file is a different credential with its own steps, which this guide does not cover.
Slack
Stripe
Dashboard, API keys, the key's overflow menu, Rotate key. The old key keeps working for up to 7 days unless you set Expiration to Now, which deletes it at once. For a leaked key choose Now. If you would rather have no replacement yet, Expire key stops the key and creates nothing. Use View request logs on the same menu before you rotate, so you can see what the key did.
OpenAI and Anthropic
Anything else
Use the issuing provider's own console and its own documentation. If you are not sure which provider a value belongs to, section 05 shows how ranwhat clean labels what it finds.
Check whether someone else used it.
Revoking stops the next request. It does not tell you about the ones before. Ask the provider for its record of the key, starting at the time the agent read it.
aws iam get-access-key-last-used --access-key-id OLD_KEY_ID aws cloudtrail lookup-events --region us-east-1 \ --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=OLD_KEY_ID
The last-used call reports the date, service and Region of the most recent request. It is a hint, not a full history, so read the CloudTrail events for the whole picture. If you find use you cannot explain, the problem is bigger than a key: look for what it created, such as new users, keys, roles, instances and webhooks, and remove those too.
Mask the key in the local transcripts.
With the key dead, remove the plaintext copy so an infostealer, a backup or the next agent does not find it.
ranwhat clean reads the transcripts for secrets and reports each distinct one with the project it was in and, when the transcript names it, the file it came from. A bare run changes nothing, and opens a review session where rotate lists what to rotate, grouped by provider.
When the list looks right, mask it. --apply masks everything it found without asking, and mask 3 in the review masks one finding. --days N widens the window past the default 30 days.
uvx ranwhat clean --apply mask what it found, backups first uvx ranwhat clean --apply --days 90 look back further
Masking is not remediation
ranwhat clean does not revoke the key. It does not touch what the model provider kept, your git history, a CI log or a clipboard. It only stops the transcript on this machine from leaking the value a second time. That is useful, and it is the smallest step in this guide.
Clean git only if it was committed.
If the key never reached a commit, skip this section. If it did, rotation is still what protects you, and a rewrite is housekeeping.
History rewriting does not un-leak a pushed secret
GitHub's documentation says that if you only rewrite history and force-push, the commits with the sensitive data may still be accessible elsewhere: in clones, in forks, in cached views and through pull requests that reference them. Once a commit has been pushed, assume someone has it.
Find it
git log --all -S'THE_KEY_VALUE' --oneline commits that add or remove the string git log --all --oneline -- path/to/.env commits that touched a file
The first command puts the full key in your shell history. Search for a prefix instead if that matters.
Rewrite it
GitHub documents git filter-repo, version 2.47 or later, with its --sensitive-data-removal flag. Run it in a fresh clone:
git-filter-repo --sensitive-data-removal --invert-paths --path PATH-TO-FILE git-filter-repo --sensitive-data-removal --replace-text ../passwords.txt git push --force --mirror origin
The first removes a file from all history, using its full path and again for each old location if it was moved. The second replaces the text listed in a file. Pushes to refs/pull/* fail, because GitHub treats those refs as read-only.
Make a repeat harmless.
Keep the key out of the agent's reach, catch it before it is pushed, and make it short-lived so a leak expires.
uvx ranwhat check runs the secret search and the action log together and changes nothing, so you can run it after each long session. The rest of the checklist is in AI coding agent security.
Where each claim comes from.
- Claude Code data usageretention by plan, zero data retention, /feedback
- Explore the .claude directorywhere transcripts live, 30-day default
- Anthropic: API key best practicesConsole steps to delete a key, GitHub scanning
- Anthropic Admin APIsetting a key's status to inactive
- OpenAI: how can I delete my API keydelete from the API keys page
- GitHub: managing personal access tokensdeleting classic and fine-grained tokens
- GitHub: reviewing your authorized OAuth appsRevoke, Revoke all
- GitHub: REST API for OAuth appstoken and grant deletion endpoints
- GitHub: reviewing your security log90 days, personal_access_token, oauth_access
- GitHub: removing sensitive data from a repositoryrotate first, git-filter-repo, forks, Support
- GitHub: about secret scanningfree for public repositories, scope of the scan
- GitHub: about push protectionblocks a push before it lands
- AWS: update access keysdeactivate, last used, delete
- AWS: CloudTrail event history90 days, management events, one Region
- aws cloudtrail lookup-eventsthe AccessKeyId lookup attribute
- Google Cloud: manage API keysRotate key, 30-day undelete
- gcloud services api-keys deletethe delete command
- Slack: auth.revokewhat it revokes, parameters
- Slack: tokensapp-level tokens do not expire, token rotation
- Stripe: API keysRotate key, Expiration, request logs, access policies
- ranwhat/clean.pymasking, backups, what it reads