mirror of
https://github.com/openai/codex.git
synced 2026-10-23 18:08:45 +00:00
feat: add active network proxy guidance
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -24,6 +24,7 @@ const APPROVAL_POLICY_ON_REQUEST_RULE: &str =
|
||||
const APPROVAL_POLICY_ON_REQUEST_RULE_REQUEST_PERMISSION: &str =
|
||||
include_str!("prompts/permissions/approval_policy/on_request_rule_request_permission.md");
|
||||
const AUTO_REVIEW_APPROVAL_SUFFIX: &str = "`approvals_reviewer` is `auto_review`: Sandbox escalations with require_escalated will be reviewed for compliance with the policy. If a rejection happens, you should proceed only with a materially safer alternative, or inform the user of the risk and send a final message to ask for approval.";
|
||||
const NETWORK_PROXY: &str = include_str!("prompts/permissions/network_proxy.md");
|
||||
|
||||
const SANDBOX_MODE_DANGER_FULL_ACCESS: &str =
|
||||
include_str!("prompts/permissions/sandbox_mode/danger_full_access.md");
|
||||
@@ -50,6 +51,7 @@ struct PermissionsPromptConfig<'a> {
|
||||
exec_policy: &'a Policy,
|
||||
exec_permission_approvals_enabled: bool,
|
||||
request_permissions_tool_enabled: bool,
|
||||
managed_network_proxy_active: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -68,6 +70,7 @@ impl PermissionsInstructions {
|
||||
cwd: &Path,
|
||||
exec_permission_approvals_enabled: bool,
|
||||
request_permissions_tool_enabled: bool,
|
||||
managed_network_proxy_active: bool,
|
||||
) -> Self {
|
||||
let (sandbox_mode, writable_roots) = sandbox_prompt_from_profile(permission_profile, cwd);
|
||||
|
||||
@@ -80,6 +83,7 @@ impl PermissionsInstructions {
|
||||
exec_policy,
|
||||
exec_permission_approvals_enabled,
|
||||
request_permissions_tool_enabled,
|
||||
managed_network_proxy_active,
|
||||
},
|
||||
writable_roots,
|
||||
)
|
||||
@@ -94,6 +98,7 @@ impl PermissionsInstructions {
|
||||
cwd: &Path,
|
||||
exec_permission_approvals_enabled: bool,
|
||||
request_permissions_tool_enabled: bool,
|
||||
managed_network_proxy_active: bool,
|
||||
) -> Self {
|
||||
Self::from_permission_profile(
|
||||
&PermissionProfile::from_legacy_sandbox_policy(sandbox_policy),
|
||||
@@ -103,6 +108,7 @@ impl PermissionsInstructions {
|
||||
cwd,
|
||||
exec_permission_approvals_enabled,
|
||||
request_permissions_tool_enabled,
|
||||
managed_network_proxy_active,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -114,6 +120,9 @@ impl PermissionsInstructions {
|
||||
) -> Self {
|
||||
let mut text = String::new();
|
||||
append_section(&mut text, &sandbox_text(sandbox_mode, network_access));
|
||||
if config.managed_network_proxy_active {
|
||||
append_section(&mut text, NETWORK_PROXY.trim_end());
|
||||
}
|
||||
append_section(
|
||||
&mut text,
|
||||
&approval_text(
|
||||
|
||||
@@ -38,6 +38,7 @@ fn builds_permissions_with_network_access_override() {
|
||||
exec_policy: &Policy::empty(),
|
||||
exec_permission_approvals_enabled: false,
|
||||
request_permissions_tool_enabled: false,
|
||||
managed_network_proxy_active: false,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
@@ -70,6 +71,7 @@ fn builds_permissions_from_policy() {
|
||||
&PathBuf::from("/tmp"),
|
||||
/*exec_permission_approvals_enabled*/ false,
|
||||
/*request_permissions_tool_enabled*/ false,
|
||||
/*managed_network_proxy_active*/ false,
|
||||
);
|
||||
let text = instructions.body();
|
||||
assert!(text.contains("Network access is enabled."));
|
||||
@@ -99,6 +101,7 @@ fn builds_permissions_from_profile() {
|
||||
&cwd,
|
||||
/*exec_permission_approvals_enabled*/ false,
|
||||
/*request_permissions_tool_enabled*/ false,
|
||||
/*managed_network_proxy_active*/ false,
|
||||
);
|
||||
let text = instructions.body();
|
||||
assert!(text.contains("`sandbox_mode` is `workspace-write`"));
|
||||
@@ -106,6 +109,47 @@ fn builds_permissions_from_profile() {
|
||||
assert!(text.contains(writable_root.to_string_lossy().as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_network_proxy_guidance_when_managed_proxy_is_active() {
|
||||
let instructions = PermissionsInstructions::from_permissions_with_network(
|
||||
SandboxMode::WorkspaceWrite,
|
||||
NetworkAccess::Restricted,
|
||||
PermissionsPromptConfig {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
exec_policy: &Policy::empty(),
|
||||
exec_permission_approvals_enabled: false,
|
||||
request_permissions_tool_enabled: false,
|
||||
managed_network_proxy_active: true,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
|
||||
let text = instructions.body();
|
||||
assert!(text.contains("# Network Proxy"));
|
||||
assert!(text.contains("blocked-by-allowlist"));
|
||||
assert!(text.contains("proxy-specific headers or messages"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn omits_network_proxy_guidance_when_managed_proxy_is_inactive() {
|
||||
let instructions = PermissionsInstructions::from_permissions_with_network(
|
||||
SandboxMode::WorkspaceWrite,
|
||||
NetworkAccess::Restricted,
|
||||
PermissionsPromptConfig {
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
exec_policy: &Policy::empty(),
|
||||
exec_permission_approvals_enabled: false,
|
||||
request_permissions_tool_enabled: false,
|
||||
managed_network_proxy_active: false,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
|
||||
assert!(!instructions.body().contains("# Network Proxy"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_request_rule_instructions_for_on_request() {
|
||||
let mut exec_policy = Policy::empty();
|
||||
@@ -121,6 +165,7 @@ fn includes_request_rule_instructions_for_on_request() {
|
||||
exec_policy: &exec_policy,
|
||||
exec_permission_approvals_enabled: false,
|
||||
request_permissions_tool_enabled: false,
|
||||
managed_network_proxy_active: false,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
@@ -142,6 +187,7 @@ fn includes_request_permissions_tool_instructions_for_unless_trusted_when_enable
|
||||
exec_policy: &Policy::empty(),
|
||||
exec_permission_approvals_enabled: false,
|
||||
request_permissions_tool_enabled: true,
|
||||
managed_network_proxy_active: false,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
@@ -162,6 +208,7 @@ fn includes_request_permissions_tool_instructions_for_on_failure_when_enabled()
|
||||
exec_policy: &Policy::empty(),
|
||||
exec_permission_approvals_enabled: false,
|
||||
request_permissions_tool_enabled: true,
|
||||
managed_network_proxy_active: false,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
@@ -182,6 +229,7 @@ fn includes_request_permission_rule_instructions_for_on_request_when_enabled() {
|
||||
exec_policy: &Policy::empty(),
|
||||
exec_permission_approvals_enabled: true,
|
||||
request_permissions_tool_enabled: false,
|
||||
managed_network_proxy_active: false,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
@@ -202,6 +250,7 @@ fn includes_request_permissions_tool_instructions_for_on_request_when_tool_is_en
|
||||
exec_policy: &Policy::empty(),
|
||||
exec_permission_approvals_enabled: false,
|
||||
request_permissions_tool_enabled: true,
|
||||
managed_network_proxy_active: false,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
@@ -222,6 +271,7 @@ fn on_request_includes_tool_guidance_alongside_inline_permission_guidance_when_b
|
||||
exec_policy: &Policy::empty(),
|
||||
exec_permission_approvals_enabled: true,
|
||||
request_permissions_tool_enabled: true,
|
||||
managed_network_proxy_active: false,
|
||||
},
|
||||
/*writable_roots*/ None,
|
||||
);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Network Proxy
|
||||
|
||||
A managed network proxy is active for model-initiated shell commands. Codex applies proxy environment variables automatically so outbound traffic is checked against the configured network policy.
|
||||
|
||||
Honor any `<network>` allow/deny entries in the environment context. Use normal network tools without clearing or overriding proxy-related environment variables. If a required host is not allowed, request additional network permissions instead of working around the proxy.
|
||||
|
||||
Interpret proxy failures precisely:
|
||||
- `blocked-by-allowlist` means the host is not allowed by the current network policy.
|
||||
- `blocked-by-denylist` means the host is explicitly denied by policy.
|
||||
- `blocked-by-method-policy` means the current network mode disallows that request method.
|
||||
- `blocked-by-mitm-required` means limited HTTPS cannot be enforced for that request without MITM support.
|
||||
- A message about local/private network addresses means the sandbox is blocking local or private targets.
|
||||
|
||||
Do not infer a proxy denial from a generic network failure alone. Timeouts, hangs, DNS errors, TLS errors, and connection failures are only evidence of proxy policy when accompanied by proxy-specific headers or messages.
|
||||
@@ -64,6 +64,7 @@ fn build_permissions_update_item(
|
||||
&next.cwd,
|
||||
next.features.enabled(Feature::ExecPermissionApprovals),
|
||||
next.features.enabled(Feature::RequestPermissionsTool),
|
||||
next.network.is_some(),
|
||||
)
|
||||
.render(),
|
||||
)
|
||||
|
||||
@@ -2579,6 +2579,7 @@ impl Session {
|
||||
turn_context
|
||||
.features
|
||||
.enabled(Feature::RequestPermissionsTool),
|
||||
turn_context.network.is_some(),
|
||||
)
|
||||
.render(),
|
||||
);
|
||||
|
||||
@@ -583,6 +583,7 @@ async fn permissions_message_includes_writable_roots() -> Result<()> {
|
||||
test.config.cwd.as_path(),
|
||||
/*exec_permission_approvals_enabled*/ false,
|
||||
/*request_permissions_tool_enabled*/ false,
|
||||
/*managed_network_proxy_active*/ false,
|
||||
)
|
||||
.render();
|
||||
let expected_normalized = normalize_line_endings(&expected);
|
||||
|
||||
Reference in New Issue
Block a user