A secret - a key, a token, a password - is doubly dangerous in an agentic environment: it is seen not only by a human but by a model that reads files, terminal output and session history. Unlike a colleague, a model can reproduce a secret verbatim in an answer, in code or in a commit without realizing it. The question is not whether secrets are needed but where they lie and who can reach them - and the answer is half of security.
The naive move is to put a token wherever it is convenient for the agent: paste it into the prompt, leave it in .env inside the repository, show it in command output. It feels practical, because the agent sees the secret at once and uses it without extra steps, and you save one motion.
It breaks on the fact that anything visible to the agent can travel further than you thought. A secret in a prompt lives in the session history and may travel to the model provider. A .env under Git leaves for the remote repository, into every clone and the reflog, from which one commit will not scrub it. A token in terminal output enters the session context and can surface in the agent's next answer. Convenience of access turns into uncontrolled spread across layers you no longer keep at hand. And the longer a secret lives in such a layer, the more copies of it manage to spread across clones, logs and caches.
The professional mechanism is a few rules, not one. Keep cloud credentials in the Cognition Secrets Manager or an approved secret store; pass local tokens through the environment or a local config, not through Git; close .env*, key material and credential paths with a deny rule; do not paste terminal output containing a token; after a leak revoke and rotate, do not merely delete the message.
A minimal deny set in permissions looks like the block below. It closes both reading and writing of .env, .pem files and SSH and AWS keys - two operations, not one, because forbidding reads is not enough if the agent can rewrite the file. It is not a request but a boundary the agent will not cross, regardless of what it was told in the prompt.
Why a deny rather than an instruction. An instruction not to read .env is influence on the model; a deny is enforcement by system means. The first can be bypassed by an injection or a hallucination, the second does not depend on what text the agent read. Hence a natural hierarchy of trust: the Secrets Manager is safer than an environment variable, a variable is safer than a line in the prompt, and a deny sits above all of them as the last line.
An important subtlety is to check what a glob actually applies to. A relative glob acts under the workspace, the home path is separate. The sandbox, the agent's direct tools and a remote environment may have different filesystem boundaries, and the same deny behaves differently across them. A Read(.env*) rule that closes the workspace root says nothing about ~/.aws or a .env in a nested directory unless it is explicitly extended there - and it is in those gaps that everything leaks.
The cost of a miss is not a deleted message but a live key in the wild. By the time you notice a leak the key may already have been used, so revoke and rotate are the only honest response: until the key is revoked it works, and deleting a line from the chat only hides the symptom. Treating a leaked secret like a fixed typo means leaving the door open and hanging a closed sign on it. Speed of response matters more than neatness here: better to revoke too much than to leave working what other eyes have already seen.
When each tool is justified. The Secrets Manager - for anything that outlives a session and is shared in a team. The environment - for the local and one-off. A deny on paths with secrets - always, as basic hygiene, regardless of trust in a particular task: it costs nothing to set up and closes a whole class of accidents that otherwise surface at the worst moment.
Verify the protection by behavior, not by memory. Ask the agent to read .env and confirm the deny fires with the layer named. Check that the glob covers the workspace, the home path and the remote layer if you work there. Scan the session and terminal history for accidentally pasted tokens. Verification is an attempt to reach a secret and the system's refusal, not confidence that the rule is written somewhere.
The typical failure is hiding a leak by deleting a message instead of rotating; writing an instruction instead of a deny; setting a deny under the workspace and forgetting the home path and the remote; pasting convenient terminal output with a token. The sign is the same: the secret is protected by words, not by a boundary. Move the protection into the Secrets Manager and a permission deny - and most leaks become impossible in principle rather than tracked after the fact.
{
"permissions": {
"deny": [
"Read(.env*)",
"Write(.env*)",
"Read(**/*.pem)",
"Write(**/*.pem)",
"Read(~/.ssh/**)",
"Read(~/.aws/**)"
]
}
}