codex TUI on Linux not honouring shell_environment_policy

Open 💬 4 comments Opened May 11, 2026 by aussielunix
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

codex-cli 0.130.0 installed via homebrew

What subscription do you have?

pro

Which model were you using?

gpt-5.5

What platform is your computer?

Linux 6.19.14-300.fc44.x86_64 x86_64 unknown

What terminal emulator and version are you using (if applicable)?

terminator 2.1.5 running bash and no tmux/screen

What issue are you seeing?

The codex TUI on Linux appears to not be honoring a strict shell_environment_policy

TUI tool execution should see only PATH, HOME, and MY_FLAG; actual behavior: it sees the full parent user environment.

What steps can reproduce the bug?

I have the following in ~/.codex/config.toml

approval_policy = "on-request"
sandbox_mode = "read-only"
web_search = "disabled"
allow_login_shell = false

[shell_environment_policy]
inherit = "none"
set = { PATH = "/usr/bin", MY_FLAG = "1" }
ignore_default_excludes = false
exclude = ["AWS_*", "AZURE_*", "HOMEBREW*"]
include_only = ["PATH", "HOME", "MY_FLAG"]

When I run the following all of my user's environment variables are visible which is not what I expected.

lunix@astro]  -> codex
codex prompt> env | sort
• Ran env | sort
  └ CODEX_CI=1
    CODEX_SANDBOX_NETWORK_DISABLED=1
    … +30 lines (ctrl + t to view transcript)
    XDG_DATA_DIRS=/var/home/lunix/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
    _=/usr/bin/env

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

• CODEX_CI=1
  CODEX_SANDBOX_NETWORK_DISABLED=1
  CODEX_THREAD_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx
  COLORTERM=
  EDITOR=vim
  GH_PAGER=cat
  GIT_PAGER=cat
  HISTSIZE=5000
  HOME=/var/home/lunix
  HOMEBREW_BUNDLE_FILE=/var/home/lunix/Brewfile
  HOMEBREW_NO_ANALYTICS=1
  HOMEBREW_NO_AUTO_UPDATE=1
  LANG=C.UTF-8
  LC_CTYPE=C.UTF-8
  LESS=-R
  LESSOPEN=||/usr/bin/lesspipe.sh %s
  NO_COLOR=1
  PAGER=cat
  PATH=xxxxxxx<trimmed>xxxxx
  PWD=/var/home/lunix/Code/xxxxxxxxxxxxxxxxxxx
  SCRT_GIT_PATH=test.scrt
  SCRT_GIT_URL=git@xxxx.xxxx:xxxxxxx/xxxxx.git
  SCRT_STORAGE=git
  SHELL=/bin/bash
  SHLVL=1
  SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
  SYSTEMD_PAGER=
  TERM=dumb
  USER=lunix
  XDG_DATA_DIRS=/var/home/lunix/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
  _=/usr/bin/env

What is the expected behavior?

When I run the following I get the expected results.
I would expect the same results when running the TUI.

lunix@astro]  -> codex sandbox linux -- env
CODEX_SANDBOX_NETWORK_DISABLED=1
MY_FLAG=1
PATH=/usr/bin
PWD=/var/home/lunix/Code/xxxxxxxxxxxxxxxxxxx

Additional information

_No response_

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 3 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #22023

Powered by Codex Action

etraut-openai contributor · 3 months ago

I’m not able to confirm this from the current code or the 0.130.0 tag.

Both the TUI shell tool and codex sandbox linux build the child env through shell_environment_policy, and the process spawn path clears the parent env before setting the computed env. With the config shown here, I’d expect MY_FLAG=1 and PATH=/usr/bin to appear, and HOMEBREW_* to be excluded.

The pasted TUI output has three signs that the shown config was not active for that command:

  • MY_FLAG=1 is missing
  • PATH is not /usr/bin
  • HOMEBREW_* variables are still present despite the explicit exclude

Could you try reproducing with a temporary CODEX_HOME containing only this config.toml, then start a fresh codex session from that environment and run env | sort again? Please also confirm whether the command was submitted as a normal model tool call or as a direct !env | sort user shell command, since those take different paths.

aussielunix · 3 months ago

