From 6395430220376bbf98320f09f9d1b80cfdf38e62 Mon Sep 17 00:00:00 2001 From: iceweasel-oai Date: Thu, 18 Dec 2025 12:59:52 -0800 Subject: [PATCH] add a default dacl to restricted token to enable reading of pipes (#8280) this fixes sandbox errors (legacy and elevated) for commands that include pipes, which the model often favors. --- codex-rs/windows-sandbox-rs/src/token.rs | 76 ++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/codex-rs/windows-sandbox-rs/src/token.rs b/codex-rs/windows-sandbox-rs/src/token.rs index d6c21f637..3b25a5a05 100644 --- a/codex-rs/windows-sandbox-rs/src/token.rs +++ b/codex-rs/windows-sandbox-rs/src/token.rs @@ -4,17 +4,29 @@ use anyhow::Result; use std::ffi::c_void; use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::GetLastError; +use windows_sys::Win32::Foundation::LocalFree; +use windows_sys::Win32::Foundation::ERROR_SUCCESS; use windows_sys::Win32::Foundation::HANDLE; +use windows_sys::Win32::Foundation::HLOCAL; use windows_sys::Win32::Foundation::LUID; use windows_sys::Win32::Security::AdjustTokenPrivileges; +use windows_sys::Win32::Security::Authorization::SetEntriesInAclW; +use windows_sys::Win32::Security::Authorization::EXPLICIT_ACCESS_W; +use windows_sys::Win32::Security::Authorization::GRANT_ACCESS; +use windows_sys::Win32::Security::Authorization::TRUSTEE_IS_SID; +use windows_sys::Win32::Security::Authorization::TRUSTEE_IS_UNKNOWN; +use windows_sys::Win32::Security::Authorization::TRUSTEE_W; use windows_sys::Win32::Security::CopySid; use windows_sys::Win32::Security::CreateRestrictedToken; use windows_sys::Win32::Security::CreateWellKnownSid; use windows_sys::Win32::Security::GetLengthSid; use windows_sys::Win32::Security::GetTokenInformation; use windows_sys::Win32::Security::LookupPrivilegeValueW; +use windows_sys::Win32::Security::SetTokenInformation; +use windows_sys::Win32::Security::TokenDefaultDacl; use windows_sys::Win32::Security::TokenGroups; +use windows_sys::Win32::Security::ACL; use windows_sys::Win32::Security::SID_AND_ATTRIBUTES; use windows_sys::Win32::Security::TOKEN_ADJUST_DEFAULT; use windows_sys::Win32::Security::TOKEN_ADJUST_PRIVILEGES; @@ -28,9 +40,71 @@ use windows_sys::Win32::System::Threading::GetCurrentProcess; const DISABLE_MAX_PRIVILEGE: u32 = 0x01; const LUA_TOKEN: u32 = 0x04; const WRITE_RESTRICTED: u32 = 0x08; +const GENERIC_ALL: u32 = 0x1000_0000; const WIN_WORLD_SID: i32 = 1; const SE_GROUP_LOGON_ID: u32 = 0xC0000000; +#[repr(C)] +struct TokenDefaultDaclInfo { + default_dacl: *mut ACL, +} + +/// Sets a permissive default DACL so sandboxed processes can create pipes/IPC objects +/// without hitting ACCESS_DENIED when PowerShell builds pipelines. +unsafe fn set_default_dacl(h_token: HANDLE, sids: &[*mut c_void]) -> Result<()> { + if sids.is_empty() { + return Ok(()); + } + let entries: Vec = sids + .iter() + .map(|sid| EXPLICIT_ACCESS_W { + grfAccessPermissions: GENERIC_ALL, + grfAccessMode: GRANT_ACCESS, + grfInheritance: 0, + Trustee: TRUSTEE_W { + pMultipleTrustee: std::ptr::null_mut(), + MultipleTrusteeOperation: 0, + TrusteeForm: TRUSTEE_IS_SID, + TrusteeType: TRUSTEE_IS_UNKNOWN, + ptstrName: *sid as *mut u16, + }, + }) + .collect(); + let mut p_new_dacl: *mut ACL = std::ptr::null_mut(); + let res = SetEntriesInAclW( + entries.len() as u32, + entries.as_ptr(), + std::ptr::null_mut(), + &mut p_new_dacl, + ); + if res != ERROR_SUCCESS { + return Err(anyhow!("SetEntriesInAclW failed: {}", res)); + } + let mut info = TokenDefaultDaclInfo { + default_dacl: p_new_dacl, + }; + let ok = SetTokenInformation( + h_token, + TokenDefaultDacl, + &mut info as *mut _ as *mut c_void, + std::mem::size_of::() as u32, + ); + if ok == 0 { + let err = GetLastError(); + if !p_new_dacl.is_null() { + LocalFree(p_new_dacl as HLOCAL); + } + return Err(anyhow!( + "SetTokenInformation(TokenDefaultDacl) failed: {}", + err + )); + } + if !p_new_dacl.is_null() { + LocalFree(p_new_dacl as HLOCAL); + } + Ok(()) +} + pub unsafe fn world_sid() -> Result> { let mut size: u32 = 0; CreateWellKnownSid( @@ -267,6 +341,7 @@ pub unsafe fn create_workspace_write_token_with_cap_from( if ok == 0 { return Err(anyhow!("CreateRestrictedToken failed: {}", GetLastError())); } + set_default_dacl(new_token, &[psid_logon, psid_everyone, psid_capability])?; enable_single_privilege(new_token, "SeChangeNotifyPrivilege")?; Ok((new_token, psid_capability)) } @@ -305,6 +380,7 @@ pub unsafe fn create_readonly_token_with_cap_from( if ok == 0 { return Err(anyhow!("CreateRestrictedToken failed: {}", GetLastError())); } + set_default_dacl(new_token, &[psid_logon, psid_everyone, psid_capability])?; enable_single_privilege(new_token, "SeChangeNotifyPrivilege")?; Ok((new_token, psid_capability)) }