Skip to content

feat: allow non-workspace filesystem writes with read-only legacy fallback#15929

Open
celia-oai wants to merge 2 commits intomainfrom
dev/cc/read-only
Open

feat: allow non-workspace filesystem writes with read-only legacy fallback#15929
celia-oai wants to merge 2 commits intomainfrom
dev/cc/read-only

Conversation

@celia-oai
Copy link
Copy Markdown
Collaborator

@celia-oai celia-oai commented Mar 27, 2026

Summary

This change stops rejecting permission profiles that write outside the workspace root when the canonical FileSystemSandboxPolicy can represent them, even if the legacy SandboxPolicy bridge cannot.

  • allow profiles that write to :tmpdir, /tmp, or other non-workspace roots to load successfully instead of failing during config load
  • fall back to legacy SandboxPolicy::ReadOnly when non-workspace writes cannot be expressed as workspace-write, while keeping the richer canonical filesystem policy for direct runtime enforcement
  • preserve additional_writable_roots such as memories when the canonical filesystem policy already has writable roots, even if the legacy projection degrades to read-only
  • split temp-path semantics so config-facing :tmpdir expands to the broader temp namespace, while legacy WorkspaceWrite bridging keeps the narrower env-backed behavior through TmpdirEnvVar
  • update legacy temp-root expansion to use the host platform's temp env vars, which means Windows WorkspaceWrite policies now pick up TEMP and TMP instead of only looking for Unix-style TMPDIR
  • teach special-path resolution and matching to handle multi-path expansions and cwd-independent aliases consistently, including /tmp realpath handling
  • remove implicit tmp write rules from restricted macOS platform defaults unless the filesystem policy explicitly requests them

Why

The previous behavior was too strict in two ways. First, valid permission profiles were rejected during config load purely because the legacy sandbox projection was lossy, even though the canonical filesystem policy already described the requested writes. Second, temp-path behavior had drifted across platforms: config-facing :tmpdir, legacy workspace-write bridging, and runtime sandbox defaults were not using the same boundaries.

With this change, the canonical filesystem policy remains authoritative. When the legacy bridge cannot represent the writable surface, it degrades to read-only instead of failing, and callers can detect that direct runtime enforcement is required. At the same time, temp handling is clarified across Unix and Windows, and restricted seatbelt defaults stop granting tmp writes unless the policy opts into them.

Testing

verified that this command succeeds:

cargo run -p codex-cli -- \                                                         
    -c 'default_permissions="tmp-write-test"' \
    -c 'permissions.tmp-write-test.filesystem.:minimal=read' \
    -c 'permissions.tmp-write-test.filesystem.:tmpdir=write' \
    sandbox macos --log-denials -- \
    /bin/sh -lc 'p="${TMPDIR%/}/codex-sandbox-pr-test.$$.txt"; printf "sandbox-ok\n" > "$p"; echo "wrote $p"; ls -l "$p"; cat "$p"'

without this change, the command returns Error: permissions profile requests filesystem writes outside the workspace root, which is not supported until the runtime enforces FileSystemSandboxPolicy directly.

and this command fails:

cargo run -p codex-cli -- \                                                         
    -c 'default_permissions="tmp-write-test"' \ 
    -c 'permissions.tmp-write-test.filesystem.:minimal=read' \
    sandbox macos --log-denials -- \
    /bin/sh -lc 'p="${TMPDIR%/}/codex-sandbox-pr-test.$$.txt"; printf "sandbox-ok\n" > "$p"; echo "wrote $p"; ls -l "$p"; cat "$p"'

@celia-oai celia-oai changed the title changes feat: allow non-workspace filesystem writes with read-only legacy fallback Mar 27, 2026
@celia-oai celia-oai marked this pull request as ready for review March 27, 2026 20:21
@celia-oai
Copy link
Copy Markdown
Collaborator Author

@codex review

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5cce1f7345

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 752 to 753
SandboxPolicy::ReadOnly {
access: read_only_access,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Expose split writable roots in model-facing permissions text

This fallback makes the legacy policy ReadOnly, but instruction generation derives sandbox_mode/writable_roots only from that legacy policy (protocol/src/models.rs:516-523). Sessions with :tmpdir or other non-workspace writes are therefore described to the model as read-only with no writable roots, so the model may avoid valid writes or over-request escalation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to need a larger refactor to get it fully right (moving the instruction generation from legacy sandbox policy to new filesystem policy), so won't include it here. can get out a followup PR if needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant