Skip to content

permissions: derive config defaults as profiles#19772

Merged
bolinfest merged 1 commit intomainfrom
pr19772
Apr 27, 2026
Merged

permissions: derive config defaults as profiles#19772
bolinfest merged 1 commit intomainfrom
pr19772

Conversation

@bolinfest
Copy link
Copy Markdown
Collaborator

@bolinfest bolinfest commented Apr 27, 2026

Why

This continues the permissions migration by making legacy config default resolution produce the canonical PermissionProfile first. The legacy SandboxPolicy projection should stay available at compatibility boundaries, but config loading should not create a legacy policy just to immediately convert it back into a profile.

Specifically, when default_permissions is not specified in config.toml, instead of creating a SandboxPolicy in codex-rs/core/src/config/mod.rs and then trying to derive a PermissionProfile from it, we use derive_permission_profile() to create a more faithful PermissionProfile using the values of ConfigToml directly.

This also keeps the existing behavior of sandbox_workspace_write and extra writable roots after #19841 replaced :cwd with :project_roots. Legacy workspace-write defaults are represented as symbolic :project_roots write access plus symbolic project-root metadata carveouts. Extra absolute writable roots are still added directly and continue to get concrete metadata protections for paths that exist under those roots.

The platform sandboxes differ when a symbolic project-root subpath does not exist yet.

  • Seatbelt can encode literal/subpath exclusions directly, so macOS emits project-root metadata subpath policies even if .git, .agents, or .codex do not exist.
  • bwrap has to materialize bind-mount targets. Binding /dev/null to a missing .git can create a host-visible placeholder that changes Git repo discovery. Binding missing .agents would not affect Git discovery, but it would still create a host-visible project metadata placeholder from an automatic compatibility carveout. Linux therefore skips only missing automatic .git and .agents read-only metadata masks; missing .codex remains protected so first-time project config creation goes through the protected-path approval flow. User-authored read and none subpath rules keep normal bwrap behavior, and none can still mask the first missing component to prevent creation under writable roots.

What Changed

  • Adds profile-native helpers for legacy workspace-write semantics, including PermissionProfile::workspace_write_with(), FileSystemSandboxPolicy::workspace_write(), and FileSystemSandboxPolicy::with_additional_legacy_workspace_writable_roots().
  • Makes FileSystemSandboxPolicy::workspace_write() the single legacy workspace-write constructor so both from_legacy_sandbox_policy() and From<&SandboxPolicy> include the project-root metadata carveouts.
  • Removes the no-carveout legacy_workspace_write_base_policy() path and the prune_read_entries_under_writable_roots() cleanup that was only needed by that split construction.
  • Adds ConfigToml::derive_permission_profile() for legacy sandbox-mode fallback resolution; named default_permissions profiles continue through the permissions profile pipeline instead of being reconstructed from sandbox_mode.
  • Updates Config::load() to start from the derived profile, validate that it still has a legacy compatibility projection, and apply additional writable roots directly to managed workspace-write filesystem policies.
  • Updates Linux bwrap argument construction so missing automatic .git/.agents symbolic project-root read-only carveouts are skipped before emitting bind args; missing .codex, user-authored read/none subpath rules, and existing missing writable-root behavior are preserved.
  • Adds coverage that legacy workspace-write config produces symbolic project-root metadata carveouts, extra legacy workspace writable roots still protect existing metadata paths such as .git, and bwrap skips missing .git/.agents project-root carveouts while preserving missing .codex and user-authored missing subpath rules.

Stack created with Sapling. Best reviewed with ReviewStack.

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: f858b35bc1

ℹ️ 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 +1977 to +1978
let (mut file_system_sandbox_policy, network_sandbox_policy) =
permission_profile.to_runtime_permissions();
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.

P1 Badge Restore cwd projection for legacy sandbox defaults

Converting legacy sandbox_mode defaults with permission_profile.to_runtime_permissions() changes workspace-write behavior: PermissionProfile::workspace_write() carries unconditional project_roots(".git") / project_roots(".agents") read rules, so ${cwd}/.git and ${cwd}/.agents become read-only even when they do not exist yet. The previous path (from_legacy_sandbox_policy_for_cwd) only added those carveouts when present on disk (except .codex), so operations like git init in a fresh directory could create .git. This regression can block common write flows under legacy workspace-write configs.

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.

Addressed in c70c0f5c94. Config loading now projects the derived profile through to_legacy_sandbox_policy(resolved_cwd) and rehydrates it with PermissionProfile::from_legacy_sandbox_policy_for_cwd(...), so legacy workspace-write keeps the cwd-aware .git / .agents behavior. Coverage includes legacy_sandbox_mode_builds_profiles_with_compatible_projection and with_additional_legacy_workspace_writable_roots_protects_metadata.

@bolinfest bolinfest force-pushed the pr19772 branch 6 times, most recently from c188a22 to c70c0f5 Compare April 27, 2026 07:14
Bojun-Vvibe added a commit to Bojun-Vvibe/oss-contributions that referenced this pull request Apr 27, 2026
- anomalyco/opencode#24574 ignore: split up reasoning transforms (merge-as-is)
- anomalyco/opencode#24573 fix: vertex anthropic toolStreaming default (merge-as-is)
- openai/codex#19778 hooks/list + hooks/config/write APIs (merge-after-nits)
- openai/codex#19772 permissions: derive config defaults as profiles (merge-after-nits)
@bolinfest bolinfest requested a review from viyatb-oai April 27, 2026 16:14
@bolinfest bolinfest force-pushed the pr19772 branch 11 times, most recently from 4b88857 to e103c1c Compare April 27, 2026 23:02
@bolinfest bolinfest merged commit 755880e into main Apr 27, 2026
39 checks passed
@bolinfest bolinfest deleted the pr19772 branch April 27, 2026 23:50
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 27, 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.

2 participants