Granular approval policy prompts model to use sandbox_permissions that runtime rejects unless OnRequest

Open 💬 1 comment Opened May 18, 2026 by lshoy

What version of Codex CLI is running?

codex-cli 0.130.0 locally. I also checked the rust-v0.131.0 source tag and the same behavior appears present there.

What subscription do you have?

Pro $200

Which model were you using?

N/A, this is model independent

What platform is your computer?

Linux 6.19.9 x86_64 unknown

What terminal emulator and version are you using (if applicable)?

N/A, this was via source inspection

Codex doctor report

What issue are you seeing?

Under approval_policy = granular, Codex can tell the model to use direct shell sandbox_permissions requests that the runtime then rejects because the policy is not OnRequest.

Specifically, when:

  • approval_policy = Granular
  • features.exec_permission_approvals = true
  • Granular.sandbox_approval = true

the generated permission instructions include the direct shell permission request text from on_request_rule_request_permission.md, telling the model to use:

{
  "sandbox_permissions": "with_additional_permissions",
  "additional_permissions": { "...": "..." }
}

or:

{
  "sandbox_permissions": "require_escalated"
}

However, the shell runtime rejects fresh direct shell sandbox overrides unless the approval policy is OnRequest.

This means the model is primed to use a path that is invalid under Granular. It can waste a tool call trying with_additional_permissions, receive a rejection, then waste another call trying require_escalated, also receiving a rejection, before possibly discovering the separate request_permissions tool path.

The prompt/context should either avoid advertising direct shell sandbox_permissions requests under Granular, or explicitly tell the model to use request_permissions instead.

What steps can reproduce the bug?

Source-level reproduction against rust-v0.131.0:

  1. In codex-rs/core/src/context/permissions_instructions.rs, granular_instructions(...) computes:
let shell_permission_requests_available =
    exec_permission_approvals_enabled && sandbox_approval_prompts_allowed;
  1. When that is true, it appends APPROVAL_POLICY_ON_REQUEST_RULE_REQUEST_PERMISSION:
if shell_permission_requests_available {
    sections.push(APPROVAL_POLICY_ON_REQUEST_RULE_REQUEST_PERMISSION.to_string());
}

Source:
https://github.com/openai/codex/blob/rust-v0.131.0/codex-rs/core/src/context/permissions_instructions.rs#L268-L318

  1. That prompt tells the model to use direct shell sandbox_permissions:
- `sandbox_permissions: "with_additional_permissions"`
...
- `sandbox_permissions: "require_escalated"`

Source:
https://github.com/openai/codex/blob/rust-v0.131.0/codex-rs/core/src/context/prompts/permissions/approval_policy/on_request_rule_request_permission.md#L1-L33

  1. The shell tool schema also advertises these fields when exec_permission_approvals_enabled is true:
"Sandbox permissions for the command. Use \"with_additional_permissions\" ... or \"require_escalated\" ..."

Source:
https://github.com/openai/codex/blob/rust-v0.131.0/codex-rs/core/src/tools/handlers/shell_spec.rs#L281-L321

  1. But shell execution rejects fresh direct sandbox overrides unless the approval policy is OnRequest:
if effective_additional_permissions
    .sandbox_permissions
    .requests_sandbox_override()
    && !effective_additional_permissions.permissions_preapproved
    && !matches!(
        turn.approval_policy.value(),
        codex_protocol::protocol::AskForApproval::OnRequest
    )
{
    ...
}

Source:
https://github.com/openai/codex/blob/rust-v0.131.0/codex-rs/core/src/tools/handlers/shell.rs#L129-L144

  1. with_additional_permissions has an additional validator with the same effective requirement:
if uses_additional_permissions {
    if !permissions_preapproved && !matches!(approval_policy, AskForApproval::OnRequest) {
        return Err(...)
    }
}

Source:
https://github.com/openai/codex/blob/rust-v0.131.0/codex-rs/core/src/tools/handlers/mod.rs#L193-L197

What is the expected behavior?

The model-visible instructions should match the runtime behavior.

Either:

  1. Under Granular, do not include direct shell sandbox_permissions instructions unless the runtime will actually accept those requests.

or:

  1. Under Granular, explicitly tell the model not to use direct shell sandbox_permissions, and to use the separate request_permissions tool for network / file_system permission requests.

Current behavior is misleading because it advertises with_additional_permissions and require_escalated in a state where fresh direct shell requests using those values are rejected before reaching the user.

Additional information

I checked this against both:

  • local CLI: codex-cli 0.130.0
  • source tag: rust-v0.131.0

The separate request_permissions tool path appears to be the viable/intended Granular path.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