mirror of
https://github.com/openai/codex.git
synced 2026-09-20 12:47:38 +00:00
Handle unsupported remote Windows sandbox workspaces
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
use anyhow::Result;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use windows_sys::Win32::Storage::FileSystem::DRIVE_REMOTE;
|
||||
use windows_sys::Win32::Storage::FileSystem::GetDriveTypeW;
|
||||
|
||||
use crate::winutil::to_wide;
|
||||
|
||||
pub fn canonicalize_path(path: &Path) -> PathBuf {
|
||||
dunce::canonicalize(path).unwrap_or_else(|_| path.to_path_buf())
|
||||
@@ -12,9 +17,41 @@ pub fn canonical_path_key(path: &Path) -> String {
|
||||
.to_ascii_lowercase()
|
||||
}
|
||||
|
||||
pub fn ensure_windows_sandbox_local_path(path: &Path, context: &str) -> Result<()> {
|
||||
let raw = path.to_string_lossy();
|
||||
let normalized = normalize_windows_device_path(&raw).unwrap_or_else(|| raw.into_owned());
|
||||
if normalized.starts_with(r"\\") {
|
||||
anyhow::bail!(
|
||||
"windows sandbox does not support {context} on UNC or mapped network paths: {}. Use a local drive workspace or run without the Windows sandbox for this session.",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(root) = windows_drive_root(&normalized) {
|
||||
let drive_type = unsafe { GetDriveTypeW(to_wide(&root).as_ptr()) };
|
||||
if drive_type == DRIVE_REMOTE {
|
||||
anyhow::bail!(
|
||||
"windows sandbox does not support {context} on mapped network drives: {}. Use the underlying local drive path or run without the Windows sandbox for this session.",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn windows_drive_root(path: &str) -> Option<String> {
|
||||
let bytes = path.as_bytes();
|
||||
if bytes.len() >= 3 && bytes[0].is_ascii_alphabetic() && bytes[1] == b':' {
|
||||
return Some(format!("{}:\\", path[..1].to_ascii_uppercase()));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::canonical_path_key;
|
||||
use super::windows_drive_root;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -23,6 +60,16 @@ mod tests {
|
||||
let windows_style = Path::new(r"C:\Users\Dev\Repo");
|
||||
let slash_style = Path::new("c:/users/dev/repo");
|
||||
|
||||
assert_eq!(canonical_path_key(windows_style), canonical_path_key(slash_style));
|
||||
assert_eq!(
|
||||
canonical_path_key(windows_style),
|
||||
canonical_path_key(slash_style)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_drive_root_extracts_drive_prefix() {
|
||||
assert_eq!(windows_drive_root(r"l:\cs-web"), Some(r"L:\".to_string()));
|
||||
assert_eq!(windows_drive_root(r"C:/repo"), Some(r"C:\".to_string()));
|
||||
assert_eq!(windows_drive_root(r"\\video1\node\cs-web"), None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use crate::allow::compute_allow_paths;
|
||||
use crate::helper_materialization::helper_bin_dir;
|
||||
use crate::logging::log_note;
|
||||
use crate::path_normalization::canonical_path_key;
|
||||
use crate::path_normalization::ensure_windows_sandbox_local_path;
|
||||
use crate::policy::SandboxPolicy;
|
||||
use crate::setup_error::SetupErrorCode;
|
||||
use crate::setup_error::SetupFailure;
|
||||
@@ -167,6 +168,13 @@ fn run_setup_refresh_inner(
|
||||
}
|
||||
let (read_roots, write_roots) = build_payload_roots(&request, &overrides);
|
||||
let deny_write_paths = build_payload_deny_write_paths(&request, overrides.deny_write_paths);
|
||||
ensure_windows_sandbox_local_path(request.command_cwd, "sandbox working directory")?;
|
||||
for root in &write_roots {
|
||||
ensure_windows_sandbox_local_path(root, "sandbox writable root")?;
|
||||
}
|
||||
for path in &deny_write_paths {
|
||||
ensure_windows_sandbox_local_path(path, "sandbox protected path")?;
|
||||
}
|
||||
let network_identity =
|
||||
SandboxNetworkIdentity::from_policy(request.policy, request.proxy_enforced);
|
||||
let offline_proxy_settings = offline_proxy_settings_from_env(request.env_map, network_identity);
|
||||
|
||||
@@ -13,6 +13,7 @@ use crate::identity::SandboxCreds;
|
||||
use crate::identity::require_logon_sandbox_creds;
|
||||
use crate::logging::log_start;
|
||||
use crate::path_normalization::canonicalize_path;
|
||||
use crate::path_normalization::ensure_windows_sandbox_local_path;
|
||||
use crate::policy::SandboxPolicy;
|
||||
use crate::policy::parse_policy;
|
||||
use crate::sandbox_utils::ensure_codex_home_exists;
|
||||
@@ -103,6 +104,8 @@ fn prepare_spawn_context_common(
|
||||
anyhow::bail!("DangerFullAccess and ExternalSandbox are not supported for sandboxing")
|
||||
}
|
||||
|
||||
ensure_windows_sandbox_local_path(cwd, "sandbox working directory")?;
|
||||
|
||||
normalize_null_device_env(env_map);
|
||||
ensure_non_interactive_pager(env_map);
|
||||
if inherit_path {
|
||||
@@ -282,6 +285,12 @@ pub(crate) fn prepare_elevated_spawn_context(
|
||||
);
|
||||
let write_roots: Vec<PathBuf> = allow.into_iter().collect();
|
||||
let deny_write_paths: Vec<PathBuf> = deny.into_iter().collect();
|
||||
for root in &write_roots {
|
||||
ensure_windows_sandbox_local_path(root, "sandbox writable root")?;
|
||||
}
|
||||
for path in &deny_write_paths {
|
||||
ensure_windows_sandbox_local_path(path, "sandbox protected path")?;
|
||||
}
|
||||
let write_roots_override = if common.is_workspace_write {
|
||||
Some(write_roots.as_slice())
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user