Replace Static API Keys
AI Security · practitioner · 8 min read · last reviewed 2026-08-15
A long-lived key in a repo or an agent env is a master key you cannot inventory. Workload identity, short-lived tokens, and brokered secrets are the replacement.
TL;DR
- Static keys are copied, unscoped, and do not expire. Revocation is a guess because you cannot count the copies.
- Agents and MCP tools make this worse: the key sits where prompt injection can ask for it.
- Replace CI keys with OIDC workload federation this month. Replace customer and agent credentials with scoped, short-lived tokens this quarter.
- Never put a secret in the model context. Broker it at call time.
- A leaked key that is 20 minutes old should already be useless.
GitHub's secret scanning finds leaked credentials in public repositories on the order of one a minute. Most of them are long-lived API keys: a string pasted into a .env, a CI variable, a notebook, a Slack thread. The leak is not the interesting part. The interesting part is that the key still works next month.
Static API keys were a reasonable 2005 design. One service, one integration, one engineer who remembered to rotate. They do not survive a world of 10,000 ephemeral agents, each of which needs scoped access for twelve seconds. The obituary is in Static API Keys. This page is the replacement.
Why a long-lived key is a different bug in 2026
A password at least pretends to belong to a person you can lock out. A static key is a person-shaped secret with no person:
- It is copied, not issued. Every copy is equally valid.
- It is rarely scoped.
sk_live_...often means the whole account. - It does not expire. Rotation is a project, so it does not happen.
- It shows up in crash logs, support tickets, model context windows, and agent traces.
- Revocation is a guess. You do not know how many copies exist.
When the caller is an AI agent or an MCP tool, the key also sits where prompt injection can ask the model to print its configuration. Secure an MCP server has the rule: never put secrets in the model context. Broker them at call time. That rule is impossible if the only credential you have is a year-old string in an environment variable.
What replaces the string
| Pattern | What the caller gets | When to use it |
|---|---|---|
| Workload identity federation (OIDC to cloud) | A short-lived cloud credential, no long-lived key in CI | GitHub Actions, GitLab, Kubernetes to AWS/GCP/Azure |
| SPIFFE / SPIRE, or cloud equivalent | A documented workload identity, often mTLS | Service-to-service inside your mesh |
| OAuth 2.0 client credentials | An access token with scopes and a TTL | First-party jobs talking to your API |
| User-delegated OAuth (authorization code) | A token limited to what that user may do | Anything an agent does on behalf of a human |
| Per-call brokered secret | The secret is attached in your server, never in the agent | MCP tools, LLM tool use |
The destination is the same idea as zero trust for machines: authenticate the workload every time, give it the least scope, make the credential die before a pastebin post matters.
You do not have to start with SPIFFE. You do have to stop minting sk_live keys that last until someone remembers.
A migration that does not take a quarter
This week. Inventory. Grep for api_key, sk_, AKIA, xoxb-, ghp_. Turn on secret scanning on every repo and the org. Rotate anything that has ever been in Slack or a laptop .env. Put remaining human-held secrets in a manager, not in the repo. The solo-founder stack already ranks this as an afternoon.
This month. CI and deploys. GitHub Actions talking to AWS should use OIDC federation, not an access key in secrets. Same pattern exists for GCP workload identity and Azure federated credentials. Kill the org-wide admin token the intern checked in in 2023.
This quarter. Customer-facing and agent-facing APIs. Issue OAuth access tokens with a TTL measured in minutes or hours, refresh where you must, scopes that name a single intent. For agents, bind the token to the original user and check it on every tool call. That is the agent identity guide.
Leave static keys only for a break-glass path that is stored offline, alerted on use, and rotated after. If "break-glass" is how your app authenticates in production, it is not break-glass.
What "good" looks like
- No long-lived cloud access keys in CI
- No customer API keys that cannot be scoped and revoked in the UI
- No secrets in LLM context, logs, or traces
- Every machine credential has an owner, a TTL, and a name you can grep
- A leaked key that is 20 minutes old is already useless
If you sell an API and the only credential is a forever key, you will spend the next incident explaining why a paste from a contractor still had write access. Issue tokens. Put a revoke button on the key that remains.
Failure modes
- Secret scanning as the strategy. Scanning finds copies. Short TTL makes copies boring.
- One org-wide token "for the agents." You built a master key and handed it to a persuadable model.
- Rotating annually. Annual is static with extra steps.
- Putting the new OIDC setup in one repo and leaving 14 jobs on the old key. Inventory first.
- Customer keys with no scope and no revoke. That is your breach waiting on their intern.
Key takeaways
- Secret scanning finds copies. Short TTL makes copies boring.
- One org-wide token 'for the agents' is a master key handed to a persuadable model.
- Annual rotation is still a static key.
- Customer API keys need a scope and a revoke button, or they are your next incident.
- Break-glass keys are offline, alerted, and rare. They are not how production authenticates.
- Inventory first. Migration second. Leaving 14 jobs on the old key is how this fails.
Frequently asked questions
- Are API keys always wrong?
- A scoped, revocable, short-lived token that happens to be called a key is fine. A forever sk_live string in an environment variable is not.
- What should GitHub Actions use instead of AWS keys?
- OIDC federation. GitHub mints a short-lived token your cloud trusts. The same pattern exists for GCP and Azure. No long-lived access key in secrets.
- How do agents authenticate then?
- A downscoped user token or a workload identity, with per-tool secrets brokered by your server. The model never reads the credential. See Identity for AI Agents.
- Is secret scanning enough?
- No. Scanning is how you find the copies you already made. Short-lived credentials are how a paste stops mattering.
- What about third-party APIs that only offer static keys?
- Put them in a secret manager, rotate on a calendar, restrict by IP if you can, and wrap them so the agent never sees the raw string. Pressure the vendor for OAuth.
Related
Research pillars
Vendor comparisons
Go deeper
Sibling guides