Secrets and agents: one vault, stdin only

Checked 22 Sep 2026 · By Luke Czak

ArticleHow to Use AIFree to read

I pass credentials from the vault through stdin to keep values out of command arguments. That removes one exposure route; it does not prevent a receiving command or a logging wrapper from recording the value.

Handing an autonomous worker real credentials multiplies every mistake a human would already make with them, because the worker runs the command exactly as specified, at speed, without the moment of hesitation a person gets before typing a password into a terminal. The habits that were merely good practice for a human become load-bearing the moment the thing typing the command isn’t pausing to think about it.

The first rule is where the value goes: on stdin, never as a command argument. A secret passed as an argument sits in the process list for the duration of the command and in shell history indefinitely, readable by anything else on the machine with permission to look — which, on a box also running other agents, is a real and not hypothetical audience. Piping the value in through stdin means it never becomes an argument in the first place, so the value is absent from that argument list. I still check the sender and receiver: a literal secret typed into the shell, tracing enabled around the command, or a receiver that logs its input can record it despite the use of stdin.

The second rule is subtler and cost me real time before I understood it: never capture key material through command substitution. Capturing a value that way strips the trailing newline, and for something like an SSH private key, that final newline isn’t decorative — it’s part of the format, and a key missing it gets rejected outright. The value looks identical to the eye and fails the moment something tries to use it. The fix is boring and reliable: write it to a file with restrictive permissions, use it from there, delete the file afterwards. Nothing clever, which is exactly what you want from a step that handles key material.

The third rule is about what happens after a mistake, because mistakes happen regardless of how careful the process is. Any secret that gets pasted into a chat transcript or printed to a terminal an agent can read should be treated as compromised the moment it happens, not investigated for whether it actually leaked. Rotate it, then update wherever it’s stored. The assumption that a pasted secret has been logged somewhere, even if you can’t immediately point to where, is the cheap assumption — rotating a key costs seconds; assuming it’s fine and being wrong costs considerably more.

Underneath all three rules is a single structural choice that makes the rest of it enforceable: one vault, one address scheme, nothing sensitive living in a repo, an env file, or a config file that an agent might read, log, or accidentally commit. Scattered secrets mean scattered exceptions, and every exception is a place where an agent has to make a judgement call about whether this particular file is safe to touch — a call it isn’t equipped to make well, because it doesn’t have the institutional memory of why the exception exists.

A stray env file is the specific case worth naming, because it’s the one that keeps recurring across projects that otherwise do this properly. It gets created once as a quick way to unblock a local run, works, and quietly becomes the actual mechanism a script depends on — invisible to the vault, invisible to rotation, sitting in a directory an agent has full read access to and no reason to suspect is special. The fix isn’t vigilance, because vigilance doesn’t scale across however many projects an agent touches. It’s not letting that file be a legitimate place for a real value to exist in the first place.

None of this is exotic security practice. It’s the same hygiene good engineering teams already apply to humans with terminal access, just enforced mechanically because an agent won’t intuit the reason a rule exists — it will follow the rule if the rule is real, and route straight through the gap if the gap is merely a convention nobody wrote down.

Comments (0)

Sign in to comment.