have world_writable_warning_details accept cwd as a param (#6913)

this enables app-server to pass in the correct workspace cwd for the
current conversation
This commit is contained in:
iceweasel-oai 2025-11-19 10:10:03 -08:00 committed by GitHub
parent 91a1d20e2d
commit b3d320433f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 39 deletions

View file

@ -191,8 +191,15 @@ impl MessageProcessor {
}
// This function is stubbed out to return None on non-Windows platforms
let cwd = match std::env::current_dir() {
Ok(cwd) => cwd,
Err(_) => return,
};
if let Some((sample_paths, extra_count, failed_scan)) =
codex_windows_sandbox::world_writable_warning_details(self.config.codex_home.as_path())
codex_windows_sandbox::world_writable_warning_details(
self.config.codex_home.as_path(),
cwd,
)
{
self.outgoing
.send_server_notification(ServerNotification::WindowsWorldWritableWarning(

View file

@ -2300,7 +2300,11 @@ impl ChatWidget {
{
return None;
}
codex_windows_sandbox::world_writable_warning_details(self.config.codex_home.as_path())
let cwd = match std::env::current_dir() {
Ok(cwd) => cwd,
Err(_) => return Some((Vec::new(), 0, true)),
};
codex_windows_sandbox::world_writable_warning_details(self.config.codex_home.as_path(), cwd)
}
#[cfg(not(target_os = "windows"))]

View file

@ -8,35 +8,35 @@ use std::path::Path;
use std::path::PathBuf;
use std::time::Duration;
use std::time::Instant;
use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::Foundation::ERROR_SUCCESS;
use windows_sys::Win32::Foundation::HLOCAL;
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
use windows_sys::Win32::Security::Authorization::GetNamedSecurityInfoW;
use windows_sys::Win32::Security::Authorization::GetSecurityInfo;
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::Storage::FileSystem::CreateFileW;
use windows_sys::Win32::Storage::FileSystem::FILE_APPEND_DATA;
use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_BACKUP_SEMANTICS;
use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_WRITE;
use windows_sys::Win32::Storage::FileSystem::FILE_SHARE_DELETE;
use windows_sys::Win32::Storage::FileSystem::FILE_SHARE_READ;
use windows_sys::Win32::Storage::FileSystem::FILE_SHARE_WRITE;
use windows_sys::Win32::Storage::FileSystem::OPEN_EXISTING;
use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_WRITE;
use windows_sys::Win32::Storage::FileSystem::FILE_WRITE_DATA;
use windows_sys::Win32::Storage::FileSystem::FILE_APPEND_DATA;
use windows_sys::Win32::Storage::FileSystem::FILE_WRITE_EA;
use windows_sys::Win32::Storage::FileSystem::FILE_WRITE_ATTRIBUTES;
use windows_sys::Win32::Storage::FileSystem::FILE_WRITE_DATA;
use windows_sys::Win32::Storage::FileSystem::FILE_WRITE_EA;
use windows_sys::Win32::Storage::FileSystem::OPEN_EXISTING;
const GENERIC_ALL_MASK: u32 = 0x1000_0000;
const GENERIC_WRITE_MASK: u32 = 0x4000_0000;
use windows_sys::Win32::Security::ACL;
use windows_sys::Win32::Security::DACL_SECURITY_INFORMATION;
use windows_sys::Win32::Security::ACL_SIZE_INFORMATION;
use windows_sys::Win32::Security::AclSizeInformation;
use windows_sys::Win32::Security::GetAclInformation;
use windows_sys::Win32::Security::EqualSid;
use windows_sys::Win32::Security::GetAce;
use windows_sys::Win32::Security::GetAclInformation;
use windows_sys::Win32::Security::ACCESS_ALLOWED_ACE;
use windows_sys::Win32::Security::ACE_HEADER;
use windows_sys::Win32::Security::EqualSid;
use windows_sys::Win32::Security::ACL;
use windows_sys::Win32::Security::ACL_SIZE_INFORMATION;
use windows_sys::Win32::Security::DACL_SECURITY_INFORMATION;
// Preflight scan limits
const MAX_ITEMS_PER_DIR: i32 = 1000;
@ -162,7 +162,9 @@ unsafe fn path_has_world_write_allow(path: &Path) -> Result<bool> {
let psid_world = world.as_mut_ptr() as *mut c_void;
// Very fast mask-based check for world-writable grants (includes GENERIC_*).
if !dacl_quick_world_write_mask_allows(p_dacl, psid_world) {
if !p_sd.is_null() { LocalFree(p_sd as HLOCAL); }
if !p_sd.is_null() {
LocalFree(p_sd as HLOCAL);
}
return Ok(false);
}
// Quick detector flagged a write grant for Everyone: treat as writable.
@ -202,7 +204,9 @@ pub fn audit_everyone_writable(
let has = unsafe { path_has_world_write_allow(&p)? };
if has {
let key = normalize_path_key(&p);
if seen.insert(key) { flagged.push(p); }
if seen.insert(key) {
flagged.push(p);
}
}
}
}
@ -218,7 +222,9 @@ pub fn audit_everyone_writable(
let has_root = unsafe { path_has_world_write_allow(&root)? };
if has_root {
let key = normalize_path_key(&root);
if seen.insert(key) { flagged.push(root.clone()); }
if seen.insert(key) {
flagged.push(root.clone());
}
}
// one level down best-effort
if let Ok(read) = std::fs::read_dir(&root) {
@ -240,13 +246,17 @@ pub fn audit_everyone_writable(
// Skip noisy/irrelevant Windows system subdirectories
let pl = p.to_string_lossy().to_ascii_lowercase();
let norm = pl.replace('\\', "/");
if SKIP_DIR_SUFFIXES.iter().any(|s| norm.ends_with(s)) { continue; }
if SKIP_DIR_SUFFIXES.iter().any(|s| norm.ends_with(s)) {
continue;
}
if ft.is_dir() {
checked += 1;
let has_child = unsafe { path_has_world_write_allow(&p)? };
if has_child {
let key = normalize_path_key(&p);
if seen.insert(key) { flagged.push(p); }
if seen.insert(key) {
flagged.push(p);
}
}
}
}
@ -258,20 +268,12 @@ pub fn audit_everyone_writable(
for p in &flagged {
list.push_str(&format!("\n - {}", p.display()));
}
crate::logging::log_note(
&format!(
"AUDIT: world-writable scan FAILED; checked={checked}; duration_ms={elapsed_ms}; flagged:{}",
list
),
logs_base_dir,
);
return Ok(flagged);
}
// Log success once if nothing flagged
crate::logging::log_note(
&format!(
"AUDIT: world-writable scan OK; checked={checked}; duration_ms={elapsed_ms}"
),
&format!("AUDIT: world-writable scan OK; checked={checked}; duration_ms={elapsed_ms}"),
logs_base_dir,
);
Ok(Vec::new())
@ -284,14 +286,10 @@ fn normalize_windows_path_for_display(p: impl AsRef<Path>) -> String {
pub fn world_writable_warning_details(
codex_home: impl AsRef<Path>,
cwd: impl AsRef<Path>,
) -> Option<(Vec<String>, usize, bool)> {
let cwd = match std::env::current_dir() {
Ok(cwd) => cwd,
Err(_) => return Some((Vec::new(), 0, true)),
};
let env_map: HashMap<String, String> = std::env::vars().collect();
match audit_everyone_writable(&cwd, &env_map, Some(codex_home.as_ref())) {
match audit_everyone_writable(cwd.as_ref(), &env_map, Some(codex_home.as_ref())) {
Ok(paths) if paths.is_empty() => None,
Ok(paths) => {
let as_strings: Vec<String> = paths
@ -329,16 +327,16 @@ unsafe fn dacl_quick_world_write_mask_allows(p_dacl: *mut ACL, psid_world: *mut
continue;
}
let hdr = &*(p_ace as *const ACE_HEADER);
if hdr.AceType != 0 { // ACCESS_ALLOWED_ACE_TYPE
if hdr.AceType != 0 {
// ACCESS_ALLOWED_ACE_TYPE
continue;
}
if (hdr.AceFlags & INHERIT_ONLY_ACE) != 0 {
continue;
}
let base = p_ace as usize;
let sid_ptr = (base
+ std::mem::size_of::<ACE_HEADER>()
+ std::mem::size_of::<u32>()) as *mut c_void; // skip header + mask
let sid_ptr =
(base + std::mem::size_of::<ACE_HEADER>() + std::mem::size_of::<u32>()) as *mut c_void; // skip header + mask
if EqualSid(sid_ptr, psid_world) != 0 {
let ace = &*(p_ace as *const ACCESS_ALLOWED_ACE);
let mask = ace.Mask;

View file

@ -467,6 +467,7 @@ mod stub {
pub fn world_writable_warning_details(
_codex_home: impl AsRef<Path>,
_cwd: impl AsRef<Path>,
) -> Option<(Vec<String>, usize, bool)> {
None
}