Why your AI coding agent should never see your API keys
Your AI coding agent needs your API keys. It needs them to call services, to test integrations, to run your stack. So you give it .env files, or you export keys into the environment, or you paste them into config files the agent can read. That means your secrets live inside the agent's context window — the same window where a prompt-injected instruction or an overly verbose debug log can leak…
It is crucial to keep your API keys secure when using an AI coding agent. Often, developers inadvertently expose these keys by feeding .env files or exporting keys into the environment to the agent. This exposes your secrets to potential attackers or untrusted endpoints that the agent may communicate with. While the risk might seem minimal most of the time, it is still a significant security concern.
The issue arises from AI agents being the first software that not only reads your source code and configurations but also communicates with third-party APIs. Unlike traditional software, where secrets live in the system's context and are read by the code without being transmitted back out, AI agents both read environment variables and transmit what they know. This creates three potential leak vectors:
1. Context exfiltration, where the agent includes secret values in prompts sent to external models.
2. Tool output echo, where a command prints an environment variable or a config value, and the agent captures this output, storing it in the conversation.
3. Prompt injection, where a malicious instruction instructs the agent to print all environment variables or send the contents of .env to a specified URL.
To address these leaks, various solutions exist. Secret managers like Vault, Doppler, and Infisical help secure your code, but they still require the agent to access the secrets, reintroducing them into the context. .env hiding techniques, while useful for keeping plaintext off disk, can still result in secret leakage through command outputs. Credential proxies, although promising, are often tied to their own vaults and not universally compatible.
The author of this piece ultimately built a small, self-contained CLI (written in Go with no external dependencies) to tackle the issue. The solution involves three layers:
1. Subprocess injection with output sanitization: The CLI resolves secrets from an existing password store and injects them as environment variables before the command runs. After execution, the command's standard output and standard error are scanned for secret values, replacing them before the agent sees them.
2. HTTP proxy with per-host injection: For services requiring headers or query parameters (such as EDINET, e-Stat, xAI, and OpenRouter), a trustless proxy injects the correct credentials per host, allowing the agent to interact with these services without directly accessing the API keys.
3. DLP reverse proxy for LLM calls: This layer acts as a scanning proxy in front of OpenAI-compatible endpoints. It checks outbound requests against secret patterns (keywords, regex, entropy, and gitleaks-compatible rules) and masks sensitive information in-flight before it leaves the machine.
The author chose to use an existing password store (pass) instead of creating a new vault, as it eliminated the need for migration. The CLI supports Bitwarden as well, with OAuth token auto-refresh for Google and Lark. By injecting secrets at the process or transport level rather than the prompt level, developers can effectively protect their API keys and maintain a secure environment for their AI coding agents.
In summary, never allow secrets to enter the agent's context window—whether as environment variables, configuration files, or tool outputs. Once inside, your secrets are vulnerable to leaks. Instead, inject secrets at the process or transport boundary, not at the prompt level. Sanitize both input and output, focusing on scanning outbound requests if your agent communicates directly with external APIs.
A DLP layer can ensure that you "know it didn't leak" rather than simply hoping it didn't. For a practical implementation, refer to the trustless CLI available at https://github.com/ikkun1222/trustless.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.