Codex unified-exec PTY can silently truncate ~/.bash_history via default HISTFILESIZE=500

Open
#33,591 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
68/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
bash, rust
Domain
cli, security, testing

Research direction

Start at the unified-exec PTY shell-launch path and trace the environment passed before bash --noprofile --norc starts; inspect how write_stdin manages the persistent shell. Reproduce with the issue's temporary HOME setup, then add the regression coverage described in the issue and verify that starting and stopping a PTY leaves a history file byte-identical.

Written by the indexing model from the issue text.

Description

bug CLI subagent tool-calls
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_history received a new inode at 2026-07-13 10:13:20.438 +0200, 35 ms later.
  • The parent rollout received the bash-5.2$ prompt at 2026-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:

  1. Force HISTFILE=/dev/null (or a Codex-owned temporary file) for all unified-exec PTYs.
  2. Do not start an interactive shell merely to apply patches; invoke scoped commands directly.
  3. Teach the guardian/risk layer that interactive shell startup can mutate dotfiles, including history, even before the first command.
  4. 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.
Dominant language
Rust
Stars
125k
Forks
19.5k
Avg merge
1m
Merged PRs (30d)
1k

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.