Skip to content

Build1 publisher3 min readPublished

One Python file wraps SOPS and age to keep API keys out of an agent's context window

A new local-only vault delegates all encryption to SOPS and age, then adds an MCP server so an assistant can act on a secret without receiving it. Adoption costs three artifacts on every machine.

The Engineer · Build desk

Illustration accompanying One Python file wraps SOPS and age to keep API keys out of an agent's context window

What happened

  • A dev.to post argues the .env file was only ever safe while a developer was its sole reader, and that AI coding assistants with repository access moved the threat model while the tooling stayed put.
  • The author's answer, concealer, is a single Python 3 script that uses the standard library only and hands all encryption to SOPS, which came out of Mozilla, and to Filippo Valsorda's age.
  • The only cryptography the script performs itself is verifying the user's password with scrypt and chaining the audit log with HMAC.
  • Around that core it adds typed secrets, scoping by project and environment, a web console, a tamper-evident audit log, and an MCP server intended to let agents use secrets safely.
  • The author rules out cloud vaults such as Vault, Doppler and cloud KMS because they require an account, a network round-trip and a service that stays up, and they park secrets on someone else's server.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost The price of a one-file vault is three installs on every machine that needs a secret, plus two upstream projects to track for updates.
  • decision Teams have to settle whether a coding assistant counts as a reader in their threat model, because that answer decides whether plaintext .env is still acceptable, not the choice of vault.
  • exposure Three of the four named leak paths happen after the value is decrypted, so encryption at rest leaves transcripts, streamed logs and long sessions exactly as reachable as before.
  • precedent A secret manager shipping an MCP broker sets the expectation that cloud vaults and password managers will be asked to run the action themselves and return only a result.

What the agent gets back is the whole design. In the author's own analogy, the assistant asks whether the electricity account is on file and hears "yes, it's on file"; it can say "pay this bill" and the bill gets paid, and the card number never leaves the drawer [17]. Every opening of the drawer goes into a ledger [17]. In code that is a broker: an MCP server that performs the action while holding the value [11]. For the property to hold, no tool on that server can return a raw secret, and nothing the broker launches can print one. The available text of the post ends mid-sentence at the start of that section, so the tool list is not in it [19].

The case for needing a broker at all rests on four paths the author enumerates: a value echoed into a chat transcript that later gets pasted into an issue, a value caught in a log the agent streams back, a value sitting in the model's context for the rest of a long session, and a value committed when the agent stages every file [4]. Three of those four happen outside the repository. Encrypting the file at rest does not reach any of them. For the argument to transfer to your codebase, the assistant has to have both file read and command execution, which is how the post describes the working tool: it scans the repo, suggests fixes, runs commands, and pipes the output back into a model [2]. "That key is now one cat .env away from a context window," the author wrote [3].

The encryption boundary is drawn where I would draw it. Structure-preserving encryption goes to SOPS, which came out of Mozilla, and the cryptography goes to Filippo Valsorda's age [7]. concealer delegates every cipher it uses [8]. "In security, boring is a compliment," the author wrote [10]. The audit log is described as tamper-evident [11], which is a claim about detecting edits, not preventing them.

Adoption is where the single-file framing gets slippery. There are no third-party Python packages [6], but the core shells out to SOPS and age [12], so a machine needs three things present rather than one [18]. Set against a .env file, that is three installs against zero. Against a cloud vault it is still cheap; the author counts those as an account, a network round-trip, and a service that has to stay up, with your secrets on someone else's server [14].

Portability is the other trade. The design is copy the files, type one password, decrypt anywhere [13]. Files plus a password also means the whole vault rides along in your backups. That is precisely what an OS keychain will not do, since it is tied to the machine and does not come along when you wipe or switch laptops [16].

In my view .env remains fine in a repository no agent reads with no agent running commands in it. That describes fewer of my repositories every quarter.

What to watch

  • Whether any tool on concealer's MCP server returns a raw secret value to the calling agent.
  • Whether the project ships a packaged installer that carries SOPS and age, since two binaries per machine is the real adoption cost.
  • Whether established secret managers add MCP brokers that execute with a secret instead of handing it to the model.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories