How It Works
Whenenvironment.allow_vars is set in a profile, nono:
- Clears the inherited environment
- Passes through only variables matching the allow-list
- Adds back nono-injected credentials (from
env_credentials) on top
environment section is omitted entirely, all variables are passed through (backward compatible). Setting allow_vars to an empty array [] restricts the environment to only nono-injected credentials — no inherited variables are passed.
Configuration
Add theenvironment section to your profile:
Prefix Patterns
Use a trailing* to match all variables with a given prefix:
AWS_REGION, AWS_SECRET_ACCESS_KEY, and any variable starting with MYAPP_, while blocking everything else.
A bare "*" matches all variables (equivalent to not setting the environment section at all). The * wildcard is only valid as a trailing suffix — patterns like "A*B" or "*X" are rejected at profile load time.
Inheritance
allow_vars is additive across profile inheritance. A child profile appends its entries to the base profile’s list, and duplicates are removed:
Interaction with Credential Injection
Variables injected by nono — viaenv_credentials or --env-credential — always bypass the allow-list. They are explicitly configured by the user and must reach the child process regardless of filtering rules.
OPENAI_API_KEY is passed through even though it’s not in allow_vars, because it was explicitly injected via env_credentials.
Operator-configured deny-list
Usedeny_vars to strip specific variables while keeping everything else inherited — without having to enumerate an explicit allow-list:
allow_vars — only trailing * is supported:
GITHUB_TOKEN, GITHUB_ACTIONS, any var starting with ANTHROPIC_ or OPENAI_, etc. Patterns like *_TOKEN (leading wildcard) are not supported — nono will print a warning and ignore them.
Precedence: deny_vars wins over allow_vars. If a variable appears in both, it is stripped:
AWS_REGION passes through; AWS_SECRET_ACCESS_KEY is stripped.
Inheritance: like allow_vars, deny_vars is additive across profile inheritance — a child profile appends to the base’s list, and duplicates are removed.
Setting static variables
Useset_vars to inject environment variables with specific values into the sandboxed process. This is the inverse of filtering: instead of controlling which inherited variables pass through, you define explicit values.
set_vars is applied after allow/deny filtering and before credential injection. If a key in set_vars collides with a variable injected via env_credentials, the injected credential wins. A set_vars value overrides any inherited value with the same name.
Variable expansion: values support the same expansion as profile paths — $HOME, ~, $WORKDIR, $TMPDIR, $UID, $XDG_CONFIG_HOME, $XDG_DATA_HOME, $XDG_STATE_HOME, $XDG_CACHE_HOME, $XDG_RUNTIME_DIR, $NONO_CONFIG, and $NONO_PACKAGES. When XDG_CONFIG_HOME is unset — typical on macOS — $XDG_CONFIG_HOME expands to $HOME/.config, so "$XDG_CONFIG_HOME/nono" is the same as ~/.config/nono. Keys are never expanded.
Reserved keys: PATH and any key starting with NONO_ are reserved and rejected at profile load time (PATH is controlled via allow_vars/deny_vars; the NONO_* prefix is reserved for nono’s own injected variables). Keys must be valid environment variable names ([A-Za-z_][A-Za-z0-9_]*).
Unlike inherited host variables,
set_vars keys are not subject to the built-in dangerous-variable blocklist. Setting LD_PRELOAD, NODE_OPTIONS, or similar via set_vars is allowed — it is an explicit, auditable operator decision in the profile, not injection from an untrusted parent shell. Use this deliberately.set_vars merges across profile inheritance like a map — a child profile’s entries are added to the base’s, and on key conflict the child’s value wins.
Interaction with the Built-in Deny-List
nono maintains a built-in deny-list of dangerous environment variables (e.g.,LD_PRELOAD, DYLD_INSERT_LIBRARIES, PYTHONPATH, NODE_OPTIONS). These variables are always blocked, even if they appear in allow_vars. This prevents a compromised profile from disabling sandbox protections.
LD_PRELOAD will not be passed through, despite being in the allow-list.
Security Properties
- Default-allow: Without the
environmentsection, all variables are passed through (no regression) - Empty allow-list restricts all:
"allow_vars": []passes zero inherited variables — only nono-injected credentials reach the child - Explicit allow-list: When
allow_varshas entries, only matching variables reach the child process - Operator deny-list:
deny_varsstrips named variables even whenallow_varswould otherwise pass them through - Static values via
set_vars: explicit variables injected after filtering and before credentials;PATHandNONO_*are reserved, but the dangerous-variable blocklist does not apply (explicit operator intent) - Injected credentials bypass both lists:
env_credentialsvariables always pass through, regardless ofallow_varsordeny_vars - Built-in deny-list is non-overridable: Dangerous variables like
LD_PRELOADare always blocked and cannot be re-allowed - Precedence: built-in blocklist >
deny_vars>allow_vars - Prefix patterns reduce misconfiguration: Only
*suffix is supported (no regex), reducing risk of accidental over-permission - Bare
*matches everything: Use as an escape hatch, but prefer explicit lists
Example: Minimal Agent Environment
A typical profile for an AI agent that only needs basic shell environment and cloud credentials:AWS_* variables and the injected OPENAI_API_KEY, but no other secrets accidentally present in the parent environment.
Next: Credential Injection | Profile Authoring