SORDINO
~/writeups/what-happens-to-a-pasted-secret

Is it safe to paste API keys into Claude or ChatGPT? The full life of a pasted secret

Pasted an API key into an AI chat? Treat it as exposed and rotate it now. Where the secret lands, what deletion doesn't fix, and how to make it moot.

FailSpy9 min read
#api-keys#claude-code#secret-management#ai-coding-tools#data-retention

No. If you’ve pasted an API key, a connection string, or a password into Claude, ChatGPT, or a coding agent’s terminal, treat it as exposed and rotate it now. There’s a full checklist below, but rotation is the checklist if you only do one thing. This holds even if you trust the provider completely, and even if you deleted the chat thirty seconds later.

The reason is mechanical, and worth tracing in full, because “the AI saw my key” undersells what actually happened. By the time you hit enter, that value exists in more places than the chat window: a retention window on the provider’s side, a plaintext transcript on your own disk, possibly your employer’s admin console, and the model’s context, where an attacker can sometimes reach it without you pasting anything at all. Deleting the chat clears at most one of these. This article walks each of those hops, then the cleanup drill, then the structural fix: rewriting the request before it leaves your machine, so detected secrets reach the provider only as opaque tokens. Disclosure up front: I maintain Sordino, a local masking proxy (open-source core, free for individuals) that does exactly that, so weigh my incentives however you see fit.

None of this is exotic, either. The canonical example is still Samsung in 2023: engineers pasted source code, test sequences, and an internal meeting transcript into ChatGPT (three separate incidents in roughly three weeks), and the company responded by banning the tools. Those weren’t careless people. Pasting context is how these tools get used, which means sensitive material rides along eventually, at roughly the rate you use them.

So, the trace.

How long do OpenAI and Anthropic keep what you paste?

Longer than “until I close the tab.” For the OpenAI API, OpenAI’s enterprise privacy documentation describes retaining API inputs and outputs for up to 30 days for abuse monitoring; zero-data-retention handling exists, though it requires prior approval and doesn’t cover every endpoint. On the Anthropic side, Anthropic’s retention practices for Mythos-class models (effective June 9, 2026) attach a mandatory ~30-day retention to those models as part of its safety work, reaching even organizations with zero-data-retention agreements. The strongest retention guarantee money can negotiate acquired a model-shaped exception; I take the whole envelope apart in Zero data retention isn’t zero exposure.

Two things follow. First, deleting a conversation doesn’t claw anything back out of an abuse-monitoring window that’s already running. Second, retention terms are policy, and policy has effective dates: whatever terms your secret was sent under, the terms that matter are the ones in force now, plus whatever comes next.

Claude Code stores your prompts in plaintext on your own disk

Claude Code writes session transcripts as plaintext JSONL under ~/.claude/projects/. I verified this on a live install this month (July 2026), and you can check yours:

grep -rl "sk-" ~/.claude/projects/ | head

If a key has passed through a session, it’s sitting in those files in the clear, regardless of what any provider promises about their servers. Your laptop is outside every retention agreement ever signed. That matters more than it sounds like it should: transcript files get swept into backups, synced by whatever is watching your home directory, and read by any other tool or agent with file access.

Who can see my Claude prompts at work?

On a personal account: you, and the provider within the windows above. On a work account, add your organization’s admins. Enterprise AI plans generally give org admins audit and export access to conversation history (Anthropic documents audit logs among its enterprise administrative capabilities), so the honest mental model is that a work AI account is work email. Anything you paste can surface in an export you never see. That’s a legitimate capability -- it’s how security teams do incident response -- but it means “who can see this?” includes people you probably haven’t thought about. If you’re on the other side of that arrangement, writing the policy rather than pasting the key, I wrote up where those policies tend to leak separately.

Do you even have to paste it for it to leak?

No, and this is the part that changed how I think about the problem. With a chat window, you decide what gets sent. A coding agent decides for itself what to read: it cats config files, prints environment variables while debugging, and captures error output that happens to include your connection string. All of that enters the model context exactly as if you’d typed it. .gitignore doesn’t help here; it governs what gets committed, not what an agent reads while working. “I never pasted a secret” and “no secret was sent” are different claims.

Once a secret is in the context, it can be a target. Two documented cases from 2025:

CamoLeak (GitHub Copilot Chat, CVSS 9.6). A researcher at Legit Security showed that remote prompt injection could turn a victim’s Copilot Chat session into an exfiltration channel for private code and credentials -- AWS keys among the demonstrated payloads. In his words: “The attack combined a novel CSP bypass using GitHub’s own infrastructure with remote prompt injection.” Per the same writeup, “GitHub fixed it by disabling image rendering in Copilot Chat completely”; the fix shipped August 14, 2025.

Prefix stripping. In a case documented by Microsoft Threat Intelligence (reported here), a prompt-injection attack instructed Claude Code, running in a GitHub Action, to strip the sk-ant- prefix from a credential before exfiltrating it, so the outbound value would no longer match signature-based secret scanners.

That second one is the load-bearing lesson of this whole section: the model already held the secret, and output-side detection was defeated by asking politely. Scanning what leaves a model is a negotiation with an adversary who can rewrite the output. A model that never received the value has nothing to be talked out of.

I already pasted a key. What do I do right now?

