Skip to content

Env store and secrets

Terminal window
wfx env # the platform's env store; values are never shown
wfx env --project api # one project's layer
wfx env set GH_TOKEN # reads the value without echoing it, stores it encrypted
wfx env set LOG_LEVEL --plain # a non-secret value

Values are sealed with AES-256-GCM (internal/secrets). The key comes from WFX_SECRET_KEY, or the platform writes one on first boot. The package is explicit about what this protects against: someone reading the database, not someone who can run the platform process.

A step’s environment is assembled in layers: system, then project, then the workflow file’s env:. A value in the file can name a variable (${GITHUB_PAT}) instead of holding it.

internal/engine/redact.go starts with the rule: secret values never reach the event log. It enforces the rule in two layers:

  1. A secret is never written into a command. It goes into a 0600 file in the run’s own directory, and the command sources that file by path, so the path is all a tool call records.
  2. Every event is scrubbed before it is stored. Tool calls, tool output, a run: step’s stdout and the model’s own text are all checked for every sensitive value of the run, in its raw, base64 and JSON-escaped forms. An agent that runs env is caught too.

“Sensitive” covers every value in the env store, plus any value under a credential-shaped name from any layer. Values shorter than 6 characters are not redacted, because replacing every true in a log would destroy the log and protect nothing.

When the server boots, config.ScrubServerEnv removes every configuration variable and the secrets key from its own process environment. That list includes WFX_RUNNER_TOKEN, DATABASE_URL, the S3 keys, WFX_DEFAULT_PROVIDER and WFX_ADDR. The comment at the call site in apps/api/main.go says why: nothing a run starts should inherit the server’s own configuration.