Download codex-rs/core/src/tools/sandboxing_tests.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 14.4 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/core/src/tools/sandboxing_tests.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/core/src/tools/sandboxing_tests.rs
-
curl -L -o sandboxing_tests.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/core/src/tools/sandboxing_tests.rs
14.4 kB
| use super::*; | |
| use crate::sandboxing::SandboxPermissions; | |
| use crate::tools::hook_names::HookToolName; | |
| use codex_network_proxy::ManagedNetworkSandboxContext; | |
| use codex_protocol::permissions::FileSystemAccessMode; | |
| use codex_protocol::permissions::FileSystemPath; | |
| use codex_protocol::permissions::FileSystemSandboxEntry; | |
| use codex_protocol::permissions::FileSystemSpecialPath; | |
| use codex_protocol::permissions::NetworkSandboxPolicy; | |
| use codex_protocol::protocol::GranularApprovalConfig; | |
| use codex_sandboxing::SandboxCommand; | |
| use codex_sandboxing::SandboxManager; | |
| use codex_sandboxing::SandboxType; | |
| use codex_utils_absolute_path::AbsolutePathBuf; | |
| use codex_utils_path_uri::PathUri; | |
| use pretty_assertions::assert_eq; | |
| use serde_json::json; | |
| use std::collections::HashMap; | |
| fn bash_permission_request_payload_omits_missing_description() { | |
| assert_eq!( | |
| PermissionRequestPayload::bash("echo hi".to_string(), /*description*/ None), | |
| PermissionRequestPayload { | |
| tool_name: HookToolName::bash(), | |
| tool_input: json!({ "command": "echo hi" }), | |
| } | |
| ); | |
| } | |
| fn bash_permission_request_payload_includes_description_when_present() { | |
| assert_eq!( | |
| PermissionRequestPayload::bash( | |
| "echo hi".to_string(), | |
| Some("network-access example.com".to_string()), | |
| ), | |
| PermissionRequestPayload { | |
| tool_name: HookToolName::bash(), | |
| tool_input: json!({ | |
| "command": "echo hi", | |
| "description": "network-access example.com", | |
| }), | |
| } | |
| ); | |
| } | |
| fn external_sandbox_skips_exec_approval_on_request() { | |
| assert_eq!( | |
| default_exec_approval_requirement( | |
| AskForApproval::OnRequest, | |
| &FileSystemSandboxPolicy::external_sandbox(), | |
| ), | |
| ExecApprovalRequirement::Skip { | |
| bypass_sandbox: false, | |
| proposed_execpolicy_amendment: None, | |
| } | |
| ); | |
| } | |
| fn restricted_sandbox_requires_exec_approval_on_request() { | |
| assert_eq!( | |
| default_exec_approval_requirement( | |
| AskForApproval::OnRequest, | |
| &FileSystemSandboxPolicy::default() | |
| ), | |
| ExecApprovalRequirement::NeedsApproval { | |
| reason: None, | |
| proposed_execpolicy_amendment: None, | |
| } | |
| ); | |
| } | |
| fn default_exec_approval_requirement_rejects_sandbox_prompt_when_granular_disables_it() { | |
| let policy = AskForApproval::Granular(GranularApprovalConfig { | |
| sandbox_approval: false, | |
| rules: true, | |
| skill_approval: true, | |
| request_permissions: true, | |
| mcp_elicitations: true, | |
| }); | |
| let requirement = | |
| default_exec_approval_requirement(policy, &FileSystemSandboxPolicy::default()); | |
| assert_eq!( | |
| requirement, | |
| ExecApprovalRequirement::Forbidden { | |
| reason: "approval policy disallowed sandbox approval prompt".to_string(), | |
| } | |
| ); | |
| } | |
| fn default_exec_approval_requirement_keeps_prompt_when_granular_allows_sandbox_approval() { | |
| let policy = AskForApproval::Granular(GranularApprovalConfig { | |
| sandbox_approval: true, | |
| rules: false, | |
| skill_approval: true, | |
| request_permissions: true, | |
| mcp_elicitations: false, | |
| }); | |
| let requirement = | |
| default_exec_approval_requirement(policy, &FileSystemSandboxPolicy::default()); | |
| assert_eq!( | |
| requirement, | |
| ExecApprovalRequirement::NeedsApproval { | |
| reason: None, | |
| proposed_execpolicy_amendment: None, | |
| } | |
| ); | |
| } | |
| fn additional_permissions_allow_bypass_sandbox_first_attempt_when_execpolicy_skips() { | |
| assert_eq!( | |
| sandbox_override_for_first_attempt( | |
| SandboxPermissions::WithAdditionalPermissions, | |
| &ExecApprovalRequirement::Skip { | |
| bypass_sandbox: true, | |
| proposed_execpolicy_amendment: None, | |
| }, | |
| &FileSystemSandboxPolicy::default(), | |
| ), | |
| SandboxOverride::BypassSandboxFirstAttempt | |
| ); | |
| } | |
| fn guardian_bypasses_sandbox_for_explicit_escalation_on_first_attempt() { | |
| assert_eq!( | |
| sandbox_override_for_first_attempt( | |
| SandboxPermissions::RequireEscalated, | |
| &ExecApprovalRequirement::Skip { | |
| bypass_sandbox: false, | |
| proposed_execpolicy_amendment: None, | |
| }, | |
| &FileSystemSandboxPolicy::default(), | |
| ), | |
| SandboxOverride::BypassSandboxFirstAttempt | |
| ); | |
| } | |
| fn deny_read_blocks_explicit_escalation_and_policy_bypass() { | |
| let file_system_policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry { | |
| path: FileSystemPath::GlobPattern { | |
| pattern: "**/*.env".to_string(), | |
| }, | |
| access: FileSystemAccessMode::Deny, | |
| missing_path_behavior: None, | |
| }]); | |
| assert_eq!( | |
| sandbox_override_for_first_attempt( | |
| SandboxPermissions::RequireEscalated, | |
| &ExecApprovalRequirement::Skip { | |
| bypass_sandbox: false, | |
| proposed_execpolicy_amendment: None, | |
| }, | |
| &file_system_policy, | |
| ), | |
| SandboxOverride::NoOverride, | |
| "explicit escalation would drop deny-read filesystem policy, so keep the first attempt sandboxed", | |
| ); | |
| assert!(!unsandboxed_execution_allowed(&file_system_policy)); | |
| assert_eq!( | |
| sandbox_permissions_preserving_denied_reads( | |
| SandboxPermissions::RequireEscalated, | |
| &file_system_policy, | |
| ), | |
| SandboxPermissions::UseDefault, | |
| ); | |
| assert_eq!( | |
| sandbox_permissions_preserving_denied_reads( | |
| SandboxPermissions::WithAdditionalPermissions, | |
| &file_system_policy, | |
| ), | |
| SandboxPermissions::WithAdditionalPermissions, | |
| ); | |
| assert_eq!( | |
| sandbox_permissions_preserving_denied_reads( | |
| SandboxPermissions::RequireEscalated, | |
| &FileSystemSandboxPolicy::default(), | |
| ), | |
| SandboxPermissions::RequireEscalated, | |
| ); | |
| assert_eq!( | |
| sandbox_override_for_first_attempt( | |
| SandboxPermissions::WithAdditionalPermissions, | |
| &ExecApprovalRequirement::Skip { | |
| bypass_sandbox: true, | |
| proposed_execpolicy_amendment: None, | |
| }, | |
| &file_system_policy, | |
| ), | |
| SandboxOverride::NoOverride, | |
| "exec-policy allow rules would drop deny-read filesystem policy, so keep the first attempt sandboxed", | |
| ); | |
| } | |
| fn windows_sandbox_env_preserves_denied_reads_or_rejects_unsupported_backend() { | |
| let temp_dir = tempfile::TempDir::new().expect("create sandbox workspace"); | |
| let cwd = AbsolutePathBuf::from_absolute_path( | |
| dunce::canonicalize(temp_dir.path()).expect("canonicalize sandbox workspace"), | |
| ) | |
| .expect("absolute sandbox workspace"); | |
| let denied_path = cwd.join("blocked"); | |
| std::fs::create_dir_all(denied_path.as_path()).expect("create denied directory"); | |
| let denied_path = AbsolutePathBuf::from_absolute_path( | |
| dunce::canonicalize(denied_path.as_path()).expect("canonicalize denied directory"), | |
| ) | |
| .expect("absolute denied directory"); | |
| let file_system_policy = FileSystemSandboxPolicy::restricted(vec![ | |
| FileSystemSandboxEntry { | |
| path: FileSystemPath::Special { | |
| value: FileSystemSpecialPath::Root, | |
| }, | |
| access: FileSystemAccessMode::Read, | |
| missing_path_behavior: None, | |
| }, | |
| FileSystemSandboxEntry { | |
| path: FileSystemPath::Special { | |
| value: FileSystemSpecialPath::project_roots(/*subpath*/ None), | |
| }, | |
| access: FileSystemAccessMode::Write, | |
| missing_path_behavior: None, | |
| }, | |
| FileSystemSandboxEntry { | |
| path: FileSystemPath::Path { | |
| path: denied_path.clone().into(), | |
| }, | |
| access: FileSystemAccessMode::Deny, | |
| missing_path_behavior: None, | |
| }, | |
| ]); | |
| let permissions = codex_protocol::models::PermissionProfile::from_runtime_permissions( | |
| &file_system_policy, | |
| NetworkSandboxPolicy::Restricted, | |
| ); | |
| let cwd_uri = PathUri::from_abs_path(&cwd); | |
| let manager = SandboxManager::new(); | |
| let mut attempt = SandboxAttempt { | |
| sandbox: SandboxType::WindowsRestrictedToken, | |
| sandbox_requested: true, | |
| permissions: &permissions, | |
| exec_server_permissions: &permissions, | |
| enforce_managed_network: false, | |
| manager: &manager, | |
| sandbox_cwd: &cwd_uri, | |
| workspace_roots: std::slice::from_ref(&cwd_uri), | |
| sandbox_exe: None, | |
| use_legacy_landlock: false, | |
| windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Elevated, | |
| windows_sandbox_private_desktop: false, | |
| network_denial_cancellation_token: None, | |
| network_proxy: None, | |
| }; | |
| let command = || SandboxCommand { | |
| program: "cmd.exe".into(), | |
| args: vec!["/C".to_string(), "echo sandboxed".to_string()], | |
| cwd: cwd_uri.clone(), | |
| env: HashMap::new(), | |
| managed_network: None, | |
| additional_permissions: None, | |
| }; | |
| let options = || crate::sandboxing::ExecOptions { | |
| expiration: crate::exec::ExecExpiration::DefaultTimeout, | |
| capture_policy: crate::exec::ExecCapturePolicy::ShellTool, | |
| }; | |
| let request = attempt | |
| .env_for( | |
| command(), | |
| options(), | |
| /*network*/ None, | |
| /*environment_id*/ None, | |
| ) | |
| .expect("prepare elevated Windows sandbox request"); | |
| let overrides = request | |
| .windows_sandbox_filesystem_overrides | |
| .expect("elevated Windows sandbox should preserve deny-read overrides"); | |
| assert_eq!(overrides.additional_deny_read_paths, vec![denied_path]); | |
| assert_eq!(request.windows_sandbox_workspace_roots, vec![cwd]); | |
| attempt.windows_sandbox_level = | |
| codex_protocol::config_types::WindowsSandboxLevel::RestrictedToken; | |
| let error = attempt | |
| .env_for( | |
| command(), | |
| options(), | |
| /*network*/ None, | |
| /*environment_id*/ None, | |
| ) | |
| .expect_err("restricted-token Windows sandbox cannot enforce deny-read restrictions"); | |
| assert_eq!( | |
| error.to_string(), | |
| "unsupported operation: windows unelevated restricted-token sandbox cannot enforce deny-read restrictions directly; refusing to run unsandboxed" | |
| ); | |
| } | |
| fn exec_server_env_keeps_command_native_and_carries_sandbox_context() { | |
| let cwd: AbsolutePathBuf = std::env::current_dir() | |
| .expect("current dir") | |
| .try_into() | |
| .expect("absolute cwd"); | |
| let cwd_uri = PathUri::from_abs_path(&cwd); | |
| let exec_server_permissions = codex_protocol::models::PermissionProfile::workspace_write(); | |
| let permissions = exec_server_permissions | |
| .clone() | |
| .materialize_project_roots_with_workspace_roots(std::slice::from_ref(&cwd)); | |
| let manager = SandboxManager::new(); | |
| let mut attempt = SandboxAttempt { | |
| sandbox: SandboxType::None, | |
| sandbox_requested: true, | |
| permissions: &permissions, | |
| exec_server_permissions: &exec_server_permissions, | |
| enforce_managed_network: true, | |
| manager: &manager, | |
| sandbox_cwd: &cwd_uri, | |
| workspace_roots: std::slice::from_ref(&cwd_uri), | |
| sandbox_exe: None, | |
| use_legacy_landlock: false, | |
| windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Disabled, | |
| windows_sandbox_private_desktop: false, | |
| network_denial_cancellation_token: None, | |
| network_proxy: None, | |
| }; | |
| let managed_network = ManagedNetworkSandboxContext { | |
| loopback_ports: vec![43123], | |
| allow_local_binding: false, | |
| ..Default::default() | |
| }; | |
| let command = || SandboxCommand { | |
| program: "/bin/bash".into(), | |
| args: vec!["-lc".to_string(), "pwd".to_string()], | |
| cwd: cwd_uri.clone(), | |
| env: HashMap::new(), | |
| managed_network: Some(managed_network.clone()), | |
| additional_permissions: None, | |
| }; | |
| let options = || crate::sandboxing::ExecOptions { | |
| expiration: crate::exec::ExecExpiration::DefaultTimeout, | |
| capture_policy: crate::exec::ExecCapturePolicy::ShellTool, | |
| }; | |
| let request = attempt | |
| .env_for_exec_server(command(), options()) | |
| .expect("prepare remote exec request"); | |
| assert!(!attempt.is_escalated()); | |
| assert_eq!( | |
| request.command, | |
| vec![ | |
| "/bin/bash".to_string(), | |
| "-lc".to_string(), | |
| "pwd".to_string() | |
| ] | |
| ); | |
| assert_eq!(request.arg0, None); | |
| assert_eq!(request.sandbox, SandboxType::None); | |
| assert_eq!( | |
| request.exec_server_sandbox, | |
| Some(codex_exec_server::FileSystemSandboxContext { | |
| permissions: exec_server_permissions.clone().into(), | |
| cwd: Some(cwd_uri.clone()), | |
| workspace_roots: vec![cwd_uri.clone()], | |
| user_home_dir: None, | |
| temporary_directories: None, | |
| windows_sandbox_selection: if cfg!(windows) { | |
| codex_file_system::WindowsSandboxSelection::RestrictedToken | |
| } else { | |
| codex_file_system::WindowsSandboxSelection::Disabled | |
| }, | |
| windows_sandbox_private_desktop: false, | |
| windows_sandbox_proxy_settings_mode: None, | |
| use_legacy_landlock: false, | |
| }) | |
| ); | |
| assert!(request.exec_server_enforce_managed_network); | |
| assert_eq!( | |
| request.exec_server_managed_network, | |
| Some(managed_network.clone()) | |
| ); | |
| attempt.sandbox_requested = false; | |
| let request = attempt | |
| .env_for_exec_server(command(), options()) | |
| .expect("prepare unsandboxed remote exec request"); | |
| assert!(attempt.is_escalated()); | |
| assert_eq!(request.exec_server_sandbox, None); | |
| assert!(!request.exec_server_enforce_managed_network); | |
| assert_eq!(request.exec_server_managed_network, Some(managed_network)); | |
| let full_access = codex_protocol::models::PermissionProfile::Disabled; | |
| attempt.permissions = &full_access; | |
| attempt.exec_server_permissions = &full_access; | |
| attempt.enforce_managed_network = false; | |
| assert!(!attempt.is_escalated(), "full access is not an escalation"); | |
| } | |