mirror of
https://github.com/openai/codex.git
synced 2026-04-25 15:15:15 +00:00
## 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`.
366 lines
9.0 KiB
JSON
366 lines
9.0 KiB
JSON
{
|
||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||
"definitions": {
|
||
"AbsolutePathBuf": {
|
||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||
"type": "string"
|
||
},
|
||
"AskForApproval": {
|
||
"description": "Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
|
||
"oneOf": [
|
||
{
|
||
"description": "Under this policy, only \"known safe\" commands—as determined by `is_safe_command()`—that **only read files** are auto‑approved. Everything else will ask the user to approve.",
|
||
"enum": [
|
||
"untrusted"
|
||
],
|
||
"type": "string"
|
||
},
|
||
{
|
||
"description": "DEPRECATED: *All* commands are auto‑approved, but they are expected to run inside a sandbox where network access is disabled and writes are confined to a specific set of paths. If the command fails, it will be escalated to the user to approve execution without a sandbox. Prefer `OnRequest` for interactive runs or `Never` for non-interactive runs.",
|
||
"enum": [
|
||
"on-failure"
|
||
],
|
||
"type": "string"
|
||
},
|
||
{
|
||
"description": "The model decides when to ask the user for approval.",
|
||
"enum": [
|
||
"on-request"
|
||
],
|
||
"type": "string"
|
||
},
|
||
{
|
||
"additionalProperties": false,
|
||
"description": "Fine-grained rejection controls for approval prompts.\n\nWhen a field is `true`, prompts of that category are automatically rejected instead of shown to the user.",
|
||
"properties": {
|
||
"reject": {
|
||
"$ref": "#/definitions/RejectConfig"
|
||
}
|
||
},
|
||
"required": [
|
||
"reject"
|
||
],
|
||
"title": "RejectAskForApproval",
|
||
"type": "object"
|
||
},
|
||
{
|
||
"description": "Never ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.",
|
||
"enum": [
|
||
"never"
|
||
],
|
||
"type": "string"
|
||
}
|
||
]
|
||
},
|
||
"ForcedLoginMethod": {
|
||
"enum": [
|
||
"chatgpt",
|
||
"api"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"Profile": {
|
||
"properties": {
|
||
"approvalPolicy": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/AskForApproval"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"chatgptBaseUrl": {
|
||
"type": [
|
||
"string",
|
||
"null"
|
||
]
|
||
},
|
||
"model": {
|
||
"type": [
|
||
"string",
|
||
"null"
|
||
]
|
||
},
|
||
"modelProvider": {
|
||
"type": [
|
||
"string",
|
||
"null"
|
||
]
|
||
},
|
||
"modelReasoningEffort": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/ReasoningEffort"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"modelReasoningSummary": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/ReasoningSummary"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"modelVerbosity": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/Verbosity"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"type": "object"
|
||
},
|
||
"ReasoningEffort": {
|
||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||
"enum": [
|
||
"none",
|
||
"minimal",
|
||
"low",
|
||
"medium",
|
||
"high",
|
||
"xhigh"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"ReasoningSummary": {
|
||
"description": "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
|
||
"oneOf": [
|
||
{
|
||
"enum": [
|
||
"auto",
|
||
"concise",
|
||
"detailed"
|
||
],
|
||
"type": "string"
|
||
},
|
||
{
|
||
"description": "Option to disable reasoning summaries.",
|
||
"enum": [
|
||
"none"
|
||
],
|
||
"type": "string"
|
||
}
|
||
]
|
||
},
|
||
"RejectConfig": {
|
||
"properties": {
|
||
"mcp_elicitations": {
|
||
"description": "Reject MCP elicitation prompts.",
|
||
"type": "boolean"
|
||
},
|
||
"rules": {
|
||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||
"type": "boolean"
|
||
},
|
||
"sandbox_approval": {
|
||
"description": "Reject approval prompts related to sandbox escalation.",
|
||
"type": "boolean"
|
||
}
|
||
},
|
||
"required": [
|
||
"mcp_elicitations",
|
||
"rules",
|
||
"sandbox_approval"
|
||
],
|
||
"type": "object"
|
||
},
|
||
"SandboxMode": {
|
||
"enum": [
|
||
"read-only",
|
||
"workspace-write",
|
||
"danger-full-access"
|
||
],
|
||
"type": "string"
|
||
},
|
||
"SandboxSettings": {
|
||
"properties": {
|
||
"excludeSlashTmp": {
|
||
"type": [
|
||
"boolean",
|
||
"null"
|
||
]
|
||
},
|
||
"excludeTmpdirEnvVar": {
|
||
"type": [
|
||
"boolean",
|
||
"null"
|
||
]
|
||
},
|
||
"networkAccess": {
|
||
"type": [
|
||
"boolean",
|
||
"null"
|
||
]
|
||
},
|
||
"writableRoots": {
|
||
"default": [],
|
||
"items": {
|
||
"$ref": "#/definitions/AbsolutePathBuf"
|
||
},
|
||
"type": "array"
|
||
}
|
||
},
|
||
"type": "object"
|
||
},
|
||
"Tools": {
|
||
"properties": {
|
||
"viewImage": {
|
||
"type": [
|
||
"boolean",
|
||
"null"
|
||
]
|
||
},
|
||
"webSearch": {
|
||
"type": [
|
||
"boolean",
|
||
"null"
|
||
]
|
||
}
|
||
},
|
||
"type": "object"
|
||
},
|
||
"UserSavedConfig": {
|
||
"properties": {
|
||
"approvalPolicy": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/AskForApproval"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"forcedChatgptWorkspaceId": {
|
||
"type": [
|
||
"string",
|
||
"null"
|
||
]
|
||
},
|
||
"forcedLoginMethod": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/ForcedLoginMethod"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"model": {
|
||
"type": [
|
||
"string",
|
||
"null"
|
||
]
|
||
},
|
||
"modelReasoningEffort": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/ReasoningEffort"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"modelReasoningSummary": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/ReasoningSummary"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"modelVerbosity": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/Verbosity"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"profile": {
|
||
"type": [
|
||
"string",
|
||
"null"
|
||
]
|
||
},
|
||
"profiles": {
|
||
"additionalProperties": {
|
||
"$ref": "#/definitions/Profile"
|
||
},
|
||
"type": "object"
|
||
},
|
||
"sandboxMode": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/SandboxMode"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"sandboxSettings": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/SandboxSettings"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"tools": {
|
||
"anyOf": [
|
||
{
|
||
"$ref": "#/definitions/Tools"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"required": [
|
||
"profiles"
|
||
],
|
||
"type": "object"
|
||
},
|
||
"Verbosity": {
|
||
"description": "Controls output length/detail on GPT-5 models via the Responses API. Serialized with lowercase values to match the OpenAI API.",
|
||
"enum": [
|
||
"low",
|
||
"medium",
|
||
"high"
|
||
],
|
||
"type": "string"
|
||
}
|
||
},
|
||
"properties": {
|
||
"config": {
|
||
"$ref": "#/definitions/UserSavedConfig"
|
||
}
|
||
},
|
||
"required": [
|
||
"config"
|
||
],
|
||
"title": "GetUserSavedConfigResponse",
|
||
"type": "object"
|
||
} |