mirror of
https://github.com/openai/codex.git
synced 2026-09-08 15:50:34 +00:00
fix(windows): clear stale protected ACLs in full access
This commit is contained in:
@@ -350,6 +350,13 @@ pub(crate) async fn execute_exec_request(
|
||||
arg0,
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
maybe_cleanup_stale_windows_sandbox_denies(
|
||||
sandbox_policy,
|
||||
params.windows_sandbox_level,
|
||||
¶ms.cwd,
|
||||
)?;
|
||||
|
||||
let start = Instant::now();
|
||||
let raw_output_result = exec(
|
||||
params,
|
||||
@@ -379,6 +386,30 @@ fn extract_create_process_as_user_error_code(err: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn maybe_cleanup_stale_windows_sandbox_denies(
|
||||
sandbox_policy: &SandboxPolicy,
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
cwd: &Path,
|
||||
) -> Result<()> {
|
||||
if !matches!(windows_sandbox_level, WindowsSandboxLevel::Elevated)
|
||||
|| !matches!(
|
||||
sandbox_policy,
|
||||
SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. }
|
||||
)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let codex_home = crate::config::find_codex_home().map_err(|err| {
|
||||
CodexErr::Io(io::Error::other(format!(
|
||||
"windows sandbox: failed to resolve codex_home for ACL cleanup: {err}"
|
||||
)))
|
||||
})?;
|
||||
crate::windows_sandbox::cleanup_stale_protected_write_denies(cwd, codex_home.as_ref())
|
||||
.map_err(|err| CodexErr::Io(io::Error::other(format!("windows sandbox: {err}"))))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn windowsapps_path_kind(path: &str) -> &'static str {
|
||||
let lower = path.to_ascii_lowercase();
|
||||
|
||||
@@ -192,6 +192,22 @@ pub fn run_elevated_setup(
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn cleanup_stale_protected_write_denies(
|
||||
command_cwd: &Path,
|
||||
codex_home: &Path,
|
||||
) -> anyhow::Result<()> {
|
||||
codex_windows_sandbox::cleanup_stale_protected_write_denies(command_cwd, codex_home)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn cleanup_stale_protected_write_denies(
|
||||
_command_cwd: &Path,
|
||||
_codex_home: &Path,
|
||||
) -> anyhow::Result<()> {
|
||||
anyhow::bail!("Windows sandbox ACL cleanup is only supported on Windows")
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn run_elevated_setup(
|
||||
_policy: &SandboxPolicy,
|
||||
|
||||
@@ -116,6 +116,8 @@ pub use setup::SandboxSetupRequest;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use setup::SetupRootOverrides;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use setup::cleanup_stale_protected_write_denies;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use setup::run_elevated_setup;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use setup::run_setup_refresh;
|
||||
|
||||
@@ -10,11 +10,16 @@ use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::process::Stdio;
|
||||
|
||||
use crate::acl::revoke_ace;
|
||||
use crate::allow::AllowDenyPaths;
|
||||
use crate::allow::compute_allow_paths;
|
||||
use crate::cap::load_or_create_cap_sids;
|
||||
use crate::cap::workspace_cap_sid_for_cwd;
|
||||
use crate::convert_string_sid_to_sid;
|
||||
use crate::helper_materialization::helper_bin_dir;
|
||||
use crate::logging::log_note;
|
||||
use crate::path_normalization::canonical_path_key;
|
||||
use crate::path_normalization::canonicalize_path;
|
||||
use crate::policy::SandboxPolicy;
|
||||
use crate::setup_error::SetupErrorCode;
|
||||
use crate::setup_error::SetupFailure;
|
||||
@@ -29,6 +34,8 @@ use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
|
||||
|
||||
use windows_sys::Win32::Foundation::CloseHandle;
|
||||
use windows_sys::Win32::Foundation::GetLastError;
|
||||
use windows_sys::Win32::Foundation::HLOCAL;
|
||||
use windows_sys::Win32::Foundation::LocalFree;
|
||||
use windows_sys::Win32::Security::AllocateAndInitializeSid;
|
||||
use windows_sys::Win32::Security::CheckTokenMembership;
|
||||
use windows_sys::Win32::Security::FreeSid;
|
||||
@@ -142,6 +149,43 @@ pub fn run_setup_refresh_with_extra_read_roots(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn cleanup_stale_protected_write_denies(command_cwd: &Path, codex_home: &Path) -> Result<()> {
|
||||
let caps = load_or_create_cap_sids(codex_home)?;
|
||||
let cap_psid = unsafe {
|
||||
convert_string_sid_to_sid(&caps.workspace)
|
||||
.ok_or_else(|| anyhow!("convert capability SID {} failed", caps.workspace))?
|
||||
};
|
||||
let workspace_sid = workspace_cap_sid_for_cwd(codex_home, command_cwd)?;
|
||||
let workspace_psid = unsafe {
|
||||
convert_string_sid_to_sid(&workspace_sid)
|
||||
.ok_or_else(|| anyhow!("convert workspace capability SID {workspace_sid} failed"))?
|
||||
};
|
||||
let canonical_command_cwd = canonicalize_path(command_cwd);
|
||||
|
||||
for protected_subdir in [".git", ".codex", ".agents"] {
|
||||
let protected_path = canonical_command_cwd.join(protected_subdir);
|
||||
if !protected_path.exists() {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
revoke_ace(&protected_path, workspace_psid);
|
||||
revoke_ace(&protected_path, cap_psid);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
if !cap_psid.is_null() {
|
||||
LocalFree(cap_psid as HLOCAL);
|
||||
}
|
||||
if !workspace_psid.is_null() {
|
||||
LocalFree(workspace_psid as HLOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_setup_refresh_inner(
|
||||
request: SandboxSetupRequest<'_>,
|
||||
overrides: SetupRootOverrides,
|
||||
|
||||
Reference in New Issue
Block a user