Skip to content

feat(agent): add [config_env] for non-sensitive agent environment - #73

Merged
radim10 merged 11 commits into
masterfrom
feat/agent-config-env
Oct 12, 2026
Merged

radim10 merged 11 commits into
masterfrom
feat/agent-config-env

Conversation

@radim10

@radim10 radim10 commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Summary

Agent profiles can now set plaintext, non-sensitive config for the sandboxed agent with a [config_env] table. Before this, the Docker backend had no way to set any variables (the container starts with an empty environment), and the native backend only had whatever happened to be in the user's shell.

[config_env]
NODE_ENV = "development"
PORT = 3000
BUILD_HASH = { value = "9f86d081…", not_secret = true }
  • Values can be strings, numbers or booleans; the agent always receives a string.
  • --config-env NAME=VALUE on agent run sets or overrides a value for one run.
  • Profile values take precedence over the inherited shell env; anything the sandbox sets always wins.

Guardrails

  • Reserved names are rejected: proxy and CA vars, HOME, TMPDIR, FORCE_COLOR, STASHBASE_*, and PATH / LD_* / DYLD_*. The last group matters: [config_env] is applied to the native launcher (bwrap, systemd-run) before confinement, and the launcher is found through the child's PATH, so a repository profile could otherwise run its own code outside the sandbox. Reserved names are also skipped when building the child env, as a backstop.
  • No shadowing bindings: a name a [secrets] / [personal_credentials] binding provides (its env, or a renamed from) is rejected, case-insensitively.
  • Size limits: 64 KiB per NAME=value, 256 KiB total; NUL bytes rejected.
  • Credential check: values that look like credentials (credential-like name, known token prefix, URL with a password, high-entropy string) warn in agent validate; agent run asks for confirmation and fails when it can't ask (non-interactive or --silent). Applies to --config-env values too. not_secret = true acknowledges a false positive. Values are never printed, and agent profiles show displays flagged values as <hidden: looks like a credential>.
  • Audit: the session_started event records config_env_names (names only).

Also: a commented [config_env] example in the agent init template, docs in docs/agent-profiles.md, a short README section, and an example profile at docs/agent-profiles/examples/config-env.toml.

Testing

  • cargo test: all pass (615 unit + integration suites), with new tests for detection, validation (reserved/invalid/conflicting names, limits, NUL), value parsing, the flag parser, env merging, audit field, masking and the init template.
  • Manual, native backend on macOS: validate warnings, non-interactive fail-closed, not_secret acknowledgement, values reaching the agent, HTTPS_PROXY not overridable, PATH/LD_PRELOAD rejected, --config-env (incl. values containing =), audit event contents, masked profiles show (TOML and JSON).

Profiles can now set plaintext config variables for the sandboxed agent.
Both backends apply them; the Docker backend previously had no way to set
any. Values may be strings, numbers or booleans.

Names the sandbox owns (proxy/CA vars, HOME, TMPDIR, FORCE_COLOR,
STASHBASE_*) or that a [secrets]/[personal_credentials] binding provides
are rejected. Values that look like credentials (name, known token
prefix, URL password, high entropy) warn in `agent validate`, and
`agent run` asks to confirm them, failing when it can't ask. A value is
acknowledged with `{ value = "...", not_secret = true }`.
Each NAME=value may be up to 64 KiB and the whole table up to 256 KiB,
well within the spawn limits (128 KiB per string on Linux, ~1 MB for
arguments and environment on macOS). NUL bytes can't be held by an
environment variable and are rejected with a clear error. Errors name
the variable and size, never the value.
config_env is set on the native launcher (bwrap, systemd-run) before any
confinement exists, and the launcher is found through the child's PATH.
A repository profile setting PATH or LD_PRELOAD could therefore run its
own code outside the sandbox. Reject those names in validation, and skip
reserved names when building the child env as a backstop.
Sets or overrides a [config_env] variable for one run. Values go through the same name, size and reserved-name validation as the profile's; the credential check is skipped since the person running the agent typed them.
Windows treats environment variable names case-insensitively, so github_token in [config_env] would shadow a binding exposed as GITHUB_TOKEN.
Runs that differ only in [config_env] (or --config-env) can now be told apart in the audit log. Only names are recorded, never values.
Flag values reach the agent in plaintext like the profile's, so they get the same confirm-or-fail check.
…es show

Flagged values without not_secret = true are shown as <hidden: looks like a credential> in both TOML and JSON output.
@radim10 radim10 self-assigned this Oct 12, 2026
@radim10
radim10 merged commit edf59ee into master Oct 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant