I pasted an API key into my coding agent. What now?
Rotate or revoke the key first, then deal with the copies in your agent's history, then set up zn-gate so the next one is blocked or replaced by a marker before the model sees it.
You typed or pasted an API key into the chat of a coding agent, or the agent read it from a file. The key is now in the conversation that was sent to the model, and probably in the agent's history on your disk. This page gives the steps in the order that matters: rotate the key, clean up the copies, then stop it from happening again.
1. Rotate or revoke the key first
Do this before anything else. Deleting a chat or a history file does not undo a copy that was already sent to a model provider or saved in a backup. Only revoking the key makes the leaked value useless.
- Open the console of the service that issued the key. Find the key in its list of API keys, tokens or access keys.
- Create a new key if something depends on the old one. If a live service uses the key and you cannot afford downtime, create the replacement first, switch your application to it, update every other place that uses the key (CI secrets, deploy settings, teammates), then revoke the old key. AWS, GitHub and Google Cloud describe this order in their own pages. If nothing depends on the key, revoke it right away.
- Revoke or delete the old key. Do not leave it active "for now".
- Give the new key the narrowest permissions it needs.
- Store the new key somewhere the agent will not read it. Not in the chat, and not in a plain
.envfile the agent can open. See step 3 below. - Look at the provider's usage or access log for the old key. If you see requests you do not recognise, treat the account as compromised and follow the provider's guidance.
Where to revoke, in each provider's own documentation:
| Provider | What its documentation says |
|---|---|
| AWS | Updating IAM user access keys: create a second key, switch your applications to it, deactivate the first key, and delete it when nothing needs it. |
| GitHub | Remediating a leaked secret: a step-by-step guide that includes revoking the secret, finding the services that use it and checking for unauthorised access. Tokens are managed in Managing your personal access tokens. |
| Google Cloud | API keys: the page explains how to rotate a key, which creates a new key with the same restrictions, and how to delete the old one once your applications use the new one. |
| Stripe | API keys: how to roll a key and when the old one expires. |
| Anthropic | API key best practices: if you suspect a key is compromised, revoke it from the API keys page of the Claude Console with "Delete API key". |
For a service that is not listed, open its own documentation and search for "revoke", "rotate" or "roll" a key. We only link pages we could open and read.
2. Clean up the copies that stay on your machine
Claude Code, Codex CLI, Cursor and OpenCode keep a history of your conversations, and a key that you typed or that passed through a tool can be in it. Claude Code also keeps every prompt you type in a separate prompt-history file. Each agent stores its history in a different place and has different controls, and for some of them the documentation says nothing about the local path or retention.
We keep that in one guide so it stays correct in one place: Do coding agents keep your API keys in their transcripts? It lists where each of the four agents stores its history according to its vendor's documentation, how long it is kept, what each vendor says about uploads, how to find the files that hold a key and delete them, and the copies that are easy to forget, such as backups and cloud sync of your home folder.
Do this after step 1, not instead of it.
3. Stop the next one with zn-gate
zn-gate is a local layer between your coding agent and its tools. It runs on your machine, with no account. Its secrets scrubber is available in zn-gate 1.5.0 and later (on Windows, 1.5.1 or later), and works with Claude Code, Codex CLI, Cursor (IDE) and OpenCode. What it can change differs by agent.
What it does about a key you are about to paste
According to the Scrubber and secrets vault page:
- Pasted prompts, file reads, command output, searches and MCP tool results go through the scrubber before they reach the model. Values it knows (from the vault and your
.envfiles) and more than 60 secret formats become stable markers such as__ZN_AWS_KEY_1__, so the model gets the marker instead of the value wherever the agent lets zn-gate rewrite them (see the limits below). - The hooks block reads of
.envfiles that hold real values and of credential files such as~/.aws/credentialsor~/.ssh/id_*. The documentation calls this a guardrail, not a sandbox. - Real values live in an encrypted vault on your machine. The agent works with markers, and a value is filled in only where you allowed it.
A secret pasted into a prompt is blocked in the four agents, so the prompt does not reach the model. Blocking does not delete what you typed from your own machine: the agent can keep the prompt locally (Claude Code keeps it in clear text in its transcript). Markers appear only in tool output that zn-gate scrubbed.
Tokens that sit in an MCP server's env or headers are a separate case: Plaintext tokens in your MCP config: how to move them out shows how to move them out of the config file.
Set it up
You need Node.js 18 or later. Run these in your own terminal:
npx -y zn-gate init
npx -y zn-gate unlock
npx -y zn-gate env shadow .env
npx -y zn-gate check
initfinds the four agents on your machine, shows the setup for each one that is not protected yet and runs each step after you confirm it.unlockcreates the vault the first time. With the system keychain it needs an interactive terminal.env shadow .envmoves the values of your.envfile into the vault. The file keeps markers such as__ZN_STRIPE_KEY__.checktests with a fake secret in a temporary folder and tells you which agent is not protected. Nothing is sent anywhere. What the output means.
To add a single secret without pasting it into a chat or putting it on a command line, type it at a hidden prompt: zn secret set GITHUB_TOKEN --host api.github.com. The documentation says never to pass a secret as an argument.
To try it with a fake value, open your agent in an empty folder and paste the AWS documentation example key AKIAIOSFODNN7EXAMPLE into the prompt. If zn-gate recognises the format, the prompt is blocked. If it is not blocked, that format may not be one zn-gate detects, and this test says nothing about your real keys.
What zn-gate does not do
These limits come from the Scrubber and secrets vault page and zn-gate's threat model.
- It does not clean transcripts that were written before you installed it. The key you pasted today stays in them until you delete them (step 2).
- It does not revoke anything and does not control what an agent vendor stores on its servers. Rotation is always step 1.
- The scrubber finds known values and recognisable formats. A secret with no known format that is not in the vault or a
.envfile can get through. - In Cursor, only MCP tool output can be rewritten. Shell output and file contents are not scrubbed there.
- Some agents keep their own local copies. Codex's session log keeps the original output.
- In Claude Code, a prompt that zn-gate blocked stays in the transcript in clear text, as Claude Code's own documentation says.
Frequently asked questions
Do I have to rotate the key if I deleted the conversation? Yes. Deleting local files does not remove a copy that was sent to the model provider or saved in a backup. Revoke the key first.
Can I just delete the transcript and keep the key? That is not safe. The key was sent to the model as part of the conversation, so treat it as exposed.
Does zn-gate remove a key that is already in my history? No. It acts on new prompts and tool output. Existing history files stay as they are.
Will zn-gate stop me from pasting a key? It blocks a secret pasted into a prompt when it recognises the format, in Claude Code, Codex CLI, Cursor and OpenCode. A secret in a format it does not know can pass, so keep keys out of chats anyway.
How do I remove zn-gate's hooks? zn hooks uninstall <agent>, for example zn hooks uninstall codex.
Related pages
- Do coding agents keep your API keys in their transcripts?: where each agent stores its history, and a cleanup checklist
- Keep API keys out of Codex CLI
- Keep API keys out of OpenCode
- Plaintext tokens in your MCP config: how to move them out
- How to stop Cursor from reading your .env
- Scrubber and secrets vault
- Install zn-gate and Check that it works
Sources
- AWS, updating IAM user access keys: https://docs.aws.amazon.com/IAM/latest/UserGuide/id-credentials-access-keys-update.html
- GitHub, remediating a leaked secret: https://docs.github.com/en/code-security/tutorials/remediate-leaked-secrets/remediating-a-leaked-secret
- GitHub, managing personal access tokens: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
- Google Cloud, API keys: https://cloud.google.com/docs/authentication/api-keys
- Stripe, API keys: https://docs.stripe.com/keys
- Anthropic, API key best practices: https://support.claude.com/en/articles/9767949-api-key-best-practices-keeping-your-keys-safe-and-secure
- zn-gate, threat model: https://github.com/usezn/zn/blob/main/docs/threat-model.md
- Claude Code, application data (transcripts and prompt history): https://code.claude.com/docs/en/claude-directory