Skip to content

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

@lshoy

Description

@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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingsandboxIssues related to permissions or sandboxing

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions