Skip to main content

Keep Secrets Out of Your AI Agents: Credential Gateways, Short-Lived Tokens, and the Leak That Should Be Impossible

11 min readDora NodaDora Noda
Share
On this page

In 2026, a prompt-injection payload hidden in a GitHub issue title tricked an AI workflow into running npm install on a malicious package — across roughly 4,000 developer machines. Nobody typed the command. Nobody reviewed it. An agent read untrusted text, treated it as instructions, and executed it with the full authority of every secret sitting in its environment.

That incident is the whole argument of this post in one paragraph. The question is no longer whether your agents will encounter hostile input — they browse, read issues, fetch URLs, and install MCP servers for a living. The question is what a compromised agent can reach. If the answer is "every long-lived API key in its environment variables and MCP config," you do not have an agent security policy. You have a blast radius with a to-do list.

Here is the verdict up front. July 2026 produced the pattern that fixes this, twice in two days: first OneCLI, an open-source credential gateway that holds real secrets in an encrypted vault and hands agents placeholder keys it swaps at request time, drawing on the order of a hundred points on Show HN; then Render's managed OIDC, which lets services authenticate to Anthropic and OpenAI with short-lived, auto-rotating tokens instead of stored API keys. Underneath both sits the same broker architecture: credentials live in infrastructure the agent cannot read, the agent receives only scoped, short-lived tokens minted per task, and revocation is a switch on the broker side.

And there is a short list of things a prompt-injected agent should never be able to touch:

Should never be agent-readableWhy it must live behind a broker
Long-lived provider API keys (sk-ant-…, sk-…)One leak lasts forever; rotation is manual and forensic
Other tenants' or other agents' credentialsA confused agent must not be able to spend someone else's access
Vault/KMS master keys and root tokensWhoever holds these re-mints everything below them
Standing cloud IAM keys with broad scopeThe classic lateral-movement prize; replace with minted-per-task identity
Raw MCP config files with embedded secretsConfig is model-visible context — treat it as already published

Everything below is how to make that table true: the leak paths, the two July signals, how the three broker layers compare, and a checklist for baking it into a self-hosted platform.

How a prompt-injected agent actually leaks

The fundamental problem is architectural, and one open-source writeup states it bluntly: credentials are treated as configuration, not as secrets. The moment an API key lands in mcp.json or .env, it becomes part of the agent's readable context — and therefore readable by anything that can influence the agent.

The exfiltration paths are concrete, not theoretical:

  • Environment-variable dumping. A malicious README, dependency, or code comment instructs the model to print its environment. Agent red-team guides now state the rule explicitly: an environment variable must never appear in model-visible output. Check Point Research demonstrated exactly this class of attack with CVEs against both Cursor and Claude Code — crafted prompts that trick the agent into sending secrets to attacker-controlled servers.
  • MCP config tampering. CVE-2025-54135 and CVE-2025-54136 covered prompt injection causing agents to create or modify MCP configuration files, pointing the agent at attacker-controlled servers. Your tool manifest is a write target, not just a read target.
  • Malicious MCP servers. A fake Postmark server published to npm was caught silently BCC'ing every email sent through it; a malicious GitHub MCP server hijacked agents into exfiltrating private-repository data. The agent browses registries and installs tools the way a developer browses packages — usually without a security review.
  • Tool-result injection. Poisoned content in a document, a tool description, or a tool result tells the agent to read a secret file (~/.ssh/id_rsa, .env) and exfiltrate it through another tool it legitimately holds. The OWASP MCP Top 10 now catalogs this whole family.

Notice what every one of these has in common: the attack succeeds because a usable, long-lived secret was sitting where the agent could see it. Remove the standing secret and the same injection degrades from "total credential compromise" to "one scoped, expiring token burned" — which is precisely what the broker architecture buys.

Signal 1: the credential gateway (OneCLI)

OneCLI is the clearest statement of the gateway half of the pattern: a Rust proxy (roughly 13k lines) plus dashboard and Postgres store that sits between your agents and the services they call. The flow:

  1. You store each real credential once, encrypted, in OneCLI's vault.
  2. Agents get placeholder keys in their config — strings that authenticate to nothing.
  3. When an agent makes an HTTP call through the proxy, OneCLI matches the request by host and path, verifies that agent is allowed that route, swaps the placeholder for the real credential, and forwards the request.

The agent never touches the actual secret. Its config files, its environment, its logs, its tool transcripts — all contain only placeholders. A prompt injection that dumps the agent's entire context recovers tokens that are worthless outside the proxy, and worthless without the proxy's own access decision.

The Show HN discussion landed because the timing is perfect: teams are handing raw API keys to coding agents the way they used to hand .env files to junior developers, and the failure mode just demonstrated itself at scale. The gateway's honest limits are worth naming too. It is a proxy, so traffic must flow through it — latency, availability, and coverage for non-HTTP credential uses (SSH keys, local CLIs) are real design questions. And the vault itself becomes the highest-value target in the system, which is why "backed by a real KMS, audited per access" belongs in any serious deployment rather than "encrypted" as a hand-wave. Gateway injection solves visibility: the agent cannot see the secret. It does not by itself solve authority: something still has to decide what the agent may do.

Signal 2: short-lived OIDC instead of stored keys

