Worker secrets handling — the contract
Class: security guardrail · Audience: any worker/agent session that touches a credential ·
Authoritative internals: worker-tmp-secret-hygiene.md
This is the short, worker-facing contract. For the incident, the full guardrail set, and the
runtime/CI internals, read worker-tmp-secret-hygiene.md.
The rules
-
Never write a secret value to a file you then read back. No
/tmp/wenv.sh, nosops -d … > /tmp/x.env; source /tmp/x.env. That is the #7724 leak class and the #5078 execute-the-env class. Thelint-worker-tmp-secretsCI check blocks it from reaching the repo; the hourlyTmpSecretScratchExposedalert catches a runtime relapse. -
Extract one key to stdout, use it, unset it — via
scripts/lib/extract_env_key.sh, which writes the value to stdout only (never a file) and matches^KEY=exactly (collision-proof, #3494):source /opt/p24-infra/scripts/lib/extract_env_key.sh TOKEN=$(extract_env_key CF_API_TOKEN "$ENV_FILE"); some-cmd --token "$TOKEN"; unset TOKEN # straight from a SOPS stream, nothing lands on disk: TOKEN=$(sops -d --input-type dotenv --output-type dotenv secrets/x.env.sops \ | extract_env_key_stdin CF_API_TOKEN) || exit 1 -
If you genuinely need a temp file, use the private
TMPDIRand self-clean. Workers launched byscripts/spawn-worker.shrun with an owner-only0700per-workerTMPDIRalready set (#7813), somktempdefaults into an un-listable private dir. Still make it owner-only and self-cleaning:TMP=$(mktemp); chmod 600 "$TMP"; trap 'rm -f "$TMP"' EXITumask 077is set before launch, so new files are0600even if you forget — but do not rely on it as the only line of defence. -
Never display a secret value in chat, a GitHub comment, a commit, a log, or a subagent prompt. Reference the key NAME only. This is the global
CLAUDE.md§Secrets ABSOLUTE rule.
The per-worker TMPDIR contract (#7813)
spawn-worker.sh exports TMPDIR=$(mktemp -d …/p24-worker-<issue>-XXXXXX) at 0700 and reaps it
when the worker exits. You inherit it automatically — you do not create or remove it. Do not
hard-code /tmp/... paths for scratch that could hold a secret: let mktemp/tempfile honour
TMPDIR so the scratch stays inside the private subtree. Full mechanics (why cleanup is colocated
with the $WORKDIR teardown rather than a parent trap … EXIT):
worker-tmp-secret-hygiene.md §Guardrail 4.
Related
worker-tmp-secret-hygiene.md— incident #7724 + all four guardrailsenv-key-extraction-safety.md— theextract_env_key.shprimitive (#3494)static-api-key-incident-rotation.md— rotation once a value leaks- Global
CLAUDE.md§Secrets — the ABSOLUTE no-secret-in-output rule