mirror of
https://github.com/openai/codex.git
synced 2026-09-07 15:40:00 +00:00
fix(windows-sandbox): normalize mapped-drive workdirs
This commit is contained in:
@@ -34,6 +34,7 @@ mod windows_impl {
|
||||
use crate::logging::log_failure;
|
||||
use crate::logging::log_start;
|
||||
use crate::logging::log_success;
|
||||
use crate::path_normalization::execution_path;
|
||||
use crate::policy::SandboxPolicy;
|
||||
use crate::policy::parse_policy;
|
||||
use crate::runner_client::spawn_runner_transport;
|
||||
@@ -126,6 +127,8 @@ mod windows_impl {
|
||||
write_roots_override,
|
||||
deny_write_paths_override,
|
||||
} = request;
|
||||
let cwd = execution_path(cwd);
|
||||
let sandbox_policy_cwd = execution_path(sandbox_policy_cwd);
|
||||
let policy = parse_policy(policy_json_or_preset)?;
|
||||
normalize_null_device_env(&mut env_map);
|
||||
ensure_non_interactive_pager(&mut env_map);
|
||||
@@ -186,10 +189,10 @@ mod windows_impl {
|
||||
(|| -> Result<CaptureResult> {
|
||||
let spawn_request = SpawnRequest {
|
||||
command: command.clone(),
|
||||
cwd: cwd.to_path_buf(),
|
||||
cwd: cwd.clone(),
|
||||
env: env_map.clone(),
|
||||
policy_json_or_preset: policy_json_or_preset.to_string(),
|
||||
sandbox_policy_cwd: sandbox_policy_cwd.to_path_buf(),
|
||||
sandbox_policy_cwd: sandbox_policy_cwd.clone(),
|
||||
codex_home: sandbox_base.clone(),
|
||||
real_codex_home: codex_home.to_path_buf(),
|
||||
cap_sids,
|
||||
|
||||
@@ -249,6 +249,7 @@ mod windows_impl {
|
||||
use super::logging::log_failure;
|
||||
use super::logging::log_success;
|
||||
use super::path_normalization::canonicalize_path;
|
||||
use super::path_normalization::execution_path;
|
||||
use super::policy::SandboxPolicy;
|
||||
use super::process::create_process_as_user;
|
||||
use super::sandbox_utils::ensure_codex_home_exists;
|
||||
@@ -378,7 +379,7 @@ mod windows_impl {
|
||||
#[allow(clippy::expect_used)]
|
||||
let psid_generic =
|
||||
convert_string_sid_to_sid(&caps.workspace).expect("valid workspace SID");
|
||||
let ws_sid = workspace_cap_sid_for_cwd(codex_home, cwd)?;
|
||||
let ws_sid = workspace_cap_sid_for_cwd(codex_home, ¤t_dir)?;
|
||||
#[allow(clippy::expect_used)]
|
||||
let psid_workspace =
|
||||
convert_string_sid_to_sid(&ws_sid).expect("valid workspace SID");
|
||||
@@ -411,8 +412,9 @@ mod windows_impl {
|
||||
}
|
||||
|
||||
let persist_aces = is_workspace_write;
|
||||
let normalized_policy_cwd = execution_path(sandbox_policy_cwd);
|
||||
let AllowDenyPaths { allow, mut deny } =
|
||||
compute_allow_paths(&policy, sandbox_policy_cwd, ¤t_dir, &env_map);
|
||||
compute_allow_paths(&policy, &normalized_policy_cwd, ¤t_dir, &env_map);
|
||||
for path in additional_deny_write_paths {
|
||||
if path.exists() {
|
||||
deny.insert(path.clone());
|
||||
@@ -607,13 +609,18 @@ mod windows_impl {
|
||||
#[allow(clippy::expect_used)]
|
||||
let psid_generic =
|
||||
unsafe { convert_string_sid_to_sid(&caps.workspace) }.expect("valid workspace SID");
|
||||
let ws_sid = workspace_cap_sid_for_cwd(codex_home, cwd)?;
|
||||
let current_dir = execution_path(cwd);
|
||||
let ws_sid = workspace_cap_sid_for_cwd(codex_home, ¤t_dir)?;
|
||||
#[allow(clippy::expect_used)]
|
||||
let psid_workspace =
|
||||
unsafe { convert_string_sid_to_sid(&ws_sid) }.expect("valid workspace SID");
|
||||
let current_dir = cwd.to_path_buf();
|
||||
let AllowDenyPaths { allow, deny } =
|
||||
compute_allow_paths(sandbox_policy, sandbox_policy_cwd, ¤t_dir, env_map);
|
||||
let normalized_policy_cwd = execution_path(sandbox_policy_cwd);
|
||||
let AllowDenyPaths { allow, deny } = compute_allow_paths(
|
||||
sandbox_policy,
|
||||
&normalized_policy_cwd,
|
||||
¤t_dir,
|
||||
env_map,
|
||||
);
|
||||
let canonical_cwd = canonicalize_path(¤t_dir);
|
||||
unsafe {
|
||||
for p in &allow {
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Normalize a path before handing it to Windows process-launch APIs.
|
||||
///
|
||||
/// For existing paths this prefers the canonical form, which helps mapped-drive
|
||||
/// workspaces resolve to a form the sandbox logon user can access.
|
||||
pub fn execution_path(path: &Path) -> PathBuf {
|
||||
canonicalize_path(path)
|
||||
}
|
||||
|
||||
pub fn canonicalize_path(path: &Path) -> PathBuf {
|
||||
dunce::canonicalize(path).unwrap_or_else(|_| path.to_path_buf())
|
||||
}
|
||||
@@ -23,6 +31,9 @@ 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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::execution_path;
|
||||
use crate::policy::SandboxPolicy;
|
||||
use crate::policy::parse_policy;
|
||||
use crate::sandbox_utils::ensure_codex_home_exists;
|
||||
@@ -105,11 +106,12 @@ fn prepare_spawn_context_common(
|
||||
|
||||
normalize_null_device_env(env_map);
|
||||
ensure_non_interactive_pager(env_map);
|
||||
let current_dir = execution_path(cwd);
|
||||
if inherit_path {
|
||||
inherit_path_env(env_map);
|
||||
}
|
||||
if add_git_safe_directory {
|
||||
inject_git_safe_directory(env_map, cwd);
|
||||
inject_git_safe_directory(env_map, ¤t_dir);
|
||||
}
|
||||
|
||||
ensure_codex_home_exists(codex_home)?;
|
||||
@@ -122,7 +124,7 @@ fn prepare_spawn_context_common(
|
||||
|
||||
Ok(SpawnContext {
|
||||
policy,
|
||||
current_dir: cwd.to_path_buf(),
|
||||
current_dir,
|
||||
sandbox_base,
|
||||
logs_base_dir,
|
||||
is_workspace_write,
|
||||
@@ -158,6 +160,7 @@ pub(crate) fn prepare_legacy_session_security(
|
||||
codex_home: &Path,
|
||||
cwd: &Path,
|
||||
) -> Result<LegacySessionSecurity> {
|
||||
let current_dir = execution_path(cwd);
|
||||
let caps = load_or_create_cap_sids(codex_home)?;
|
||||
let (h_token, psid_generic, psid_workspace, cap_sid_str) = unsafe {
|
||||
match policy {
|
||||
@@ -168,7 +171,7 @@ pub(crate) fn prepare_legacy_session_security(
|
||||
}
|
||||
SandboxPolicy::WorkspaceWrite { .. } => {
|
||||
let psid_generic = LocalSid::from_string(&caps.workspace)?;
|
||||
let workspace_sid = workspace_cap_sid_for_cwd(codex_home, cwd)?;
|
||||
let workspace_sid = workspace_cap_sid_for_cwd(codex_home, ¤t_dir)?;
|
||||
let psid_workspace = LocalSid::from_string(&workspace_sid)?;
|
||||
let base = get_current_token_for_restriction()?;
|
||||
let h_token = create_workspace_write_token_with_caps_from(
|
||||
@@ -273,10 +276,11 @@ pub(crate) fn prepare_elevated_spawn_context(
|
||||
/*inherit_path*/ true,
|
||||
/*add_git_safe_directory*/ true,
|
||||
)?;
|
||||
let normalized_policy_cwd = execution_path(sandbox_policy_cwd);
|
||||
|
||||
let AllowDenyPaths { allow, deny } = compute_allow_paths(
|
||||
&common.policy,
|
||||
sandbox_policy_cwd,
|
||||
&normalized_policy_cwd,
|
||||
&common.current_dir,
|
||||
env_map,
|
||||
);
|
||||
@@ -289,8 +293,8 @@ pub(crate) fn prepare_elevated_spawn_context(
|
||||
};
|
||||
let sandbox_creds = require_logon_sandbox_creds(
|
||||
&common.policy,
|
||||
sandbox_policy_cwd,
|
||||
cwd,
|
||||
&normalized_policy_cwd,
|
||||
&common.current_dir,
|
||||
env_map,
|
||||
codex_home,
|
||||
/*read_roots_override*/ None,
|
||||
@@ -306,7 +310,7 @@ pub(crate) fn prepare_elevated_spawn_context(
|
||||
vec![caps.readonly.clone()],
|
||||
),
|
||||
SandboxPolicy::WorkspaceWrite { .. } => {
|
||||
let cap_sid = workspace_cap_sid_for_cwd(codex_home, cwd)?;
|
||||
let cap_sid = workspace_cap_sid_for_cwd(codex_home, &common.current_dir)?;
|
||||
(
|
||||
LocalSid::from_string(&caps.workspace)?,
|
||||
vec![caps.workspace.clone(), cap_sid],
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::ipc_framed::EmptyPayload;
|
||||
use crate::ipc_framed::FramedMessage;
|
||||
use crate::ipc_framed::Message;
|
||||
use crate::ipc_framed::SpawnRequest;
|
||||
use crate::path_normalization::execution_path;
|
||||
use crate::runner_client::spawn_runner_transport;
|
||||
use crate::spawn_prep::prepare_elevated_spawn_context;
|
||||
use anyhow::Result;
|
||||
@@ -39,13 +40,15 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated(
|
||||
&mut env_map,
|
||||
&command,
|
||||
)?;
|
||||
let normalized_cwd = elevated.common.current_dir.clone();
|
||||
let normalized_policy_cwd = execution_path(sandbox_policy_cwd);
|
||||
|
||||
let spawn_request = SpawnRequest {
|
||||
command: command.clone(),
|
||||
cwd: cwd.to_path_buf(),
|
||||
cwd: normalized_cwd.clone(),
|
||||
env: env_map.clone(),
|
||||
policy_json_or_preset: policy_json_or_preset.to_string(),
|
||||
sandbox_policy_cwd: sandbox_policy_cwd.to_path_buf(),
|
||||
sandbox_policy_cwd: normalized_policy_cwd,
|
||||
codex_home: elevated.common.sandbox_base.clone(),
|
||||
real_codex_home: codex_home.to_path_buf(),
|
||||
cap_sids: elevated.cap_sids.clone(),
|
||||
@@ -55,12 +58,15 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated(
|
||||
use_private_desktop,
|
||||
};
|
||||
let codex_home = codex_home.to_path_buf();
|
||||
let cwd = cwd.to_path_buf();
|
||||
let sandbox_creds = elevated.sandbox_creds.clone();
|
||||
let logs_base_dir = elevated.common.logs_base_dir.clone();
|
||||
let transport = tokio::task::spawn_blocking(move || -> Result<_> {
|
||||
let mut transport =
|
||||
spawn_runner_transport(&codex_home, &cwd, &sandbox_creds, logs_base_dir.as_deref())?;
|
||||
let mut transport = spawn_runner_transport(
|
||||
&codex_home,
|
||||
&normalized_cwd,
|
||||
&sandbox_creds,
|
||||
logs_base_dir.as_deref(),
|
||||
)?;
|
||||
transport.send_spawn_request(spawn_request)?;
|
||||
transport.read_spawn_ready_with_timeout()?;
|
||||
Ok(transport)
|
||||
|
||||
Reference in New Issue
Block a user