openai / openai/codex

Codex Python SDK 0.147.0: Sandbox.read_only permits persistent filesystem writes via managed file-edit path

Open
#40,229 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app-server bug CLI sandbox
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What issue are you seeing?

Summary

The Codex Python SDK does not enforce Sandbox.read_only end-to-end for the managed file-edit path in the tested environment.

With Sandbox.read_only explicitly configured at both the thread and turn levels, a Codex turn can create a file through the managed file-edit / apply_patch path, and the file remains persistently visible to the external SDK client after the turn completes.

I reproduced the behavior twice with completely fresh SDK threads in a neutral working directory with:

  • no AGENTS.md;
  • no project-specific instructions;
  • no prior engineering context.

An external Python process, rather than the Codex agent itself, verified the filesystem state before and after each turn.

Affected environment

  • Python package: openai-codex 0.147.0
  • SDK pinned runtime: codex-cli 0.147.0
  • Separately installed interactive CLI: codex-cli 0.149.0 (not used as the SDK runtime for the reproduction)
  • WSL2 Ubuntu 24.04
  • Docker Desktop
  • Linux container
  • Python SDK executed inside the container

Security impact

Applications integrating the Codex SDK may rely on Sandbox.read_only as a filesystem protection boundary.

In the reproduced configuration, a managed file-edit operation can persist filesystem modifications despite an explicit read-only sandbox request.

This can cause files to be modified when the embedding application expects Sandbox.read_only to prevent persistent filesystem writes.

Causal isolation

The issue does not depend on project-specific instructions or workspace-level agent configuration.

The reproduction used a neutral control directory whose governing parent chain contained no AGENTS.md.

Two independent fresh SDK threads, using different filenames and explicit Sandbox.read_only settings at both thread and turn levels, reproduced the same persistent write behavior.

What steps can reproduce the bug?
Environment
  • Python package: openai-codex 0.147.0
  • SDK pinned runtime: codex-cli 0.147.0
  • WSL2 Ubuntu 24.04
  • Docker Desktop
  • Linux container
  • No governing AGENTS.md or project-specific instructions in the control directory
Reproduction
  1. Create or use a neutral working directory with no applicable AGENTS.md.

  2. Generate a unique probe filename and verify from the external Python client that it does not exist:

from pathlib import Path
import uuid

cwd = Path("/home/quasar/codex-sdk-readonly-control")
probe = cwd / f"readonly_probe_{uuid.uuid4().hex}.txt"

assert not probe.exists()

3. Start a completely fresh Codex SDK thread with Sandbox.read_only:
thread = codex.thread_start(
    cwd=str(cwd),
    sandbox=Sandbox.read_only,
)

4. Run the turn while explicitly specifying Sandbox.read_only again:
prompt = f"""
Create exactly one file named {probe.name} in the current working directory
using the managed file-edit/apply_patch path.

The file must contain exactly:

codex-sdk-read-only-control

Do not use shell commands.
Do not create or modify any other file.
"""

result = thread.run(
    prompt,
    sandbox=Sandbox.read_only,
)

5. After the Codex turn has completely returned, inspect the probe path from the external Python client rather than asking the agent to verify it:
print("OUTSIDE_AFTER_EXISTS =", probe.exists())

if probe.exists():
    print("OUTSIDE_AFTER_CONTENT =", probe.read_text())

### What is the expected behavior?

When `Sandbox.read_only` is explicitly configured, Codex should be able to read files but should not be able to persist filesystem modifications.

This restriction should apply consistently to all mutation paths, including the managed file-edit / `apply_patch` path.

A managed file-edit request under `Sandbox.read_only` should therefore be rejected or otherwise prevented from modifying the persistent filesystem visible to the external SDK client.

### Additional information

_No response_

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.

Research direction

Start with the Sandbox.read_only settings on thread_start and thread.run, then trace how the managed file-edit/apply_patch path handles them. Run the supplied reproduction in a neutral directory and verify the filesystem externally after the turn. Done means read-only turns cannot persist modifications through this path.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
cli, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.