Skip to content

Build1 publisher3 min readPublished Updated

Your agent needs the API call, not the API key

A developer's argument that .env access is an architectural bug in agent workflows, and a small Go CLI that brokers credentials at the process and transport boundary instead.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

Illustration accompanying Your agent needs the API call, not the API key
Generated illustration

What happened

  • AI coding agents need API keys to call services, test integrations and run a stack, so developers give them .env files, export keys into the environment, or paste them into config files the agent can read.
  • The author argues this means secrets live inside the agent's context window, the same window where a prompt-injected instruction or an overly verbose debug log can leak them to an attacker or an untrusted model endpoint.
  • The author states that anyone who has used Claude Code or OpenCode for more than a few days has probably seen a tool call dump an environment variable or a log line echo a connection string, and that 'most of the time nothing bad happens' is a bad security posture.
  • The author frames agents as the first software that reads source, config and secrets and then sends summaries of what it read to a third-party API; in traditional software secrets lived in the process environment, code read them at runtime, and nobody read them back out, whereas the agent both reads the environment and transmits what it knows.
  • Three named leak vectors: context exfiltration (agent reads .env and includes values in a later prompt to an external model, unauditable inside the model pipeline); tool output echo (a command prints an env var or config value and the agent captures stdout into the conversation); prompt injection (a malicious instruction in a fetched web page, dependency or artifact tells the agent to print all environment variables or send .env contents to a URL).

Compiled by The EngineerSomething wrong?How this is made

Why it matters

A developer publishing on dev.to under the handle ikkun1222 argued this week that handing a coding agent your `.env` file is not a convenience trade-off but a design error, because the secret then lives inside the agent's context window, the same window that gets summarized and shipped to a third-party model endpoint [1][2]. The interesting part is not the warning, which is familiar, but the proposed fix: stop trying to instruct the agent and instead inject credentials below the level the agent can observe [12].

The framing is worth restating because it is the load-bearing claim. In conventional software the boundary was crisp: secrets sat in the process environment, code read them at runtime, and nothing read them back out [4]. An agent reads your source, your config and your environment, then transmits a summary of what it read to an external API, so the read path and the exfiltration path are the same path [4].

The author names three leak vectors: context exfiltration, where the agent includes a `.env` value in a later prompt; tool output echo, where a command prints an environment variable and the agent captures stdout into the conversation; and prompt injection, where a malicious instruction in a fetched page, a dependency or an artifact tells the agent to dump the environment or POST the file somewhere [5]. Two of the three do not require the model to want anything [15]. That is the argument against prompt-level mitigation, and the author puts it bluntly: "Please don't print the key" is not a security control [12].

On existing tooling, the post is fair rather than dismissive. Secret managers such as Vault, Doppler and Infisical protect the store but still need to hand the value to the agent, which puts it back in context; `.env` hiding tools such as enject and tene keep plaintext off disk but not out of stdout; credential proxies such as vaulty are described as promising but typically bound to their own vault [6].

The author's own implementation, a Go CLI called trustless with no external dependencies, has three layers [7]. `trustless run -- cmd` resolves secrets from an existing `pass` store, injects them as environment variables, then scans stdout and stderr afterwards and replaces the values, including base64 and URL-encoded variants [8]. `trustless proxy` does per-host header and query-parameter injection for services including EDINET, e-Stat, xAI and OpenRouter, with the agent pointed at `127.0.0.1:8080` [9]. `trustless serve` is a scanning reverse proxy in front of OpenAI-compatible endpoints, checking outbound requests against keyword, regex and entropy rules described as gitleaks-compatible and masking matches in flight [10]. There was no new vault because the author already used `pass`, so migration cost was zero, and Bitwarden is supported with OAuth token refresh for Google and Lark [11].

Read the layers against the vectors and the mapping is one to one, which is the tell that the threat model came first [16]. The caveats are the author's own: it is MIT-licensed, self-reported at 321 tests with race-detector-clean and cosign-signed releases, and presented as one implementation whose threat model matters more than the code [13]. A rules-based outbound scanner also only catches what its rules describe, which makes the DLP layer the weakest of the three by construction.

What to watch: whether agent runtimes start brokering credentials natively rather than reading them from the environment, whether credential proxies decouple from their vendors' vaults [6], and how much per-host configuration a proxy approach accumulates before teams abandon it [9].

Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories