7.4 KiB
PR#166: The values of a build's variables no longer stand on the command line of werkdock and docker
Version: patch
WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
Problem
Werkator passes each variable of a sandboxed build as -e KEY=VALUE to werkdock run,
and as --env KEY=VALUE to docker run.
So every secret of a build stands in the argv of that process, e.g. the tokens of the ai-review build of werkrevisor.
Each process that can read /proc/<pid>/cmdline sees them, and so does each ps, crash report or log of an argv.
On mih09 on 2026-10-20 they leaked from pgrep -af into a transcript.
Non-Goals
- No change of what a build sees: the same variables with the same values, the same precedence of
werkdock.env/docker.env. - No change of
bwrap's command line; werkdock passes the values on asbwrap --setenvup to 0.13.1, and werkdock PR#17 ends that. - No rotation of the leaked secrets; that is the human's.
Specification
Feature: a build's variables reach the sandbox off the command line
Background
- werkdock takes a bare
-e KEYfrom its own environment and omits the variable when that has none (since 0.2.0). - docker reads
--env-file: oneKEY=VALUEper line, before the--envoperands, a later entry winning.
Scenario#166.01: the werkdock command line names a build's variables, werkdock's environment holds their values
… so that no ps and no log of an argv shows a secret of a build.
- Given a build with a token and a whole configuration file in
werkdock.env- and a server with a secret of its own in its environment
- When Werkator starts the build
- Then the argv of
werkdock runnames each variable as a bare-e KEY, and holds none of the values- and werkdock's environment holds the values, and of the server's environment only what werkdock reads itself
Verified by
Scenario#166.02: a variable that steers werkdock itself stays on the command line
… so that a build cannot change how werkdock runs outside the sandbox.
- Given a build that sets
PATH,WERKDOCK_HOMEandLD_PRELOADinwerkdock.env - When Werkator starts the build
- Then the command line holds each as
-e KEY=VALUE, as before- and werkdock runs with the server's values of these three
Verified by
Scenario#166.03: the build still sees the values
… so that a build that needs its secrets keeps working.
- Given a build with a key and an empty value in
werkdock.env - When Werkator starts the build
- Then the command in the sandbox sees both values
- and werkdock sees none of the server's own secrets
Verified by
Scenario#166.04: a Docker build's values reach the container through a file only the server's account reads
… so that neither ps nor a program the docker client starts on the host sees them.
- Given a build with a token in
docker.env - When Werkator starts the build
- Then the command line of
docker runholds no value of the build- and only the server's account reads the file that holds them, and only until the build ends
- and a value that docker's file format cannot hold stays on the command line, as before
Verified by
Solution
- werkdock:
RuntimeEnvironmentsplits a build's variables into the-eoperands and the environment ofwerkdock run, whichWerkdockBuildRunnerstarts with exactly that environment, cleared first. It holds the server's values of werkdock's own names, then the build's values; before, werkdock inherited all of the server's environment. - werkdock's own names: what werkdock, the Go runtime or glibc reads, e.g.
PATH,HOME,WERKDOCK_HOME,LD_PRELOAD,GCONV_PATH; the full list is indocs/configuration.md. A build variable of such a name keepsKEY=VALUEon the command line, as before. In werkdock's environment it would steer werkdock: a branch could choose thebwrapit runs, its image store, or a library loaded into a process outside the sandbox. A name with=or an empty name stays on the command line, since no environment can hold it. - The environment route is safe for werkdock alone:
werkdock runstarts no host program but itself andbwrap, and werkdock PR#18 startsbwrapwith an empty environment. - Docker:
DockerEnvFilewrites the variables, after the container defaultsHOMEandGRADLE_USER_HOME, to a0600file in.git/werkator/docker-env/(0700), which the build container sees masked. The file goes when the client ends; a file older than an hour, left by a killed Werkator, goes with the next Docker build. The docker client keeps Werkator's environment, as before, and gets no build value in it. - Why not the environment for Docker too: the Codex review found that the docker client starts host programs with it,
sshfor anssh://daemon (SSH_ASKPASS) and credential helpers such aspass(BASH_ENV). A list of forbidden names never covers every helper; the human chose the file (2026-10-20). - docker's file format holds one line per variable, shorter than 64 KiB:
a value with a line break, a longer line, or a name docker would misread
stays
--env KEY=VALUEon the command line, after the file, as before. SecretFiles.createDirectoriesOwnerOnlytakes a directory that another thread created in the meantime, so two Docker builds that start together both get their file (review of the Codex agent).- Red/green: with
KEY=VALUEoperands back, the tests of Scenario#166.01 fail. - Werkator and werkdock can be rolled out in either order; the leak ends with both.
- The native runner already puts the variables into the build's environment, and the follow-up builds run through the same runners.
- Version 1.43.6 with a release-notes entry.
Open Questions
- Does anything else of Werkator put a build's value on a command line?
No: the image builds,
werkdock images/importandcurlcarry no build variable.
Additional Changes
docs/configuration.md, the architecture skill anddocs/werkator.werkbaumdescribe the change.
Prerequisite PRs
- None; werkdock has taken a bare
-e KEYsince 0.2.0.
Follow-up PRs
- werkdock PR#17: bwrap reads the sandbox's environment from a pipe, not from its command line; an instance's files are readable by the owner only.
- werkdock PR#18: bwrap starts with an empty environment.