I created a new dir and put a fresh config.toml in it.
I also copied over my auth.json

[~/codex_home]
lunix@astro]  -> cat config.toml 
approval_policy = "on-request"
sandbox_mode = "read-only"
web_search = "disabled"
allow_login_shell = false
model = "gpt-5.5"
model_reasoning_effort = "medium"
plan_mode_reasoning_effort = "medium"

[shell_environment_policy]
inherit = "none"
set = { PATH = "/usr/bin", MY_FLAG = "1" }
ignore_default_excludes = false
exclude = ["AWS_*", "AZURE_*", "HOMEBREW*"]
include_only = ["PATH", "HOME", "MY_FLAG"]

[otel]
metrics_exporter = "none"
trace_exporter = "none"
log_user_prompt = false

[analytics]
enabled = false

I then ran codex.
I can see it populate the temporary CODEX_HOME.

If you look at the output below it sort of worked first time but then failed every time after that.

I say sort of worked because if you hit <ctrl-t> the transcript has all your parent env's variables.

    … +28 lines (ctrl + t to view transcript)
lunix@astro]  -> CODEX_HOME="/home/lunix/codex_home" codex

› env

• Ran env
  └ COLORTERM=
    LESS=-R
    … +28 lines (ctrl + t to view transcript)
    HOMEBREW_BUNDLE_FILE=/Brewfile
    _=/bin/env

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

• MY_FLAG=1
  PWD=/home/lunix/Code/xxxxx
  CODEX_SANDBOX_NETWORK_DISABLED=1
  PATH=/home/linuxbrew/.linuxbrew/sbin:/home/linuxbrew/.linuxbrew/bin:/go/bin:/.local/bin:/bin:/usr/bin

  Ran env; full output is shown above in the command result.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


› env

• Ran env
  └ COLORTERM=
    LESS=-R
    … +28 lines (ctrl + t to view transcript)
    HOMEBREW_BUNDLE_FILE=/Brewfile
    _=/bin/env

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

• COLORTERM=
  LESS=-R
  HISTSIZE=5000
  SCRT_GIT_URL=git@xxxx.xxxx:xxxxxxx/xxxxx.git
  EDITOR=vim
  GH_PAGER=cat
  PWD=/home/lunix/Code/xxxxxxxxxxxxxxxxxxx
  SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
  LANG=C.UTF-8
  SCRT_GIT_PATH=test.scrt
  HOMEBREW_NO_AUTO_UPDATE=1
  HOMEBREW_NO_ANALYTICS=1
  TERM=dumb
  CODEX_THREAD_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx
  LESSOPEN=||/usr/bin/lesspipe.sh %s
  GIT_PAGER=cat
  SHLVL=0
  SCRT_STORAGE=git
  PAGER=cat
  MY_FLAG=1
  SYSTEMD_PAGER=
  NO_COLOR=1
  CODEX_CI=1
  LC_CTYPE=C.UTF-8
  XDG_DATA_DIRS=/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
  CODEX_SANDBOX_NETWORK_DISABLED=1
  PATH=/home/linuxbrew/.linuxbrew/sbin:/home/linuxbrew/.linuxbrew/bin:/go/bin:/.local/bin:/bin:/usr/bin
  HISTIGNORE=pwd:exit:clear
  HOMEBREW_BUNDLE_FILE=/Brewfile
  _=/bin/env
hanohrs · 26 days ago

Still reproducible with codex-cli 0.146.0 on Linux.

This also affects the built-in secret-name filtering controlled by ignore_default_excludes = false, so the impact is broader than custom exclude/include_only patterns.

Minimal reproduction using a dummy value:

MY_SECRET=dummy-value codex \
  -c 'shell_environment_policy.ignore_default_excludes = false' \
  exec 'Run: env | grep "^MY_SECRET=" || echo filtered'

Observed output from the tool execution:

MY_SECRET=dummy-value

The equivalent direct sandbox command applies the policy correctly:

MY_SECRET=dummy-value codex \
  -c 'shell_environment_policy.ignore_default_excludes = false' \
  sandbox /bin/sh -c 'env | grep "^MY_SECRET=" || echo filtered'

Output:

filtered