Harness runtime files

How an agent harness gets its config/auth files (e.g. ~/.codex/config.toml, ~/.claude/...) into the sandbox without putting secrets on the wire.

Code: swarm/src/sandbox.py (render_runtime_files, _stage_home, _safe_rel_path), app/executors/swarm.py::prefill_model_in_files.

The problem

Each agent CLI wants some files in $HOME to know its model + how to reach the API. Those files often reference an API key. We must not ship the key through pond → orchestrator → worker in clear, and the files must land inside the sandbox’s $HOME, not the worker’s real home.

Templating + the two fill points

A harness declares runtime files as {path, content} templates with three placeholders, filled at different trust points so no secret crosses the wire:

PlaceholderFilled byWhen
{{MODEL}}pond (dispatch)prefill_model_in_files — non-secret, backend-known
{{BROKER_URL}}workerat launch — the per-job broker address
{{SECRET:NAME}}workerat launch — from the unsealed credential env

So the templates that travel are secret-free; the worker fills {{BROKER_URL}} and {{SECRET:NAME}} locally after unsealing the credential (see model-credentials).

Materialization

render_runtime_files fills the placeholders and flags a file is_secret when it consumed a {{SECRET:...}}. _stage_home writes them into a fresh per-job $HOME (a temp dir the provider mounts at the sandbox $HOME), removed on every exit path. Secret-bearing files are written 0600.

Preferred pattern is {{BROKER_URL}} + a dummy key, not {{SECRET:NAME}}: under a brokered profile the real key lives only in the broker sidecar, so a materialized real secret is redundant — _stage_home logs a warning when it sees one on a brokered profile.

Path safety

_safe_rel_path rejects any runtime-file path that is absolute, starts with ~, or contains a .. segment; _stage_home additionally resolves the final path and refuses anything that escapes the staged home. A harness template can never write outside the per-job $HOME.

Invariants

  • Templates on the wire never contain secrets; {{SECRET}}/{{BROKER_URL}} are worker-local fills.
  • Runtime files land only in a disposable per-job $HOME, removed after the run.
  • Secret-bearing files are 0600; the broker-redundant case is flagged.
  • No runtime-file path can escape $HOME.