Standalone updater can overwrite managed Codex with a self-referential symlink when CODEX_INSTALL_DIR points to standalone/current/bin

Open 💬 0 comments Opened Jul 13, 2026 by Taratarra0099-jpg

What version of Codex CLI is running?

The failure occurred while a 0.144.2 managed updater was installing 0.144.3.

It is also reproducible directly with the current standalone installer resolving Codex CLI 0.144.3.

What platform is your computer?

macOS, Apple Silicon.

Observed on two separate Macs and reproduced in an isolated temporary HOME.

What issue are you seeing?

If CODEX_INSTALL_DIR points to the managed standalone command directory:

$HOME/.codex/packages/standalone/current/bin

the standalone installer overwrites the managed codex binary with a
self-referential symbolic link:

current/bin/codex ->
current/bin/codex

The release binary reached through standalone/current is also corrupted.

When this environment variable is inherited by:

codex app-server daemon pid-update-loop

the installation may initially work, then break during the daemon updater's
first or subsequent update cycle. Remote clients subsequently report that the
Codex CLI is not installed.

Minimal reproduction

This uses an isolated temporary HOME and does not modify the user's real Codex
installation:

REPRO_HOME="$(mktemp -d)"

curl -fsSL https://chatgpt.com/codex/install.sh |
  env -i \
    HOME="$REPRO_HOME" \
    PATH="/usr/bin:/bin:/usr/sbin:/sbin" \
    CODEX_HOME="$REPRO_HOME/.codex" \
    CODEX_INSTALL_DIR="$REPRO_HOME/.codex/packages/standalone/current/bin" \
    CODEX_NON_INTERACTIVE=true \
    /bin/sh

Actual behavior

The installer exits with:

==> Installing standalone package to .../.codex/packages/standalone/releases/0.144.3-aarch64-apple-darwin
/bin/sh: .../standalone/current/bin/codex: Too many levels of symbolic links

Afterward:

readlink "$REPRO_HOME/.codex/packages/standalone/current/bin/codex"

returns the exact same path:

.../.codex/packages/standalone/current/bin/codex

Expected behavior

The installer should reject a CODEX_INSTALL_DIR that points inside the
managed standalone/current tree, rather than replacing the managed binary.

The daemon updater should also avoid inheriting installer-affecting environment
variables such as CODEX_INSTALL_DIR, or explicitly sanitize them before
invoking install.sh.

Why this matters

The app-server daemon update loop invokes the standalone installer
automatically after an initial delay and then periodically:

https://github.com/openai/codex/blob/main/codex-rs/app-server-daemon/src/update_loop.rs

Because the spawned shell inherits the updater environment, a persistent
CODEX_INSTALL_DIR can silently corrupt an otherwise working managed
installation later.

A related Windows report also shows the standalone updater being affected by
inherited shell environment:

https://github.com/openai/codex/issues/27117

Possible fixes

  1. Canonicalize and compare the visible command path with the managed binary

path before creating the symlink.

  1. Reject CODEX_INSTALL_DIR values located inside standalone/current or its

active release.

  1. Remove CODEX_INSTALL_DIR from the daemon updater child's environment.
  2. Add a regression test covering this self-referential destination.

View original on GitHub ↗