mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
Reshape permission request hook payload
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -448,7 +448,7 @@ async fn execve_permission_request_hook_short_circuits_prompt() -> anyhow::Resul
|
||||
expected_hook_command
|
||||
);
|
||||
assert_eq!(
|
||||
hook_inputs[0]["approval_context"]["approval_attempt"],
|
||||
hook_inputs[0]["approval_context"]["attempt"]["stage"],
|
||||
"initial"
|
||||
);
|
||||
|
||||
|
||||
@@ -1174,12 +1174,16 @@ async fn permission_request_hook_allows_shell_command_without_user_approval() ->
|
||||
assert_eq!(
|
||||
hook_inputs[0]["approval_context"],
|
||||
serde_json::json!({
|
||||
"sandbox_permissions": "use_default",
|
||||
"additional_permissions": null,
|
||||
"attempt": {
|
||||
"stage": "initial",
|
||||
"retryReason": null,
|
||||
},
|
||||
"policy": {
|
||||
"sandboxPermissions": "use_default",
|
||||
"additionalPermissions": null,
|
||||
},
|
||||
"justification": null,
|
||||
"approval_attempt": "initial",
|
||||
"retry_reason": null,
|
||||
"network_approval_context": null,
|
||||
"resource": {},
|
||||
})
|
||||
);
|
||||
assert!(
|
||||
@@ -1277,12 +1281,16 @@ async fn permission_request_hook_sees_raw_exec_command_input() -> Result<()> {
|
||||
assert_eq!(
|
||||
hook_inputs[0]["approval_context"],
|
||||
serde_json::json!({
|
||||
"sandbox_permissions": "use_default",
|
||||
"additional_permissions": null,
|
||||
"attempt": {
|
||||
"stage": "initial",
|
||||
"retryReason": null,
|
||||
},
|
||||
"policy": {
|
||||
"sandboxPermissions": "use_default",
|
||||
"additionalPermissions": null,
|
||||
},
|
||||
"justification": null,
|
||||
"approval_attempt": "initial",
|
||||
"retry_reason": null,
|
||||
"network_approval_context": null,
|
||||
"resource": {},
|
||||
})
|
||||
);
|
||||
|
||||
@@ -1355,8 +1363,7 @@ allow_local_binding = true
|
||||
.enable(Feature::CodexHooks)
|
||||
.expect("test config should allow feature update");
|
||||
config.permissions.approval_policy = Constrained::allow_any(approval_policy);
|
||||
config.permissions.sandbox_policy =
|
||||
Constrained::allow_any(sandbox_policy_for_config.clone());
|
||||
config.permissions.sandbox_policy = Constrained::allow_any(sandbox_policy_for_config);
|
||||
let layers = config
|
||||
.config_layer_stack
|
||||
.get_layers(
|
||||
@@ -1444,10 +1451,21 @@ allow_local_binding = true
|
||||
"network-access http://codex-network-test.invalid:80"
|
||||
);
|
||||
assert_eq!(
|
||||
hook_inputs[0]["approval_context"]["network_approval_context"],
|
||||
hook_inputs[0]["approval_context"],
|
||||
serde_json::json!({
|
||||
"host": "codex-network-test.invalid",
|
||||
"protocol": "http",
|
||||
"attempt": {
|
||||
"stage": "initial",
|
||||
"retryReason": null,
|
||||
},
|
||||
"policy": {
|
||||
"sandboxPermissions": "use_default",
|
||||
"additionalPermissions": null,
|
||||
},
|
||||
"justification": "codex-network-test.invalid is not in the allowed_domains",
|
||||
"resource": {
|
||||
"host": "codex-network-test.invalid",
|
||||
"protocol": "http",
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
@@ -1534,12 +1552,16 @@ async fn permission_request_hook_sees_retry_context_after_sandbox_denial() -> Re
|
||||
assert_eq!(
|
||||
hook_inputs[0]["approval_context"],
|
||||
serde_json::json!({
|
||||
"sandbox_permissions": "use_default",
|
||||
"additional_permissions": null,
|
||||
"attempt": {
|
||||
"stage": "retry",
|
||||
"retryReason": "command failed; retry without sandbox?",
|
||||
},
|
||||
"policy": {
|
||||
"sandboxPermissions": "use_default",
|
||||
"additionalPermissions": null,
|
||||
},
|
||||
"justification": null,
|
||||
"approval_attempt": "retry",
|
||||
"retry_reason": "command failed; retry without sandbox?",
|
||||
"network_approval_context": null,
|
||||
"resource": {},
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -23,21 +23,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"NetworkApprovalContext": {
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"protocol": {
|
||||
"$ref": "#/definitions/NetworkApprovalProtocol"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"host",
|
||||
"protocol"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"NetworkApprovalProtocol": {
|
||||
"enum": [
|
||||
"http",
|
||||
@@ -82,31 +67,68 @@
|
||||
"PermissionRequestApprovalContext": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"additional_permissions": {
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
"approval_attempt": {
|
||||
"$ref": "#/definitions/PermissionRequestApprovalAttempt"
|
||||
"attempt": {
|
||||
"$ref": "#/definitions/PermissionRequestAttemptContext"
|
||||
},
|
||||
"justification": {
|
||||
"type": "string"
|
||||
},
|
||||
"network_approval_context": {
|
||||
"$ref": "#/definitions/NetworkApprovalContext"
|
||||
"policy": {
|
||||
"$ref": "#/definitions/PermissionRequestPolicyContext"
|
||||
},
|
||||
"retry_reason": {
|
||||
"resource": {
|
||||
"$ref": "#/definitions/PermissionRequestResourceContext"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attempt",
|
||||
"policy",
|
||||
"resource"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PermissionRequestAttemptContext": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"retryReason": {
|
||||
"type": "string"
|
||||
},
|
||||
"sandbox_permissions": {
|
||||
"stage": {
|
||||
"$ref": "#/definitions/PermissionRequestApprovalAttempt"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"stage"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PermissionRequestPolicyContext": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"additionalPermissions": {
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
"sandboxPermissions": {
|
||||
"$ref": "#/definitions/SandboxPermissions"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"approval_attempt",
|
||||
"sandbox_permissions"
|
||||
"sandboxPermissions"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PermissionRequestResourceContext": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"protocol": {
|
||||
"$ref": "#/definitions/NetworkApprovalProtocol"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PermissionRequestToolInput": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
||||
@@ -36,7 +36,10 @@ use crate::engine::command_runner::CommandRunResult;
|
||||
use crate::engine::dispatcher;
|
||||
use crate::engine::output_parser;
|
||||
use crate::schema::PermissionRequestApprovalContext;
|
||||
use crate::schema::PermissionRequestAttemptContext;
|
||||
use crate::schema::PermissionRequestCommandInput;
|
||||
use crate::schema::PermissionRequestPolicyContext;
|
||||
use crate::schema::PermissionRequestResourceContext;
|
||||
use crate::schema::PermissionRequestToolInput;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -195,6 +198,11 @@ fn resolve_permission_request_decision<'a>(
|
||||
}
|
||||
|
||||
fn build_command_input(request: &PermissionRequestRequest) -> PermissionRequestCommandInput {
|
||||
let (host, protocol) = request
|
||||
.network_approval_context
|
||||
.as_ref()
|
||||
.map(|context| (Some(context.host.clone()), Some(context.protocol)))
|
||||
.unwrap_or((None, None));
|
||||
PermissionRequestCommandInput {
|
||||
session_id: request.session_id.to_string(),
|
||||
turn_id: request.turn_id.clone(),
|
||||
@@ -208,12 +216,16 @@ fn build_command_input(request: &PermissionRequestRequest) -> PermissionRequestC
|
||||
command: request.command.clone(),
|
||||
},
|
||||
approval_context: PermissionRequestApprovalContext {
|
||||
sandbox_permissions: request.sandbox_permissions,
|
||||
additional_permissions: request.additional_permissions.clone(),
|
||||
attempt: PermissionRequestAttemptContext {
|
||||
stage: request.approval_attempt,
|
||||
retry_reason: request.retry_reason.clone(),
|
||||
},
|
||||
policy: PermissionRequestPolicyContext {
|
||||
sandbox_permissions: request.sandbox_permissions,
|
||||
additional_permissions: request.additional_permissions.clone(),
|
||||
},
|
||||
justification: request.justification.clone(),
|
||||
approval_attempt: request.approval_attempt,
|
||||
retry_reason: request.retry_reason.clone(),
|
||||
network_approval_context: request.network_approval_context.clone(),
|
||||
resource: PermissionRequestResourceContext { host, protocol },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use serde_json::Value;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_protocol::approvals::NetworkApprovalContext;
|
||||
use codex_protocol::approvals::NetworkApprovalProtocol;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::models::SandboxPermissions;
|
||||
|
||||
@@ -251,14 +251,38 @@ pub(crate) struct PermissionRequestToolInput {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub(crate) struct PermissionRequestApprovalContext {
|
||||
pub(crate) struct PermissionRequestAttemptContext {
|
||||
pub stage: PermissionRequestApprovalAttempt,
|
||||
pub retry_reason: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub(crate) struct PermissionRequestPolicyContext {
|
||||
pub sandbox_permissions: SandboxPermissions,
|
||||
pub additional_permissions: Option<PermissionProfile>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub(crate) struct PermissionRequestResourceContext {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub host: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub protocol: Option<NetworkApprovalProtocol>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub(crate) struct PermissionRequestApprovalContext {
|
||||
pub attempt: PermissionRequestAttemptContext,
|
||||
pub policy: PermissionRequestPolicyContext,
|
||||
pub justification: Option<String>,
|
||||
pub approval_attempt: PermissionRequestApprovalAttempt,
|
||||
pub retry_reason: Option<String>,
|
||||
pub network_approval_context: Option<NetworkApprovalContext>,
|
||||
pub resource: PermissionRequestResourceContext,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, JsonSchema)]
|
||||
|
||||
Reference in New Issue
Block a user