Nothing here needs a product. This is the incident-response drill, sized for one leaked credential:

  1. Rotate at the issuer, now. Revoke the old key, mint a new one -- treat it exactly like a key committed to a public repo. If immediate rotation would break production, constrain it first (scope it down, add an IP allowlist) and rotate the same day. Every other step is secondary to this one.
  2. Rotate the whole credential, not the visible part. A leaked connection string means the database password changes, not just the string -- and treat the hostname, port, and username as reconnaissance data that’s now out. A leaked .env means everything in it.
  3. Check usage logs for the credential since the moment of the paste. You’re looking for activity that isn’t yours.
  4. Delete the conversation, with accurate expectations. Worth doing, and it does not reach an abuse-monitoring window already in progress, the transcript on your laptop, or anything your org has already exported.
  5. Scrub your own disk. Grep ~/.claude/projects/ and your shell history for the raw value and clean it out, before a backup or another agent picks it up.
  6. If it was a shared or work credential, tell the owner. An awkward message today beats the same message after someone else finds it in a log. On a work account, follow the credential-exposure process and assume admin visibility rather than quietly hoping.

For steps 1 and 3, here’s where that actually happens for the credentials devs paste most:

ProviderWhere to revokeWhere to check usage
AWS IAM access keyIAM console, the affected user’s Security credentials tab: deactivate the key, then delete itCloudTrail event history, filtered by the access key ID
OpenAI API keyPlatform dashboard, API keys page: delete the key and reissueUsage page in the same dashboard
Anthropic API keyAnthropic Console, API Keys section: disable or deleteUsage and cost pages in the Console
GitHub tokenSettings, Developer settings, Personal access tokens: delete or regenerateAccount security log; org audit log for org resources
Stripe API keyDashboard, Developers, API keys: roll the keyRequest logs under Developers in the Dashboard
Database connection stringAt the database itself: change the user’s password (ALTER USER, or your managed provider’s credentials panel)The database’s authentication and connection logs

Rotation resolves the key case. It does nothing for the case where what went out was a customer’s email in a stack trace or a name in a support-ticket dump -- you can’t rotate someone’s identity. That asymmetry is why the structural fix matters, and it raises the obvious question.

How do you make the paste harmless?

The oldest rule of secret handling still applies: the best way to keep a secret is to never say it. A secrets manager works because the raw value never appears where it doesn’t need to be. The equivalent for AI tooling is masking at egress -- rewriting the request after your tool composes it and before it leaves your machine. The way I put it in Sordino’s docs:

“Not zero data retention — zero data access. The AI never had your secrets to begin with.”

Mechanically, Sordino does this for Claude Code and OpenAI Codex as a local proxy on 127.0.0.1. No TLS interception, no certificates: Claude Code natively honors ANTHROPIC_BASE_URL, and the proxy re-originates TLS to the provider. Outbound prompts and tool output -- which is how the .env case leaks -- are scanned for API keys, passwords, bearer tokens, connection strings, emails, phone numbers, credit cards, IBANs, and SSNs. (A raw SSH private key has no regex signature -- register it as a secret and it masks unconditionally.) Matches become deterministic tokens like [EMAIL_ADDRESS_a47n1d8s9c0f] before the bytes leave the machine, restored locally when a response references them, so multi-turn work and prompt caching keep functioning. The token-to-value table stays on your machine, encrypted (AES-256-GCM), isolated per project; there’s nothing on the provider side to reverse. And it fails closed -- mask-or-refuse -- so a masking failure rejects the request rather than silently forwarding unmasked bytes. Full mechanics are in the docs.

Now run the trace again with that in place. The provider’s retention window holds an opaque token, not your key. An admin export shows tokens. And the injection attacks above lose their target: the model can’t leak a value it never had -- whether it had it depends on detection, which is exactly the first item in the limits below.

What this doesn’t solve

I’d rather list these myself than have you find them the hard way.

  • Detection is pattern-based, and recall is not 100%. A secret that matches no recognizer goes through unmasked. Structured credentials are the tractable core of this problem: known prefixes, fixed shapes, high entropy. Free-text PII is harder; Sordino ships an optional local ML model (CPU-only, offline, off by default) for names, locations, and organizations, and I’d still call free-text detection best-effort. The exception is values you explicitly register as secrets: those mask unconditionally, even with the detection engine dialed down.
  • Your local transcripts still hold plaintext. Masking happens at the proxy, on the wire. The JSONL files under ~/.claude/projects/ are unchanged, so step 5 of the drill stays relevant.
  • It doesn’t replace rotation, least-privilege, or keeping secrets out of your repo. It’s the layer for what slips past those into a prompt, which, per the incident record above, is a nonzero amount.

Quick answers

Is it safe to paste API keys into ChatGPT or Claude?

No. Treat any pasted secret as exposed and rotate it. The provider isn’t the only copy-holder; your own disk and possibly your org’s admin console are in the chain too.

Does deleting the chat delete my data?

It removes the conversation from your view and, per provider policy, eventually from their systems. It doesn’t reach an abuse-monitoring window already in progress, the plaintext transcript on your laptop, or anything already exported by your org. Rotation is remediation; deletion is tidying.

Does a zero-data-retention agreement fix this?

It narrows what the provider keeps, with carve-outs, and it says nothing about your laptop or your admins. Longer treatment in what ZDR actually covers.

How do I stop Claude Code from reading my .env?

Permissioning controls what the agent may execute; masking controls what leaves the machine when something gets read anyway. They’re different layers, and you probably want both. .gitignore is not one of the layers; it only governs commits.

I use a work account. Who can see my prompts?

Assume your org’s admins can, through audit and export tooling. If prompts were masked at egress, an export shows tokens rather than raw values.

Shouldn’t I just never paste secrets?

You should never paste secrets. You will anyway -- at 11pm, with a failing deploy, when the fastest path to an answer is pasting the whole error message, connection string included. And your agent will “paste” on your behalf every time tool output contains a value you never typed. A policy that depends on humans never doing the convenient thing isn’t a policy; it’s hope. Make the convenient path safe instead.