The second half of the pattern removes the stored key entirely. Anthropic's Workload Identity Federation, generally available since June 2026, is the reference design: workloads authenticate to the Claude API with short-lived OIDC tokens minted from an identity provider you already run — AWS IAM, Google Cloud, Kubernetes service accounts, GitHub Actions, Entra ID, Okta, SPIFFE, anything standards-compliant. You configure federation rules in the Claude Console binding an external identity to a service account; at runtime the workload presents its signed JWT, Anthropic verifies it against your rules, and returns a short-lived access token bound to that service account. The SDK handles exchange and refresh automatically, and it covers every Claude API endpoint including the SDKs and Claude Code — so headless agents in CI run with no static key at all.

Each workload gets its own identity, roles, and audit trail instead of sharing one sk-ant-… string. That last part matters as much as the expiry: a shared key makes every agent's calls indistinguishable, while per-workload identity makes each one attributable.

Render's managed OIDC, shipped days after the OneCLI launch, productizes the same idea for its tenants: with a Pro workspace or higher, each Render service gets a short-lived authentication token that rotates automatically, usable against Anthropic and OpenAI (plus AWS), so services call models with nothing long-lived to store, rotate, or leak. Render's August agent-tooling update extended the same posture to its MCP server and CLI. The direction is unmistakable: the platform mints identity at runtime; the tenant stops pasting keys into dashboards.

One honest caveat: as of mid-2026 this is uneven across providers — OpenAI-side keyless auth remains gated and undocumented outside OpenAI's own surfaces, which is exactly why a platform-level broker matters more than any single provider's feature. You want the architecture to hold even for the provider that still only takes a static key — and that is what the third layer is for.

The three layers, compared

Gateway injection, OIDC federation, and dynamic-secret brokers are not competing answers. They cover different parts of the problem and compose well. Here is the comparison that matters — judged by the only question that counts: the agent is already compromised; now what?

LayerExampleWhat the agent holdsCompromised-agent blast radiusRevocation story
Credential gateway (request-time injection)OneCLIPlaceholder keys, valid only through the proxyAttacker sees placeholders; must also beat the proxy's per-route access checkDisable the agent's routes broker-side; placeholders die with the policy
Workload identity federation (OIDC)Anthropic WIF, Render managed OIDCShort-lived tokens (minutes), auto-refreshed, bound to one service accountToken works until expiry — minutes, with the service account's scope, fully attributedDelete the federation rule or service account; exchange stops immediately
Dynamic-secret broker (JIT credentials)HashiCorp Vault dynamic secrets, Audex-style scoped AWS credsJust-in-time credentials with a TTL, minted per taskCredential dies on TTL or lease revoke; each issuance is logged with user attributionRevoke the lease or role broker-side; no secret material to rotate

HashiCorp's own validated pattern for AI agent authentication with Vault dynamic secrets shows the third layer in full: the agent logs in via JWT, Vault maps group claims to a scoped policy, and every credential issued is unique, TTL-bound, auto-revoked at lease expiry, and traceable to the requesting user. Tools like Audex wrap the same idea in an operator-friendly shape — temporary IAM permissions injected into a subprocess, an append-only HMAC-chained audit trail, credentials that stop working when the command exits.

Read the table as a composition guide. Federation is the cleanest answer wherever the provider speaks OIDC — no secret exists to steal. The dynamic-secret broker covers everything that still takes keys: databases, third-party APIs, cloud IAM — minting narrow, expiring credentials per task instead of distributing standing ones. The gateway covers the messy middle: legacy tools, HTTP APIs, and agents whose configs you cannot fully control, where placeholders plus per-route policy beat plaintext. A serious platform runs all three and can say, for any credential an agent uses, which row of the table it sits in.

Baking it into a self-hosted platform

This is where self-hosting stops being the harder option and starts being the advantaged one. A PaaS that owns its control plane can make brokered identity the default path rather than a feature tenants bolt on. The checklist:

  1. Workload identity via OIDC federation first. Every agent runtime — build job, sandbox, scheduled task — gets a platform-minted identity (Kubernetes service account, SPIFFE ID, CI OIDC token) that federates outward. Static provider keys become the fallback you have to justify, not the default the quickstart teaches.
  2. A Vault- or KMS-backed broker for everything with a key. Long-lived secrets live in exactly one encrypted store, and agents never read from it directly — they request scoped, TTL-bound credentials through the broker, which logs every issuance with agent attribution.
  3. Per-task scoping, not per-agent standing access. Tokens and dynamic credentials are minted for the task at hand with the narrowest policy that completes it, then expire. An agent that deploys staging on Monday holds no credential that deploys production on Friday.
  4. Per-agent audit trails as a first-class surface. Every issuance, exchange, and injection is logged against the agent's identity — which is what turns "the deploy was made by an agent" from a shrug into an attributable, reviewable event.
  5. Revocation as a broker-side switch. Killing an agent's access means flipping broker policy — disabling a route, deleting a federation rule, revoking a lease — not hunting down copies of a key you distributed six months ago and hoping you found them all.

Note what this architecture does to the incident at the top of the post. The injected instruction still runs — prompt injection is an input problem and no credential design fixes inputs. But the command executes holding a minutes-lived, narrowly scoped token instead of the kingdom's keys: the exfiltration window collapses from "indefinitely" to "minutes," the blast radius collapses from "everything the key touches" to "one task's scope," and the audit trail names the agent, the issuance, and the call. That is the difference between a security incident and a postmortem footnote.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Agents are first-class operators there, which is exactly why agent identity should be brokered, short-lived, and revocable instead of pasted into a config file. Star the repo on GitHub or deploy your first app today.

Related articles

Give your agents a chain backend

Autonomous agents hit RPC endpoints very differently than people do. See what bex router handles on their behalf.

Read the agents guide