mirror of
https://github.com/openai/codex.git
synced 2026-10-21 17:48:44 +00:00
Sandbox remote apply_patch operations (#38043)
## Why Cross-platform remote `apply_patch` calls were rejected when filesystem writes were restricted because patch verification and writes could not be safely performed against executor files. ## What changed - Route intercepted and direct remote patches through the executor-managed filesystem sandbox, including the configured workspace roots. - Select the restricted-token sandbox for Windows executor paths when no Windows sandbox level was configured. - Fail closed when an executor cannot enforce the requested sandbox, and treat executor-managed access failures as sandbox denials so approval can retry the patch without sandboxing. ## Testing - Cover sandboxed remote patches, denied writes, approval retries, Windows sandbox selection, and executor filesystem enforcement. GitOrigin-RevId: caddeed0b266c456a689080a14a3a58e2bd7887c
This commit is contained in:
@@ -13,6 +13,7 @@ use codex_sandboxing::SandboxDirectSpawnTransformRequest;
|
||||
use codex_sandboxing::SandboxExecRequest;
|
||||
use codex_sandboxing::SandboxManager;
|
||||
use codex_sandboxing::SandboxTransformRequest;
|
||||
use codex_sandboxing::SandboxType;
|
||||
use codex_sandboxing::SandboxablePreference;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_absolute_path::canonicalize_preserving_symlinks;
|
||||
@@ -114,10 +115,15 @@ impl FileSystemSandboxRunner {
|
||||
let sandbox_manager = SandboxManager::new();
|
||||
let sandbox = sandbox_manager.select_initial(
|
||||
permission_profile,
|
||||
SandboxablePreference::Auto,
|
||||
SandboxablePreference::Require,
|
||||
sandbox_context.windows_sandbox_level,
|
||||
/*has_managed_network_requirements*/ false,
|
||||
);
|
||||
if sandbox == SandboxType::None {
|
||||
return Err(invalid_request(
|
||||
"filesystem sandbox cannot be enforced on this executor".to_string(),
|
||||
));
|
||||
}
|
||||
let command = SandboxCommand {
|
||||
program: helper.as_path().as_os_str().to_owned(),
|
||||
args: vec![CODEX_FS_HELPER_ARG1.to_string()],
|
||||
@@ -545,10 +551,11 @@ mod tests {
|
||||
let runner = FileSystemSandboxRunner::new(runtime_paths);
|
||||
let native_cwd = AbsolutePathBuf::current_dir().expect("cwd");
|
||||
let cwd = PathUri::from_abs_path(&native_cwd);
|
||||
let file_system_policy = restricted_policy(vec![path_entry(
|
||||
native_cwd.clone(),
|
||||
FileSystemAccessMode::Write,
|
||||
)]);
|
||||
let file_system_policy = restricted_policy(vec![
|
||||
#[cfg(windows)]
|
||||
special_entry(FileSystemSpecialPath::Root, FileSystemAccessMode::Read),
|
||||
path_entry(native_cwd.clone(), FileSystemAccessMode::Write),
|
||||
]);
|
||||
let network_policy = NetworkSandboxPolicy::Restricted;
|
||||
let permission_profile =
|
||||
PermissionProfile::from_runtime_permissions(&file_system_policy, network_policy);
|
||||
@@ -557,6 +564,26 @@ mod tests {
|
||||
uri: cwd,
|
||||
native: native_cwd,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
let sandbox_context = {
|
||||
let error = runner
|
||||
.sandbox_exec_request(
|
||||
&permission_profile,
|
||||
&sandbox_cwd,
|
||||
std::slice::from_ref(&sandbox_cwd.native),
|
||||
&sandbox_context,
|
||||
)
|
||||
.expect_err("disabled Windows sandbox must not run the helper unsandboxed");
|
||||
assert_eq!(
|
||||
error.message,
|
||||
"filesystem sandbox cannot be enforced on this executor"
|
||||
);
|
||||
crate::FileSystemSandboxContext {
|
||||
windows_sandbox_level:
|
||||
codex_protocol::config_types::WindowsSandboxLevel::RestrictedToken,
|
||||
..sandbox_context
|
||||
}
|
||||
};
|
||||
|
||||
let request = runner
|
||||
.sandbox_exec_request(
|
||||
|
||||
@@ -756,6 +756,10 @@ pub(crate) async fn assert_sandboxed_canonicalize_resolves_directory_alias(
|
||||
/// Verifies that effective additional permissions extend a read-only sandbox with a writable root.
|
||||
#[test_case(FileSystemImplementation::Local ; "local")]
|
||||
#[test_case(FileSystemImplementation::Remote ; "remote")]
|
||||
#[cfg_attr(
|
||||
windows,
|
||||
ignore = "Windows restricted-token sandbox cannot enforce split writable roots"
|
||||
)]
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn file_system_sandboxed_write_allows_additional_write_root(
|
||||
implementation: FileSystemImplementation,
|
||||
|
||||
@@ -7,11 +7,13 @@ use codex_exec_server::ExecServerRuntimePaths;
|
||||
use codex_exec_server::ExecutorFileSystem;
|
||||
use codex_exec_server::FileSystemSandboxContext;
|
||||
use codex_exec_server::LocalFileSystem;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::permissions::FileSystemAccessMode;
|
||||
use codex_protocol::permissions::FileSystemPath;
|
||||
use codex_protocol::permissions::FileSystemSandboxEntry;
|
||||
use codex_protocol::permissions::FileSystemSandboxPolicy;
|
||||
use codex_protocol::permissions::FileSystemSpecialPath;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
|
||||
@@ -103,9 +105,25 @@ pub(crate) fn workspace_write_sandbox(
|
||||
}])
|
||||
}
|
||||
|
||||
fn sandbox_context(entries: Vec<FileSystemSandboxEntry>) -> FileSystemSandboxContext {
|
||||
FileSystemSandboxContext::from_permission_profile(PermissionProfile::from_runtime_permissions(
|
||||
&FileSystemSandboxPolicy::restricted(entries),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
))
|
||||
fn sandbox_context(mut entries: Vec<FileSystemSandboxEntry>) -> FileSystemSandboxContext {
|
||||
if cfg!(windows) {
|
||||
// Restricted-token sandboxing cannot enforce read restrictions, so leave the root
|
||||
// readable while exercising the requested write restrictions.
|
||||
entries.push(FileSystemSandboxEntry::new(
|
||||
FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
FileSystemAccessMode::Read,
|
||||
));
|
||||
}
|
||||
let mut sandbox = FileSystemSandboxContext::from_permission_profile(
|
||||
PermissionProfile::from_runtime_permissions(
|
||||
&FileSystemSandboxPolicy::restricted(entries),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
),
|
||||
);
|
||||
if cfg!(windows) {
|
||||
sandbox.windows_sandbox_level = WindowsSandboxLevel::RestrictedToken;
|
||||
}
|
||||
sandbox
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user