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:
parent
91a1d20e2d
commit
b3d320433f
4 changed files with 49 additions and 39 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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"))]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue