Codex App Linux sandbox allowed a Bash fork chain to freeze the host
What version of the Codex App are you using?
Codex App 26.803.81509 with codex-cli 0.147.0-alpha.6.6
What subscription do you have?
ChatGPT subscription; the exact tier is not exposed by the Linux app package
What platform is your computer?
Linux 7.1.8-200.nobara.fc44.x86_64 x86_64 unknown
Nobara/Fedora 44, Bash 5.3.9, Python 3.14.6
What issue are you seeing?
A normal Python test launched by the Codex App exec sandbox produced a linear, self-replicating Bash process chain. The command should have printed one hostname and exited. Instead, every Bash process created another Bash process with the same command line.
The runaway chain exhausted unreclaimable kernel slab memory and froze the entire host twice. The second occurrence required a forced reboot.
Persistent atop and kernel-memory captures established this process tree inside the Codex App cgroup:
Codex App
└─ bwrap --new-session --die-with-parent ...
└─ /bin/bash -c "python3 <test> && make lint"
└─ python3 <test>
└─ bash -c '<function definition>; render_hostname'
└─ bash -c '<same command>'
└─ bash -c '<same command>'
└─ ...
All descendants were in:
/user.slice/user-1000.slice/user@1000.service/app.slice/app-org.chromium.Chromium-<pid>.scope
At the last complete diagnostic snapshot:
- 6,144
bashprocesses - 196,298,624
anon_vma_chainobjects - 14,836,968 kB
SUnreclaim - only 2,827,064 kB
MemAvailable - 24,636,816 kB swap still free
The kernel then logged repeated order-0 page-allocation failures from Btrfs, Wi-Fi, GUI, and SQLite threads. These were consequences of the unreclaimable slab growth, not independent hardware failures.
The monitor captured two separate growth waves in the same app session. The first chain disappeared, then the test was run again and the second chain grew until the host stopped responding.
What steps can reproduce the bug?
The triggering test used this pattern:
import subprocess
shell_function = r'''render_hostname() {
local template="${HOST_TEMPLATE:-%s.example.com}"
printf "$template" "${VM_NAME}-service"
}
'''
subprocess.run(
["bash", "-c", f"{shell_function}\nrender_hostname"],
env={"VM_NAME": "foo"},
check=True,
capture_output=True,
text=True,
)
- Run a Python test containing the snippet through a Codex App shell tool call on Linux
- Inspect the descendant process tree and cgroup task count
- If affected, Bash descendants form a linear chain with identical command lines instead of returning once
I have not deliberately rerun this unbounded on the host because it froze the machine twice. As a control, the same Bash payload with the same stripped environment completed normally in a transient systemd scope capped at 32 tasks and 100 MB, outside the failing bwrap execution path
What is the expected behavior?
The subprocess should print foo-service.example.com and exit with status 0
The Codex Linux sandbox should also have a finite descendant-process limit so a faulty command cannot exhaust host kernel memory and freeze the desktop
Additional information
No kernel panic, GPU reset, NVMe error, MCE, or hardware error preceded the freeze. A crash dump was not produced because the machine was force-rebooted rather than panicking
Suggested safeguards:
- Apply a finite cgroup
pids.max/TasksMaxto each shell-tool execution - Apply a reasonable per-execution memory ceiling or pressure threshold
- Terminate the entire execution process group/cgroup when a command times out or its turn ends
- Investigate why the stripped-environment Bash subprocess replicated only inside this Codex App
bwrappath
1 Comment
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action