Codex unified-exec PTY can silently truncate ~/.bash_history via default HISTFILESIZE=500
What version of Codex CLI is running?
The incident occurred with codex-cli 0.144.1. The currently installed version is 0.144.5; the underlying Bash behavior remains reproducible.
What subscription do you have?
ChatGPT Pro
Which model were you using?
gpt-5.6-sol
What platform is your computer?
Linux 6.17.0-122035-tuxedo x86_64 x86_64 (Ubuntu 24.04)
What terminal emulator and version are you using (if applicable)?
Kitty; Codex TUI. No terminal multiplexer was involved.
Codex doctor report
Redacted to omit local usernames and paths; all checks reported ok.
{
"schemaVersion": 1,
"overallStatus": "ok",
"codexVersion": "0.144.5",
"auth": "ChatGPT",
"installMethod": "npm",
"platform": "linux-x86_64",
"os": "Ubuntu 24.04 (noble) [64-bit]",
"terminal": "kitty",
"sandbox": {
"approvalPolicy": "OnRequest",
"filesystem": "restricted",
"network": "restricted"
},
"features": [
"shell_tool",
"unified_exec",
"shell_snapshot",
"multi_agent",
"guardian_approval"
],
"updates": {
"current": "0.144.5",
"latest": "0.144.5"
}
}
What issue are you seeing?
A Codex subagent silently truncated the user's persistent ~/.bash_history, causing irreversible loss of years of shell history.
The subagent requested an escalated persistent PTY shell using:
taskset -c 0-5 env OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 \
MKL_NUM_THREADS=1 NUMEXPR_NUM_THREADS=1 bash --noprofile --norc
Because --norc bypasses the user's .bashrc, the child Bash used its default HISTFILESIZE=500. On startup, interactive Bash rewrote ~/.bash_history to 500 entries and replaced its inode. The agent subsequently sent many multiline apply_patch heredocs through the persistent PTY, so patch payloads later appeared in the user's shell history.
There was no rm, truncate, history -c, or explicit operation on ~/.bash_history anywhere in the rollout. This was an unintended side effect of opening the interactive PTY shell.
Forensic correlation was exact:
- Guardian approved the PTY launch at
2026-07-13T08:13:20.403Z. ~/.bash_historyreceived a new inode at2026-07-13 10:13:20.438 +0200, 35 ms later.- The parent rollout received the
bash-5.2$prompt at2026-07-13T08:13:21.580Z. - The persistent PTY was later lost without a clean
exit(write_stdin failed: Unknown process id).
Incident thread ID: 019f57f1-790b-7131-8b87-b1d166d7fda3.
This is especially dangerous because the approval request describes the action as merely opening a CPU-capped shell for scoped repository changes. Neither the agent nor the guardian surfaces that launching the shell can irreversibly modify a user file outside the repository.
What steps can reproduce the bug?
The Bash side effect can be reproduced safely with an isolated HOME:
tmp_home=$(mktemp -d)
seq 1 4434 > "$tmp_home/.bash_history"
stat -c 'before: inode=%i size=%s' "$tmp_home/.bash_history"
# Launch this with a PTY, as Codex unified exec does with tty=true.
env HOME="$tmp_home" bash --noprofile --norc
While that shell is still sitting at its first prompt, inspect from another shell:
wc -l "$tmp_home/.bash_history"
stat -c 'after: inode=%i size=%s' "$tmp_home/.bash_history"
Observed result: the history file falls from 4,434 lines to exactly 500 and has a new inode before any command is entered in the child shell.
To reproduce the Codex path, have an agent start a long-lived unified-exec PTY with bash --noprofile --norc and then use write_stdin to send commands. Do not do this with a real HOME/history file.
What is the expected behavior?
Codex-created interactive shells must never read, truncate, rewrite, or append to the user's persistent shell history unless the user explicitly asks for that behavior.
At minimum, any agent/runtime-created PTY shell should be launched with an isolated history configuration such as:
HISTFILE=/dev/null bash --noprofile --norc
Preferably the unified exec runtime should enforce this itself rather than relying on model-generated commands. A shell launch capable of modifying history should also not be classified as a harmless reversible local action.
Additional information
The user's normal .bashrc was configured defensively:
shopt -s histappend
HISTSIZE=100000
HISTFILESIZE=200000
PROMPT_COMMAND='history -a; history -n; ...'
Those protections were bypassed specifically because the Codex-generated shell used --noprofile --norc. This was not caused by normal history-size limits, an OS update, or a user command.
Suggested defenses:
- Force
HISTFILE=/dev/null(or a Codex-owned temporary file) for all unified-exec PTYs. - Do not start an interactive shell merely to apply patches; invoke scoped commands directly.
- Teach the guardian/risk layer that interactive shell startup can mutate dotfiles, including history, even before the first command.
- Add a regression test with a temporary HOME containing more than 500 history entries and assert that starting/stopping a PTY leaves it byte-identical.