Skip to content

Commit ae078a7

Browse files
dogzzdogzzclaude
andcommitted
feat(agent): three-axis env inheritance via [agent.clear_env]
Replaces the flat [agent].inherit_env allow-list with a structured [agent.clear_env] table that supports both allow-list and deny-list filtering plus an enabled toggle. Decision tree: if enabled (default true): if allow_list non-empty -> only those keys pass through elif deny_list non-empty -> all process env passes EXCEPT deny_list else -> nothing inherited (pure secure default) else: full process env inherited; both lists ignored (escape hatch) Use case: AWS-IRSA / web-identity workloads where k8s auto-injects many AWS_* env vars. Listing every benign one in an allow-list is brittle; deny_list = ["DISCORD_BOT_TOKEN", ...] is a much better fit. Helm values structure: agents.<name>.clearEnv: enabled: true allowList: [] denyList: [] BREAKING CHANGE (beta): agents.<name>.inheritEnv is removed. Migration: inheritEnv: ["A", "B"] -> clearEnv.allowList: ["A", "B"] The helm template hard-fails with a migration message if the legacy key is encountered. TOML config users: rename `inherit_env = [...]` to `[agent.clear_env]\nallow_list = [...]`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1fd36df commit ae078a7

6 files changed

Lines changed: 296 additions & 48 deletions

File tree

charts/openab/templates/configmap.yaml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,23 @@ data:
106106
{{- if $cfg.env }}
107107
env = { {{ $first := true }}{{ range $k, $v := $cfg.env }}{{ if not $first }}, {{ end }}{{ $k }} = {{ $v | toJson }}{{ $first = false }}{{ end }} }
108108
{{- end }}
109-
{{- if $cfg.inheritEnv }}
110-
inherit_env = {{ $cfg.inheritEnv | toJson }}
109+
{{- if hasKey $cfg "inheritEnv" }}
110+
{{- fail (printf "agents.%s.inheritEnv was removed -- use agents.%s.clearEnv.allowList instead (BREAKING in beta; see CHANGELOG)" $name $name) }}
111+
{{- end }}
112+
{{- $clearEnv := $cfg.clearEnv | default dict }}
113+
{{- $clearEnvDisabled := and (hasKey $clearEnv "enabled") (not $clearEnv.enabled) }}
114+
{{- if or $clearEnvDisabled $clearEnv.allowList $clearEnv.denyList }}
115+
116+
[agent.clear_env]
117+
{{- if $clearEnvDisabled }}
118+
enabled = false
119+
{{- end }}
120+
{{- if $clearEnv.allowList }}
121+
allow_list = {{ $clearEnv.allowList | toJson }}
122+
{{- end }}
123+
{{- if $clearEnv.denyList }}
124+
deny_list = {{ $clearEnv.denyList | toJson }}
125+
{{- end }}
111126
{{- end }}
112127
113128
[pool]

charts/openab/tests/configmap_test.yaml

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,45 @@ tests:
143143
path: data["config.toml"]
144144
pattern: 'max_bot_turns = 30'
145145

146-
- it: renders inherit_env as TOML array
146+
- it: renders clear_env.allow_list as TOML array
147147
set:
148-
agents.kiro.inheritEnv:
148+
agents.kiro.clearEnv.allowList:
149149
- "API_BASE_URL"
150150
- "MODEL_NAME"
151151
asserts:
152152
- matchRegex:
153153
path: data["config.toml"]
154-
pattern: 'inherit_env = \["API_BASE_URL","MODEL_NAME"\]'
154+
pattern: '\[agent\.clear_env\]'
155+
- matchRegex:
156+
path: data["config.toml"]
157+
pattern: 'allow_list = \["API_BASE_URL","MODEL_NAME"\]'
158+
159+
- it: renders clear_env.enabled = false when disabled
160+
set:
161+
agents.kiro.clearEnv.enabled: false
162+
agents.kiro.clearEnv.denyList:
163+
- "DISCORD_BOT_TOKEN"
164+
asserts:
165+
- matchRegex:
166+
path: data["config.toml"]
167+
pattern: '\[agent\.clear_env\]'
168+
- matchRegex:
169+
path: data["config.toml"]
170+
pattern: 'enabled = false'
171+
- matchRegex:
172+
path: data["config.toml"]
173+
pattern: 'deny_list = \["DISCORD_BOT_TOKEN"\]'
155174

156-
- it: does not render inherit_env when unset
175+
- it: does not render clear_env section when unset
157176
asserts:
158177
- notMatchRegex:
159178
path: data["config.toml"]
160-
pattern: 'inherit_env'
179+
pattern: '\[agent\.clear_env\]'
180+
181+
- it: fails with helpful message when legacy inheritEnv is used
182+
set:
183+
agents.kiro.inheritEnv:
184+
- "API_BASE_URL"
185+
asserts:
186+
- failedTemplate:
187+
errorPattern: 'inheritEnv was removed'

config.toml.example

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,39 @@ working_dir = "/home/agent"
6060
# Note: env vars here can override baseline vars (HOME, PATH, USER) if needed.
6161
# env = { ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}" }
6262
#
63-
# By default, the agent subprocess only inherits these baseline vars:
64-
# Linux/macOS: HOME, PATH, USER
65-
# Windows: USERPROFILE, USERNAME, PATH, SystemRoot, SystemDrive
63+
# Env inheritance from the OAB process is controlled by the [agent.clear_env]
64+
# table. The default is secure: the subprocess starts with env_clear() and
65+
# only receives the baseline (HOME/PATH/USER on Linux/macOS,
66+
# USERPROFILE/USERNAME/PATH/SystemRoot/SystemDrive on Windows) plus
67+
# everything in [agent].env above.
6668
#
67-
# To pass additional env vars from the OAB process (e.g. vars injected via K8s envFrom),
68-
# list them in inherit_env. Keys in [agent].env take precedence over inherited ones.
69-
# inherit_env = ["API_BASE_URL", "MODEL_NAME"]
69+
# Decision tree (when [agent.clear_env] is set):
70+
# if enabled (default true):
71+
# if allow_list non-empty → only those keys pass through from process env
72+
# elif deny_list non-empty → all process env passes through EXCEPT deny_list
73+
# else → nothing inherited (pure secure default)
74+
# else (enabled = false):
75+
# full process env inherited; both lists ignored (pure escape hatch)
76+
#
77+
# allow_list takes priority over deny_list when both are set under enabled=true.
78+
# [agent].env always wins on key conflict (highest precedence).
79+
#
80+
# Example: allow-list mode — explicitly pass a small set of keys.
81+
# [agent.clear_env]
82+
# allow_list = ["API_BASE_URL", "MODEL_NAME"]
83+
#
84+
# Example: deny-list mode for AWS-IRSA / web-identity workloads. K8s auto-
85+
# injects many AWS_* env vars (AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE, ...);
86+
# listing every benign one in allow_list is brittle. Inherit everything and
87+
# strip known secrets:
88+
# [agent.clear_env]
89+
# deny_list = ["DISCORD_BOT_TOKEN", "SLACK_BOT_TOKEN", "ANTHROPIC_API_KEY"]
90+
#
91+
# Example: pure escape hatch — disable filtering entirely (NOT recommended,
92+
# every secret in the OAB env is exposed to the agent and exfil-able via
93+
# prompt injection).
94+
# [agent.clear_env]
95+
# enabled = false
7096

7197
# [agent]
7298
# command = "codex"

0 commit comments

Comments
 (0)