Skip to content

fix(permissions): preserve managed deny-read during escalation#15977

Merged
viyatb-oai merged 10 commits into
mainfrom
codex/viyatb/deny-read-enforcement
May 11, 2026
Merged

fix(permissions): preserve managed deny-read during escalation#15977
viyatb-oai merged 10 commits into
mainfrom
codex/viyatb/deny-read-enforcement

Conversation

@viyatb-oai
Copy link
Copy Markdown
Collaborator

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

Why

Managed filesystem deny_read requirements are administrator-enforced restrictions on specific paths. Once those requirements are active, Codex should not drop them just because an execution path would otherwise leave the sandbox.

Before this change, an explicit escalation, a prefix-rule allow, a sandbox-denial retry, or an app-server legacy sandbox override could rebuild the runtime policy without those managed read-deny entries and expose a path the administrator had marked unreadable.

This is narrower than general sandbox-mode constraints. If an enterprise only sets allowed_sandbox_modes, a trusted prefix_rule(..., decision = "allow") can still run its matching command unsandboxed; this PR only preserves managed filesystem deny_read restrictions across those paths.

What Changed

  • Mark filesystem policies built from managed deny_read requirements so callers can tell when those deny entries must survive escalation.
  • Preserve managed deny-read entries when runtime permission profiles are rebuilt through protocol, app-server, or legacy sandbox-policy compatibility paths.
  • Keep managed deny-read attempts inside the selected sandbox on the first attempt and after sandbox-denial retries.
  • Preserve the same behavior in the zsh-fork escalation path, including prefix-rule-driven escalation.
  • Add a regression test showing the opposite case too: without managed deny-read, a prefix-rule allow still chooses unsandboxed execution.

Verification

Targeted automated verification:

cargo test -p codex-core shell_request_escalation_execution_is_explicit -- --nocapture
cargo test -p codex-core prefix_rule_uses_unsandboxed_execution_without_managed_deny_read -- --nocapture
cargo test -p codex-core prefix_rule_preserves_managed_deny_read_escalation -- --nocapture
cargo test -p codex-protocol permission_profile_round_trip_preserves_filesystem_policy_metadata -- --nocapture
cargo test -p codex-protocol preserving_deny_entries_keeps_unrestricted_policy_enforceable -- --nocapture
cargo test -p codex-app-server-protocol permission_profile_file_system_permissions_preserves_policy_metadata -- --nocapture
cargo check -p codex-app-server -p codex-tui

Smoke-test invocations:

# macOS exact deny + allowed control
codex exec --skip-git-repo-check -C "$ROOT" \
  -c 'default_permissions="deny_read_smoke"' \
  -c 'permissions.deny_read_smoke.filesystem={":minimal"="read",":project_roots"={"."="write","secrets"="none","future-secret"="none","**/*.env"="none"}}' \
  'Run shell commands only. Print the contents of allowed.txt. Then test whether reading secrets/exact-secret.txt succeeds without printing that file if it does. End with exactly two lines: allowed=<contents> and exact_secret=<BLOCKED or READABLE>.'

# Linux exact deny + allowed control
codex exec --skip-git-repo-check -C "$ROOT" \
  -c 'default_permissions="deny_read_smoke"' \
  -c 'permissions.deny_read_smoke.filesystem={":minimal"="read",glob_scan_max_depth=3,":project_roots"={"."="write","secrets"="none","future-secret"="none","**/*.env"="none"}}' \
  'Run shell commands only. Print the contents of allowed.txt. Then test whether reading secrets/exact-secret.txt succeeds without printing that file if it does. End with exactly two lines: allowed=<contents> and exact_secret=<BLOCKED or READABLE>.'

Observed manual smoke matrix:

Case macOS Seatbelt Linux bubblewrap
cat allowed.txt Pass Pass
cat secrets/exact-secret.txt Blocked Blocked
cat envs/root.env Blocked Blocked
cat envs/nested/one.env Blocked Blocked
cat envs/nested/two.env Blocked Blocked
cat alias-to-secrets/exact-secret.txt Blocked Blocked
Missing denied path A file created after sandbox setup remained unreadable Creation was blocked by the reserved missing-path placeholder, and the placeholder was cleaned up after exit
Real codex exec shell turn Pass Pass

Notes:

  • The Linux smoke run used the fallback glob walker because the devbox did not have rg installed.
  • The smoke matrix verifies the end-to-end filesystem behavior on macOS and Linux; the escalation-specific behavior is covered by the focused tests above.

@viyatb-oai viyatb-oai changed the title fix(core): enforce explicit deny-read paths fix(permissions): enforce exact deny-read paths Mar 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Closing this pull request because it has had no updates for more than 14 days. If you plan to continue working on it, feel free to reopen or open a new PR.

