mirror of
https://github.com/openai/codex.git
synced 2026-04-26 23:55:25 +00:00
feat: add Reject approval policy with granular prompt rejection controls (#12087)
## Why
We need a way to auto-reject specific approval prompt categories without
switching all approvals off.
The goal is to let users independently control:
- sandbox escalation approvals,
- execpolicy `prompt` rule approvals,
- MCP elicitation prompts.
## What changed
- Added a new primary approval mode in `protocol/src/protocol.rs`:
```rust
pub enum AskForApproval {
// ...
Reject(RejectConfig),
// ...
}
pub struct RejectConfig {
pub sandbox_approval: bool,
pub rules: bool,
pub mcp_elicitations: bool,
}
```
- Wired `RejectConfig` semantics through approval paths in `core`:
- `core/src/exec_policy.rs`
- rejects rule-driven prompts when `rules = true`
- rejects sandbox/escalation prompts when `sandbox_approval = true`
- preserves rule priority when both rule and sandbox prompt conditions
are present
- `core/src/tools/sandboxing.rs`
- applies `sandbox_approval` to default exec approval decisions and
sandbox-failure retry gating
- `core/src/safety.rs`
- keeps `Reject { all false }` behavior aligned with `OnRequest` for
patch safety
- rejects out-of-root patch approvals when `sandbox_approval = true`
- `core/src/mcp_connection_manager.rs`
- auto-declines MCP elicitations when `mcp_elicitations = true`
- Ensured approval policy used by MCP elicitation flow stays in sync
with constrained session policy updates.
- Updated app-server v2 conversions and generated schema/TypeScript
artifacts for the new `Reject` shape.
## Verification
Added focused unit coverage for the new behavior in:
- `core/src/exec_policy.rs`
- `core/src/tools/sandboxing.rs`
- `core/src/mcp_connection_manager.rs`
- `core/src/safety.rs`
- `core/src/tools/runtimes/apply_patch.rs`
Key cases covered include rule-vs-sandbox prompt precedence, MCP
auto-decline behavior, and patch/sandbox retry behavior under
`RejectConfig`.
This commit is contained in:
@@ -378,11 +378,41 @@ pub enum AskForApproval {
|
||||
#[default]
|
||||
OnRequest,
|
||||
|
||||
/// Fine-grained rejection controls for approval prompts.
|
||||
///
|
||||
/// When a field is `true`, prompts of that category are automatically
|
||||
/// rejected instead of shown to the user.
|
||||
Reject(RejectConfig),
|
||||
|
||||
/// Never ask the user to approve commands. Failures are immediately returned
|
||||
/// to the model, and never escalated to the user for approval.
|
||||
Never,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, TS)]
|
||||
pub struct RejectConfig {
|
||||
/// Reject approval prompts related to sandbox escalation.
|
||||
pub sandbox_approval: bool,
|
||||
/// Reject prompts triggered by execpolicy `prompt` rules.
|
||||
pub rules: bool,
|
||||
/// Reject MCP elicitation prompts.
|
||||
pub mcp_elicitations: bool,
|
||||
}
|
||||
|
||||
impl RejectConfig {
|
||||
pub const fn rejects_sandbox_approval(self) -> bool {
|
||||
self.sandbox_approval
|
||||
}
|
||||
|
||||
pub const fn rejects_rules_approval(self) -> bool {
|
||||
self.rules
|
||||
}
|
||||
|
||||
pub const fn rejects_mcp_elicitations(self) -> bool {
|
||||
self.mcp_elicitations
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents whether outbound network access is available to the agent.
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Display, Default, JsonSchema, TS,
|
||||
@@ -2818,6 +2848,26 @@ mod tests {
|
||||
assert!(enabled.has_full_network_access());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reject_config_mcp_elicitation_flag_is_field_driven() {
|
||||
assert!(
|
||||
RejectConfig {
|
||||
sandbox_approval: false,
|
||||
rules: false,
|
||||
mcp_elicitations: true,
|
||||
}
|
||||
.rejects_mcp_elicitations()
|
||||
);
|
||||
assert!(
|
||||
!RejectConfig {
|
||||
sandbox_approval: false,
|
||||
rules: false,
|
||||
mcp_elicitations: false,
|
||||
}
|
||||
.rejects_mcp_elicitations()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_write_restricted_read_access_includes_effective_writable_roots() {
|
||||
let cwd = if cfg!(windows) {
|
||||
|
||||
Reference in New Issue
Block a user