What version of Codex CLI is running?
0.128.0
What subscription do you have?
Pro
Which model were you using?
gpt-5.5
What platform is your computer?
Darwin 25.4.0 arm64 unknown
What terminal emulator and version are you using (if applicable)?
Ghostty
What issue are you seeing?
The command: TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z is explicitly allowed by my active execpolicy rules when checked as the intended policy shape: ["TZ=America/Sao_Paulo", "date", "+%Y%m%dT%H%M%S%z"]
The policy helper returns:
decision: allow
matchedPrefix: ["TZ=America/Sao_Paulo", "date"]
justification: "Timezone-specific date inspection is allowed."
However, during actual Codex execution, the command is submitted/rejected as a shell command-string launch: /bin/zsh -lc 'TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z' or, with login=false: /bin/zsh -c 'TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z'
That launch shape correctly matches my shell command-string forbid rule:
pattern = [SHELLS, ["-c", "-lc"]]
decision = "forbidden"
justification = "Do not use shell command-string execution. If it becomes necessary to continue the task right now, stop and ask the user to run the exact command manually. Otherwise finish all other work first and present the command at the end."
So the local policy is internally consistent:
-
direct timezone-prefixed date shape is allowed
-
broad env wrapper is forbidden
-
shell command-string execution is forbidden
The regression is that Codex/model/tool-call emission is now routing a previously working allowed command through a forbidden shell-wrapper shape. This was working for days using the exact literal command TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z and other allowed timezone prefixes, with no local rule/config/workflow changes.
What steps can reproduce the bug?
Uploaded thread: 019e0360-0c68-75a1-8888-b1844e63bc51
It's reproducible on both codex-cli and codex-app.
Additional reproducible steps:
~/.codex/rules/default.rules:
SHELLS = [
"zsh",
"/bin/zsh",
"/usr/bin/zsh",
"bash",
"/bin/bash",
"/usr/bin/bash",
"sh",
"/bin/sh",
"/usr/bin/sh",
"dash",
"/bin/dash",
"/usr/bin/dash",
"ash",
"/bin/ash",
"/usr/bin/ash",
"ksh",
"/bin/ksh",
"/usr/bin/ksh",
"fish",
"/bin/fish",
"/usr/bin/fish",
]
# Block shell command-string execution.
prefix_rule(
pattern = [SHELLS, ["-c", "-lc"]],
decision = "forbidden",
justification = "Do not use shell command-string execution. If it becomes necessary to continue the task right now, stop and ask the user to run the exact command manually. Otherwise finish all other work first and present the command at the end.",
match = [
"/bin/zsh -lc rg -n TODO",
"bash -lc git status",
"/bin/sh -c pwd",
"zsh -c pwd",
"/bin/zsh -lc TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z",
],
)
# Allowed
prefix_rule(
pattern = [[
"TZ=America/Sao_Paulo",
"TZ=UTC",
"TZ=Etc/UTC",
"TZ=America/New_York",
"TZ=America/Chicago",
"TZ=America/Denver",
"TZ=America/Los_Angeles",
"TZ=America/Toronto",
"TZ=America/Vancouver",
"TZ=Europe/London",
"TZ=Europe/Berlin",
"TZ=Europe/Paris",
"TZ=Asia/Tokyo",
"TZ=Asia/Shanghai",
"TZ=Asia/Kolkata",
"TZ=Australia/Sydney",
], "date"],
decision = "allow",
justification = "Timezone-specific date inspection is allowed.",
match = [
"TZ=America/Sao_Paulo date",
"TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z",
"TZ=UTC date",
"TZ=America/New_York date",
"TZ=America/Toronto date",
"TZ=America/Vancouver date",
"TZ=Europe/London date",
"TZ=Asia/Tokyo date",
],
)
Validating rules:
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- /bin/zsh -lc TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z
Result
{
"matchedRules": [
{
"prefixRuleMatch": {
"matchedPrefix": [
"/bin/zsh",
"-lc"
],
"decision": "forbidden",
"justification": "Do not use shell command-string execution. If it becomes necessary to continue the task right now, stop and ask the user to run the exact command manually. Otherwise finish all other work first and present the command at the end."
}
}
],
"decision": "forbidden"
}
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z
Result
{
"matchedRules": [
{
"prefixRuleMatch": {
"matchedPrefix": [
"TZ=America/Sao_Paulo",
"date"
],
"decision": "allow",
"justification": "Timezone-specific date inspection is allowed."
}
}
],
"decision": "allow"
}
What is the expected behavior?
Codex should not route this simple allowed command through /bin/zsh -lc or /bin/zsh -c when shell command-string execution is forbidden by policy; it could also use the policy forbidden justification as feedback to the model. It should either:
-
preserve a direct policy-visible command shape, or
-
expose/use a true direct argv + env execution API, e.g.
argv=["date", ["+%Y%m%dT%H%M%S%z"]], env=[{"TZ":["America/Sao_Paulo"]}], or
-
avoid emitting inline env assignment when the active policy forbids shell wrappers.
Additional information
Important:
I am not requesting that Codex weaken or bypass the shell-wrapper forbid rule. The report is that the command emission/normalization changed and now violates the active policy boundary.
Versions:
-
codex-cli: v0.128.0
-
codex-app: v6.429.61741 (2429)
-
shell: zsh
-
first observed: 2026-04-29
-
returned working as expected: 2026-05-03
-
confirmed unexpected behavior again: 2026-05-07
Related issue class:
This resembles the known prefix_rule/shell-wrapper/env-prefix behavior class where env-prefix commands and /bin/zsh -lc wrapping cause policy matching to apply to the wrapper instead of the intended command.
What version of Codex CLI is running?
0.128.0
What subscription do you have?
Pro
Which model were you using?
gpt-5.5
What platform is your computer?
Darwin 25.4.0 arm64 unknown
What terminal emulator and version are you using (if applicable)?
Ghostty
What issue are you seeing?
The command:
TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%zis explicitly allowed by my active execpolicy rules when checked as the intended policy shape:["TZ=America/Sao_Paulo", "date", "+%Y%m%dT%H%M%S%z"]The policy helper returns:
However, during actual Codex execution, the command is submitted/rejected as a shell command-string launch:
/bin/zsh -lc 'TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z'or, with login=false:/bin/zsh -c 'TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%z'That launch shape correctly matches my shell command-string forbid rule:
So the local policy is internally consistent:
direct timezone-prefixed date shape is allowed
broad env wrapper is forbidden
shell command-string execution is forbidden
The regression is that Codex/model/tool-call emission is now routing a previously working allowed command through a forbidden shell-wrapper shape. This was working for days using the exact literal command
TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%zand other allowed timezone prefixes, with no local rule/config/workflow changes.What steps can reproduce the bug?
Uploaded thread: 019e0360-0c68-75a1-8888-b1844e63bc51
It's reproducible on both codex-cli and codex-app.
Additional reproducible steps:
~/.codex/rules/default.rules:Validating rules:
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- /bin/zsh -lc TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%zResult
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- TZ=America/Sao_Paulo date +%Y%m%dT%H%M%S%zResult
What is the expected behavior?
Codex should not route this simple allowed command through
/bin/zsh -lcor/bin/zsh -cwhen shell command-string execution is forbidden by policy; it could also use the policy forbidden justification as feedback to the model. It should either:preserve a direct policy-visible command shape, or
expose/use a true direct argv + env execution API, e.g.
argv=["date", ["+%Y%m%dT%H%M%S%z"]], env=[{"TZ":["America/Sao_Paulo"]}], oravoid emitting inline env assignment when the active policy forbids shell wrappers.
Additional information
Important:
I am not requesting that Codex weaken or bypass the shell-wrapper forbid rule. The report is that the command emission/normalization changed and now violates the active policy boundary.
Versions:
codex-cli: v0.128.0
codex-app: v6.429.61741 (2429)
shell: zsh
first observed: 2026-04-29
returned working as expected: 2026-05-03
confirmed unexpected behavior again: 2026-05-07
Related issue class:
This resembles the known prefix_rule/shell-wrapper/env-prefix behavior class where env-prefix commands and
/bin/zsh -lcwrapping cause policy matching to apply to the wrapper instead of the intended command.