@github-actions github-actions Bot closed this Apr 11, 2026
@viyatb-oai viyatb-oai reopened this Apr 11, 2026
@viyatb-oai viyatb-oai force-pushed the codex/viyatb/deny-read-enforcement branch from cbde62a to a8a396a Compare April 11, 2026 22:09
@viyatb-oai viyatb-oai marked this pull request as ready for review April 12, 2026 01:57
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: a5d463d15e

ℹ️ 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 thread codex-rs/core/src/filesystem_deny_read.rs Outdated
Comment thread codex-rs/core/src/tools/sandboxing_tests.rs Outdated
Comment thread codex-rs/core/src/exec_policy_tests.rs Outdated
Comment thread codex-rs/core/src/exec_policy_tests.rs Outdated
@viyatb-oai viyatb-oai changed the title fix(permissions): enforce exact deny-read paths fix(permissions): preserve deny-read on explicit escalation Apr 20, 2026
@viyatb-oai viyatb-oai changed the title fix(permissions): preserve deny-read on explicit escalation test(core): avoid known-safe command in exec-policy test Apr 21, 2026
@viyatb-oai viyatb-oai changed the title test(core): avoid known-safe command in exec-policy test fix(permissions): preserve deny-read during escalation Apr 21, 2026
@viyatb-oai viyatb-oai changed the title fix(permissions): preserve deny-read during escalation fix(permissions): preserve managed deny-read during escalation May 1, 2026
@viyatb-oai viyatb-oai force-pushed the codex/viyatb/deny-read-enforcement branch from 0ba1cc2 to d503f31 Compare May 1, 2026 23:40
@viyatb-oai viyatb-oai changed the title fix(permissions): preserve managed deny-read during escalation fix(permissions): preserve constrained profiles during escalation May 3, 2026
@viyatb-oai viyatb-oai changed the title fix(permissions): preserve constrained profiles during escalation fix(permissions): preserve managed deny-read during escalation May 5, 2026
viyatb-oai and others added 2 commits May 5, 2026 13:15
Keep approval/escalation flow intact while ensuring deny-read policies do not allow first-attempt sandbox bypass. Centralize the clamp in sandbox override selection and remove the special rejection helper.

Co-authored-by: Codex <noreply@openai.com>
viyatb-oai added 3 commits May 5, 2026 13:16
Co-authored-by: Codex noreply@openai.com
Co-authored-by: Codex noreply@openai.com
Co-authored-by: Codex noreply@openai.com
@viyatb-oai viyatb-oai force-pushed the codex/viyatb/deny-read-enforcement branch from 729b6fa to 1efc5b0 Compare May 5, 2026 20:19
Comment thread codex-rs/app-server-protocol/src/protocol/v2.rs Outdated
Comment thread codex-rs/core/src/tools/runtimes/shell.rs
Comment thread codex-rs/core/src/tools/runtimes/unified_exec.rs
Comment thread codex-rs/core/src/tools/orchestrator.rs Outdated
Comment thread codex-rs/core/src/tools/sandboxing_tests.rs
viyatb-oai and others added 3 commits May 11, 2026 11:12
Co-authored-by: Codex <noreply@openai.com>
## Summary

In #21584, we disabled doctests for
crates that lack any doctests. We can enforce that property via `cargo
shear --deny-warnings`: crates that lack doctests will be flagged if
doctests are enabled, and crates with doctests will be flagged if
doctests are disabled.

A few additional notes:

- By adding `--deny-warnings`, `cargo shear` also flagged a number of
modules that were not reachable at all. Some of those have been removed.
- This PR removes a usage of `windows_modules!` (since `cargo shear` and
`rustfmt` couldn't see through it) in favor of simple `#[cfg(target_os =
"windows")]` macros. As a consequence, many of these files exhibit churn
in this PR, since they weren't being formatted by `rustfmt` at all on
main.
- Again, to make the code more analyzable, this PR also removes some
usages of `#[path = "cwd_junction.rs"]` in favor of a more standard
module structure. The bin sidecar structure is still retained, but,
e.g., `windows-sandbox-rs/src/bin/command_runner.rs‎` was moved to
`windows-sandbox-rs/src/bin/command_runner/main.rs`, and so on.

---------

Co-authored-by: Codex <noreply@openai.com>
@viyatb-oai viyatb-oai merged commit 6506765 into main May 11, 2026
26 checks passed
@viyatb-oai viyatb-oai deleted the codex/viyatb/deny-read-enforcement branch May 11, 2026 18:49
@github-actions github-actions Bot locked and limited conversation to collaborators May 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants