shim: secrets reach any shimmed tool, and the tool is found through the agent's PATH #5
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The shim keeps secrets out of the agent's env and off disk, and the docs are honest that it is leak-prevention, not containment. This issue asks whether it can also be containment for one narrow case: a secret that only one trusted tool should ever hold.
The motivating case is runa running Home Assistant with a
runa-houseprofile. The HA token is admin-capable, and one rule is P0: never switch off the plugs that feed computers. The planned enforcement is that the model cannot reach HA at all except throughhass, a verb that refuses those entities. That only holds if the token cannot get out ofhass. Today it can, three ways.1. The real binary is resolved through the agent's own PATH
cmd/claudia-shim/main.gostrips the shim dir from$PATHand runsexec.LookPath(name)against the rest. The agent controls$PATHfor every command it runs:2. Every shimmed tool gets every secret
fetchSecrets(sock, name)sends the tool name for the audit record only, and the broker returns the whole map.gitandcurlare on the default shim list, so:3. The env passes through unscrubbed
hassis a Python script. With a pinned path and scoped secret it still loses:LD_PRELOADdoes the same to any shimmed ELF binary.Proposal
All three changes are opt-in, so nothing changes for a profile that does not use them.
claudia secret add HASS_TOKEN --tool hass(repeatable). The broker answers a scoped secret only to the tool names it is bound to. Unscoped secrets behave as today. The broker already authenticates the shim binary over the socket, so the tool name it is given is trustworthy as long as the shim derives it from a pinned path (below) rather than fromargv[0]alone.claudia config add shim hass=/home/agent/src/runa/bin/hass. The path is resolved outside the sandbox at launch and handed to the shim through the runtime dir, not the env. The shim execs that path and ignores$PATH. Launch refuses if the pinned file, or any directory above it, is writable under the session's grants, because a writable pinned path is no pin.LD_*,PYTHON*,PERL5*,RUBYOPT/RUBYLIB,NODE_OPTIONS,BASH_ENV/ENV. Run interpreters in isolated mode where the shebang allows it (python3 -I). A scrub list is a denylist and will miss something, so this is the weakest of the three. Executing the pinned tool with a minimal allowlisted env could be stronger, at the cost of tools that legitimately read env.Scoped secrets would be rejected for tools that are not pinned, so the combination is always the strong one.
What it still does not stop
A pinned tool that will hand out its own secret still does:
hassmust not have a verb that echoes the token or makes arbitrary requests. That is the tool author's job, and the issue is about making it the only remaining job.Tests
One test per bypass above, each shown to work against current
mainand to fail with the change: PATH shadowing, cross-tool secret delivery, andPYTHONPATH/LD_PRELOADinjection. Plus a launch-refusal test for a pinned path under a writable grant.