mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
Route Windows sandbox proxy traffic by restricting SID (#34613)
## Why Elevated Windows sandboxes need stable managed-proxy ports while preserving the network policy and environment attribution of each sandboxed process. ## What changed - Keep shared HTTP and SOCKS5 loopback ingress listeners alive across managed-proxy instances. - Add a per-route restricting SID to elevated sandbox tokens and dispatch incoming connections to the matching proxy policy after attributing the client process. - Reject connections without exactly one registered route, remove routes when their proxy handle is dropped, and keep unsandboxed Windows launches off the managed ingress. - Provision the elevated sandbox with the configured proxy ports and local-binding setting, honoring the selected profile and CLI overrides. ## Testing - Add Windows unit tests for TCP ownership attribution, route selection, restricting-token propagation, and setup settings. - Add an end-to-end Windows test covering stable ports, isolated environment policies, HTTP and SOCKS5 routing, and route teardown. GitOrigin-RevId: 783fac6e0f904dc9bb1955b75d4a5895e8bb9690
This commit is contained in:
1 parent
dfd2d8133c
commit
999a715089
40 files changed
+2792
-191
No files matched your search
@@ -273,19 +273,37 @@ fn spawn_ipc_process(req: &SpawnRequest) -> Result<IpcSpawnedProcess> {
|
||||
if cap_psids.is_empty() {
|
||||
anyhow::bail!("runner: empty capability SID list");
|
||||
}
|
||||
let network_proxy_restricting_sid = req
|
||||
.network_proxy_restricting_sid
|
||||
.as_deref()
|
||||
.map(LocalSid::from_string)
|
||||
.transpose()
|
||||
.context("ConvertStringSidToSidW failed for network proxy restricting SID")?;
|
||||
|
||||
// The token helpers still take raw SID pointers, but we keep ownership in `LocalSid`
|
||||
// wrappers for as long as possible. That way any failure after SID parsing but before the
|
||||
// child is fully spawned still releases the backing LocalAlloc memory automatically.
|
||||
let cap_psid_ptrs: Vec<*mut _> = cap_psids.iter().map(LocalSid::as_ptr).collect();
|
||||
let additional_restricting_sid_ptrs: Vec<*mut _> = network_proxy_restricting_sid
|
||||
.iter()
|
||||
.map(LocalSid::as_ptr)
|
||||
.collect();
|
||||
let base = OwnedWinHandle::new(unsafe { get_current_token_for_restriction()? });
|
||||
let h_token = OwnedWinHandle::new(unsafe {
|
||||
match token_mode {
|
||||
WindowsSandboxTokenMode::ReadOnlyCapability => {
|
||||
create_readonly_token_with_caps_and_user_from(base.raw(), &cap_psid_ptrs)
|
||||
create_readonly_token_with_caps_and_user_from(
|
||||
base.raw(),
|
||||
&cap_psid_ptrs,
|
||||
&additional_restricting_sid_ptrs,
|
||||
)
|
||||
}
|
||||
WindowsSandboxTokenMode::WritableRootsCapability => {
|
||||
create_workspace_write_token_with_caps_and_user_from(base.raw(), &cap_psid_ptrs)
|
||||
create_workspace_write_token_with_caps_and_user_from(
|
||||
base.raw(),
|
||||
&cap_psid_ptrs,
|
||||
&additional_restricting_sid_ptrs,
|
||||
)
|
||||
}
|
||||
}
|
||||
}?);
|
||||
|
||||
@@ -26,7 +26,7 @@ use std::path::PathBuf;
|
||||
const MAX_FRAME_LEN: usize = 8 * 1024 * 1024;
|
||||
|
||||
/// Protocol version shared by the parent process and elevated command runner.
|
||||
pub const IPC_PROTOCOL_VERSION: u8 = 4;
|
||||
pub const IPC_PROTOCOL_VERSION: u8 = 5;
|
||||
|
||||
/// Length-prefixed, JSON-encoded frame.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -65,6 +65,9 @@ pub struct SpawnRequest {
|
||||
pub codex_home: PathBuf,
|
||||
pub real_codex_home: PathBuf,
|
||||
pub cap_sids: Vec<String>,
|
||||
/// Optional managed-network identity added only to the child's restricting SID set.
|
||||
#[serde(default)]
|
||||
pub network_proxy_restricting_sid: Option<String>,
|
||||
pub timeout_ms: Option<u64>,
|
||||
pub tty: bool,
|
||||
#[serde(default)]
|
||||
@@ -224,6 +227,7 @@ mod tests {
|
||||
codex_home: PathBuf::from(r"C:\codex"),
|
||||
real_codex_home: PathBuf::from(r"C:\Users\codex"),
|
||||
cap_sids: vec!["S-1-15-3-1024-1".to_string()],
|
||||
network_proxy_restricting_sid: Some("S-1-5-21-100-200-300-400".to_string()),
|
||||
timeout_ms: Some(1000),
|
||||
tty: false,
|
||||
stdin_open: false,
|
||||
@@ -245,6 +249,10 @@ mod tests {
|
||||
};
|
||||
assert_eq!(PermissionProfile::read_only(), payload.permission_profile);
|
||||
assert_eq!(workspace_roots, payload.workspace_roots);
|
||||
assert_eq!(
|
||||
Some("S-1-5-21-100-200-300-400"),
|
||||
payload.network_proxy_restricting_sid.as_deref()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -15,6 +15,7 @@ pub struct ElevatedSandboxProfileCaptureRequest<'a> {
|
||||
pub cancellation: Option<crate::WindowsSandboxCancellationToken>,
|
||||
pub use_private_desktop: bool,
|
||||
pub proxy_enforced: bool,
|
||||
pub network_proxy_restricting_sid: Option<String>,
|
||||
pub read_roots_override: Option<&'a [PathBuf]>,
|
||||
pub read_roots_include_platform_defaults: bool,
|
||||
pub write_roots_override: Option<&'a [PathBuf]>,
|
||||
@@ -110,6 +111,7 @@ mod windows_impl {
|
||||
cancellation,
|
||||
use_private_desktop,
|
||||
proxy_enforced,
|
||||
network_proxy_restricting_sid,
|
||||
read_roots_override,
|
||||
read_roots_include_platform_defaults,
|
||||
write_roots_override,
|
||||
@@ -190,6 +192,7 @@ mod windows_impl {
|
||||
codex_home: sandbox_base.clone(),
|
||||
real_codex_home: codex_home.to_path_buf(),
|
||||
cap_sids,
|
||||
network_proxy_restricting_sid,
|
||||
timeout_ms,
|
||||
tty: false,
|
||||
stdin_open: false,
|
||||
|
||||
@@ -44,6 +44,15 @@ pub enum WindowsSandboxProxySettingsMode {
|
||||
Preserve,
|
||||
}
|
||||
|
||||
/// Network settings installed by an administrator during managed Windows sandbox setup.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub struct WindowsSandboxProvisioningSettings {
|
||||
/// Loopback proxy ports permitted for the offline sandbox identity.
|
||||
pub proxy_ports: Vec<u16>,
|
||||
/// Whether the offline sandbox identity may exchange arbitrary loopback traffic.
|
||||
pub allow_local_binding: bool,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
mod acl;
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
@@ -705,6 +705,10 @@ const PROXY_ENV_KEYS: &[&str] = &[
|
||||
"wss_proxy",
|
||||
];
|
||||
const ALLOW_LOCAL_BINDING_ENV_KEY: &str = "CODEX_NETWORK_ALLOW_LOCAL_BINDING";
|
||||
// Internal wire format shared with network-proxy/src/proxy.rs. The value is a comma-separated,
|
||||
// sorted list of non-zero loopback proxy ports used only when computing the Windows offline
|
||||
// sandbox setup marker.
|
||||
const WINDOWS_SANDBOX_PROXY_PORTS_ENV_KEY: &str = "CODEX_WINDOWS_SANDBOX_PROXY_PORTS";
|
||||
|
||||
pub(crate) fn offline_proxy_settings_from_env(
|
||||
env_map: &HashMap<String, String>,
|
||||
@@ -744,6 +748,14 @@ pub(crate) fn proxy_ports_from_env(env_map: &HashMap<String, String>) -> Vec<u16
|
||||
ports.insert(port);
|
||||
}
|
||||
}
|
||||
if let Some(value) = env_map.get(WINDOWS_SANDBOX_PROXY_PORTS_ENV_KEY) {
|
||||
ports.extend(
|
||||
value
|
||||
.split(',')
|
||||
.filter_map(|port| port.trim().parse::<u16>().ok())
|
||||
.filter(|port| *port != 0),
|
||||
);
|
||||
}
|
||||
ports.into_iter().collect()
|
||||
}
|
||||
|
||||
@@ -1034,7 +1046,11 @@ fn run_elevated_setup_inner(
|
||||
run_setup_exe(&payload, needs_elevation, request.codex_home)
|
||||
}
|
||||
|
||||
pub fn run_elevated_provisioning_setup(codex_home: &Path, real_user: &str) -> Result<()> {
|
||||
pub fn run_elevated_provisioning_setup(
|
||||
codex_home: &Path,
|
||||
real_user: &str,
|
||||
settings: crate::WindowsSandboxProvisioningSettings,
|
||||
) -> Result<()> {
|
||||
let sbx_dir = sandbox_dir(codex_home);
|
||||
std::fs::create_dir_all(&sbx_dir).map_err(|err| {
|
||||
failure(
|
||||
@@ -1063,8 +1079,8 @@ pub fn run_elevated_provisioning_setup(codex_home: &Path, real_user: &str) -> Re
|
||||
write_roots: Vec::new(),
|
||||
deny_read_paths: Vec::new(),
|
||||
deny_write_paths: Vec::new(),
|
||||
proxy_ports: Vec::new(),
|
||||
allow_local_binding: false,
|
||||
proxy_ports: settings.proxy_ports,
|
||||
allow_local_binding: settings.allow_local_binding,
|
||||
otel: codex_otel::global_statsig_metrics_settings(),
|
||||
real_user: real_user.to_string(),
|
||||
mode: SetupMode::ProvisionOnly,
|
||||
@@ -1264,6 +1280,7 @@ fn filter_sensitive_write_roots(mut roots: Vec<PathBuf>, codex_home: &Path) -> V
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::WINDOWS_PLATFORM_DEFAULT_READ_ROOTS;
|
||||
use super::WINDOWS_SANDBOX_PROXY_PORTS_ENV_KEY;
|
||||
use super::build_payload_roots;
|
||||
use super::find_setup_exe_for_current_exe;
|
||||
use super::gather_full_read_roots_for_permissions;
|
||||
@@ -1599,8 +1616,12 @@ mod tests {
|
||||
"HTTPS_PROXY".to_string(),
|
||||
"https://example.com:9999".to_string(),
|
||||
);
|
||||
env.insert(
|
||||
WINDOWS_SANDBOX_PROXY_PORTS_ENV_KEY.to_string(),
|
||||
"8080,43129,0,invalid, 43128,65536".to_string(),
|
||||
);
|
||||
|
||||
assert_eq!(proxy_ports_from_env(&env), vec![1081, 8080]);
|
||||
assert_eq!(proxy_ports_from_env(&env), vec![1081, 8080, 43128, 43129]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -381,7 +381,8 @@ pub unsafe fn create_workspace_write_token_with_caps_from(
|
||||
create_token_with_caps_from(base_token, psid_capabilities, &[])
|
||||
}
|
||||
|
||||
/// Create a restricted token that includes all provided capability SIDs plus the token user SID.
|
||||
/// Create a restricted token that includes all provided capability SIDs, the token user SID, and
|
||||
/// any additional restricting SIDs.
|
||||
///
|
||||
/// This is intended for the elevated sandbox backend, where the token user is the dedicated
|
||||
/// sandbox account rather than the real signed-in user.
|
||||
@@ -391,10 +392,13 @@ pub unsafe fn create_workspace_write_token_with_caps_from(
|
||||
pub unsafe fn create_workspace_write_token_with_caps_and_user_from(
|
||||
base_token: HANDLE,
|
||||
psid_capabilities: &[*mut c_void],
|
||||
additional_restricting_sids: &[*mut c_void],
|
||||
) -> Result<HANDLE> {
|
||||
let mut user_sid_bytes = get_user_sid_bytes(base_token)?;
|
||||
let psid_user = user_sid_bytes.as_mut_ptr() as *mut c_void;
|
||||
create_token_with_caps_from(base_token, psid_capabilities, &[psid_user])
|
||||
create_token_with_caps_user_and_additional_restrictions_from(
|
||||
base_token,
|
||||
psid_capabilities,
|
||||
additional_restricting_sids,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a restricted token that includes all provided capability SIDs.
|
||||
@@ -408,7 +412,8 @@ pub unsafe fn create_readonly_token_with_caps_from(
|
||||
create_token_with_caps_from(base_token, psid_capabilities, &[])
|
||||
}
|
||||
|
||||
/// Create a restricted token that includes all provided capability SIDs plus the token user SID.
|
||||
/// Create a restricted token that includes all provided capability SIDs, the token user SID, and
|
||||
/// any additional restricting SIDs.
|
||||
///
|
||||
/// This is intended for the elevated sandbox backend, where the token user is the dedicated
|
||||
/// sandbox account rather than the real signed-in user.
|
||||
@@ -418,10 +423,26 @@ pub unsafe fn create_readonly_token_with_caps_from(
|
||||
pub unsafe fn create_readonly_token_with_caps_and_user_from(
|
||||
base_token: HANDLE,
|
||||
psid_capabilities: &[*mut c_void],
|
||||
additional_restricting_sids: &[*mut c_void],
|
||||
) -> Result<HANDLE> {
|
||||
create_token_with_caps_user_and_additional_restrictions_from(
|
||||
base_token,
|
||||
psid_capabilities,
|
||||
additional_restricting_sids,
|
||||
)
|
||||
}
|
||||
|
||||
unsafe fn create_token_with_caps_user_and_additional_restrictions_from(
|
||||
base_token: HANDLE,
|
||||
psid_capabilities: &[*mut c_void],
|
||||
additional_restricting_sids: &[*mut c_void],
|
||||
) -> Result<HANDLE> {
|
||||
let mut user_sid_bytes = get_user_sid_bytes(base_token)?;
|
||||
let psid_user = user_sid_bytes.as_mut_ptr() as *mut c_void;
|
||||
create_token_with_caps_from(base_token, psid_capabilities, &[psid_user])
|
||||
let mut extra_restricting_sids = Vec::with_capacity(additional_restricting_sids.len() + 1);
|
||||
extra_restricting_sids.push(psid_user);
|
||||
extra_restricting_sids.extend_from_slice(additional_restricting_sids);
|
||||
create_token_with_caps_from(base_token, psid_capabilities, &extra_restricting_sids)
|
||||
}
|
||||
|
||||
unsafe fn create_token_with_caps_from(
|
||||
@@ -472,6 +493,8 @@ unsafe fn create_token_with_caps_from(
|
||||
return Err(anyhow!("CreateRestrictedToken failed: {}", GetLastError()));
|
||||
}
|
||||
|
||||
// Additional restricting SIDs are identity markers, not capabilities. Deliberately exclude
|
||||
// them from the default DACL so possessing a route identity cannot grant object access.
|
||||
let mut dacl_sids: Vec<*mut c_void> = Vec::with_capacity(psid_capabilities.len() + 2);
|
||||
dacl_sids.push(psid_logon);
|
||||
dacl_sids.push(psid_everyone);
|
||||
@@ -481,3 +504,7 @@ unsafe fn create_token_with_caps_from(
|
||||
enable_single_privilege(new_token, "SeChangeNotifyPrivilege")?;
|
||||
Ok(new_token)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "token_tests.rs"]
|
||||
mod tests;
|
||||
@@ -0,0 +1,69 @@
|
||||
use super::*;
|
||||
use windows_sys::Win32::Security::EqualSid;
|
||||
use windows_sys::Win32::Security::TokenRestrictedSids;
|
||||
|
||||
unsafe fn token_has_restricting_sid(token: HANDLE, expected_sid: *mut c_void) -> Result<bool> {
|
||||
let mut needed = 0;
|
||||
GetTokenInformation(
|
||||
token,
|
||||
TokenRestrictedSids,
|
||||
std::ptr::null_mut(),
|
||||
0,
|
||||
&mut needed,
|
||||
);
|
||||
if needed == 0 {
|
||||
return Err(anyhow!(
|
||||
"GetTokenInformation(TokenRestrictedSids) size query failed: {}",
|
||||
GetLastError()
|
||||
));
|
||||
}
|
||||
|
||||
let mut buffer = vec![0_u8; needed as usize];
|
||||
if GetTokenInformation(
|
||||
token,
|
||||
TokenRestrictedSids,
|
||||
buffer.as_mut_ptr().cast(),
|
||||
needed,
|
||||
&mut needed,
|
||||
) == 0
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"GetTokenInformation(TokenRestrictedSids) failed: {}",
|
||||
GetLastError()
|
||||
));
|
||||
}
|
||||
|
||||
let group_count = std::ptr::read_unaligned(buffer.as_ptr().cast::<u32>()) as usize;
|
||||
let after_count = buffer.as_ptr().add(std::mem::size_of::<u32>()) as usize;
|
||||
let align = std::mem::align_of::<SID_AND_ATTRIBUTES>();
|
||||
let entries_addr = (after_count + (align - 1)) & !(align - 1);
|
||||
let restricting_sids =
|
||||
std::slice::from_raw_parts(entries_addr as *const SID_AND_ATTRIBUTES, group_count);
|
||||
Ok(restricting_sids
|
||||
.iter()
|
||||
.any(|entry| EqualSid(entry.Sid, expected_sid) != 0))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elevated_token_includes_network_proxy_restricting_sid() -> Result<()> {
|
||||
let capability_sid = LocalSid::from_string("S-1-5-21-10-20-30-40")?;
|
||||
let network_proxy_sid = LocalSid::from_string("S-1-5-21-50-60-70-80")?;
|
||||
let base_token = unsafe { get_current_token_for_restriction()? };
|
||||
let restricted_token = unsafe {
|
||||
create_readonly_token_with_caps_and_user_from(
|
||||
base_token,
|
||||
&[capability_sid.as_ptr()],
|
||||
&[network_proxy_sid.as_ptr()],
|
||||
)?
|
||||
};
|
||||
|
||||
let has_network_proxy_sid =
|
||||
unsafe { token_has_restricting_sid(restricted_token, network_proxy_sid.as_ptr()) };
|
||||
unsafe {
|
||||
CloseHandle(restricted_token);
|
||||
CloseHandle(base_token);
|
||||
}
|
||||
|
||||
assert!(has_network_proxy_sid?);
|
||||
Ok(())
|
||||
}
|
||||
@@ -116,6 +116,7 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profil
|
||||
cwd: &Path,
|
||||
mut env_map: HashMap<String, String>,
|
||||
proxy_enforced: bool,
|
||||
network_proxy_restricting_sid: Option<String>,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
timeout_ms: Option<u64>,
|
||||
read_roots_override: Option<&[PathBuf]>,
|
||||
@@ -171,6 +172,7 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profil
|
||||
codex_home: elevated.sandbox_base,
|
||||
real_codex_home: codex_home.to_path_buf(),
|
||||
cap_sids: elevated.cap_sids,
|
||||
network_proxy_restricting_sid,
|
||||
timeout_ms,
|
||||
tty,
|
||||
stdin_open,
|
||||
|
||||
@@ -76,6 +76,7 @@ fn retry_uses_original_unified_exec_request_and_stops_after_second_failure() {
|
||||
codex_home: PathBuf::from(r"C:\Users\codex\.sandbox"),
|
||||
real_codex_home: PathBuf::from(r"C:\Users\codex"),
|
||||
cap_sids: vec!["S-1-15-3-1024-1".to_string()],
|
||||
network_proxy_restricting_sid: Some("S-1-5-21-100-200-300-400".to_string()),
|
||||
timeout_ms: Some(5_000),
|
||||
tty: true,
|
||||
stdin_open: true,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
mod backends;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::bail;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
@@ -31,6 +32,7 @@ pub struct WindowsSandboxSessionRequest<'a> {
|
||||
pub env_map: HashMap<String, String>,
|
||||
pub windows_sandbox_level: WindowsSandboxLevel,
|
||||
pub proxy_enforced: bool,
|
||||
pub network_proxy_restricting_sid: Option<String>,
|
||||
pub proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
pub timeout_ms: Option<u64>,
|
||||
pub read_roots_override: Option<&'a [PathBuf]>,
|
||||
@@ -57,6 +59,7 @@ pub async fn spawn_windows_sandbox_session_for_level(
|
||||
request.cwd,
|
||||
request.env_map,
|
||||
request.proxy_enforced,
|
||||
request.network_proxy_restricting_sid,
|
||||
request.proxy_settings_mode,
|
||||
request.timeout_ms,
|
||||
request.read_roots_override,
|
||||
@@ -70,6 +73,9 @@ pub async fn spawn_windows_sandbox_session_for_level(
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
if request.network_proxy_restricting_sid.is_some() {
|
||||
bail!("network proxy restricting SID requires the elevated Windows sandbox backend");
|
||||
}
|
||||
spawn_windows_sandbox_session_legacy(
|
||||
request.permission_profile,
|
||||
request.workspace_roots,
|
||||
@@ -129,6 +135,7 @@ pub async fn spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
cwd: &Path,
|
||||
env_map: HashMap<String, String>,
|
||||
proxy_enforced: bool,
|
||||
network_proxy_restricting_sid: Option<String>,
|
||||
timeout_ms: Option<u64>,
|
||||
read_roots_override: Option<&[PathBuf]>,
|
||||
read_roots_include_platform_defaults: bool,
|
||||
@@ -147,6 +154,7 @@ pub async fn spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
cwd,
|
||||
env_map,
|
||||
proxy_enforced,
|
||||
network_proxy_restricting_sid,
|
||||
crate::WindowsSandboxProxySettingsMode::Reconcile,
|
||||
timeout_ms,
|
||||
read_roots_override,
|
||||
|
||||
@@ -24,6 +24,7 @@ const CODEX_HOME_FLAG: &str = "--codex-home";
|
||||
const DENY_READ_PATHS_JSON_FLAG: &str = "--deny-read-paths-json";
|
||||
const DENY_WRITE_PATHS_JSON_FLAG: &str = "--deny-write-paths-json";
|
||||
const ENV_JSON_FLAG: &str = "--env-json";
|
||||
const NETWORK_PROXY_RESTRICTING_SID_FLAG: &str = "--network-proxy-restricting-sid";
|
||||
const PERMISSION_PROFILE_FLAG: &str = "--permission-profile";
|
||||
const PRIVATE_DESKTOP_FLAG: &str = "--windows-sandbox-private-desktop";
|
||||
const PRESERVE_PROXY_SETTINGS_FLAG: &str = "--preserve-proxy-settings";
|
||||
@@ -44,6 +45,7 @@ pub fn create_windows_sandbox_command_args_for_permission_profile(
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
windows_sandbox_private_desktop: bool,
|
||||
proxy_enforced: bool,
|
||||
network_proxy_restricting_sid: Option<&str>,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
read_roots_override: Option<&[PathBuf]>,
|
||||
read_roots_include_platform_defaults: bool,
|
||||
@@ -84,6 +86,10 @@ pub fn create_windows_sandbox_command_args_for_permission_profile(
|
||||
if proxy_enforced {
|
||||
args.push(PROXY_ENFORCED_FLAG.to_string());
|
||||
}
|
||||
if let Some(network_proxy_restricting_sid) = network_proxy_restricting_sid {
|
||||
args.push(NETWORK_PROXY_RESTRICTING_SID_FLAG.to_string());
|
||||
args.push(network_proxy_restricting_sid.to_string());
|
||||
}
|
||||
if proxy_settings_mode == crate::WindowsSandboxProxySettingsMode::Preserve {
|
||||
args.push(PRESERVE_PROXY_SETTINGS_FLAG.to_string());
|
||||
}
|
||||
@@ -159,6 +165,7 @@ struct WindowsSandboxWrapperRequest {
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
windows_sandbox_private_desktop: bool,
|
||||
proxy_enforced: bool,
|
||||
network_proxy_restricting_sid: Option<String>,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
read_roots_override: Option<Vec<PathBuf>>,
|
||||
read_roots_include_platform_defaults: bool,
|
||||
@@ -182,6 +189,7 @@ async fn run_windows_sandbox_wrapper_request(request: WindowsSandboxWrapperReque
|
||||
env_map: request.env_map,
|
||||
windows_sandbox_level: request.windows_sandbox_level,
|
||||
proxy_enforced: request.proxy_enforced,
|
||||
network_proxy_restricting_sid: request.network_proxy_restricting_sid,
|
||||
proxy_settings_mode: request.proxy_settings_mode,
|
||||
timeout_ms: None,
|
||||
read_roots_override: request.read_roots_override.as_deref(),
|
||||
@@ -208,6 +216,7 @@ fn parse_windows_sandbox_wrapper_args(args: Vec<String>) -> Result<WindowsSandbo
|
||||
let mut windows_sandbox_level = None;
|
||||
let mut windows_sandbox_private_desktop = false;
|
||||
let mut proxy_enforced = false;
|
||||
let mut network_proxy_restricting_sid = None;
|
||||
let mut proxy_settings_mode = crate::WindowsSandboxProxySettingsMode::Reconcile;
|
||||
let mut read_roots_override = None;
|
||||
let mut read_roots_include_platform_defaults = false;
|
||||
@@ -252,6 +261,9 @@ fn parse_windows_sandbox_wrapper_args(args: Vec<String>) -> Result<WindowsSandbo
|
||||
proxy_settings_mode = crate::WindowsSandboxProxySettingsMode::Preserve;
|
||||
}
|
||||
PROXY_ENFORCED_FLAG => proxy_enforced = true,
|
||||
NETWORK_PROXY_RESTRICTING_SID_FLAG => {
|
||||
network_proxy_restricting_sid = Some(next_flag_value(&mut args, &arg)?);
|
||||
}
|
||||
READ_ROOTS_INCLUDE_PLATFORM_DEFAULTS_FLAG => {
|
||||
read_roots_include_platform_defaults = true;
|
||||
}
|
||||
@@ -293,6 +305,7 @@ fn parse_windows_sandbox_wrapper_args(args: Vec<String>) -> Result<WindowsSandbo
|
||||
.ok_or_else(|| anyhow!("missing required {SANDBOX_LEVEL_FLAG}"))?,
|
||||
windows_sandbox_private_desktop,
|
||||
proxy_enforced,
|
||||
network_proxy_restricting_sid,
|
||||
proxy_settings_mode,
|
||||
read_roots_override,
|
||||
read_roots_include_platform_defaults,
|
||||
|
||||
@@ -14,6 +14,7 @@ use super::COMMAND_CWD_FLAG;
|
||||
use super::DENY_READ_PATHS_JSON_FLAG;
|
||||
use super::DENY_WRITE_PATHS_JSON_FLAG;
|
||||
use super::ENV_JSON_FLAG;
|
||||
use super::NETWORK_PROXY_RESTRICTING_SID_FLAG;
|
||||
use super::PERMISSION_PROFILE_FLAG;
|
||||
use super::PRESERVE_PROXY_SETTINGS_FLAG;
|
||||
use super::PRIVATE_DESKTOP_FLAG;
|
||||
@@ -62,6 +63,7 @@ fn windows_wrapper_args_round_trip() {
|
||||
WindowsSandboxLevel::Elevated,
|
||||
/*windows_sandbox_private_desktop*/ true,
|
||||
/*proxy_enforced*/ true,
|
||||
/*network_proxy_restricting_sid*/ Some("S-1-5-21-100-200-300-400"),
|
||||
crate::WindowsSandboxProxySettingsMode::Preserve,
|
||||
Some(read_roots_override.as_slice()),
|
||||
/*read_roots_include_platform_defaults*/ true,
|
||||
@@ -80,6 +82,7 @@ fn windows_wrapper_args_round_trip() {
|
||||
assert!(args.contains(&SANDBOX_LEVEL_FLAG.to_string()));
|
||||
assert!(args.contains(&PRIVATE_DESKTOP_FLAG.to_string()));
|
||||
assert!(args.contains(&PROXY_ENFORCED_FLAG.to_string()));
|
||||
assert!(args.contains(&NETWORK_PROXY_RESTRICTING_SID_FLAG.to_string()));
|
||||
assert!(args.contains(&PRESERVE_PROXY_SETTINGS_FLAG.to_string()));
|
||||
assert!(args.contains(&READ_ROOTS_JSON_FLAG.to_string()));
|
||||
assert!(args.contains(&READ_ROOTS_INCLUDE_PLATFORM_DEFAULTS_FLAG.to_string()));
|
||||
@@ -101,6 +104,10 @@ fn windows_wrapper_args_round_trip() {
|
||||
assert_eq!(parsed.windows_sandbox_level, WindowsSandboxLevel::Elevated);
|
||||
assert_eq!(parsed.windows_sandbox_private_desktop, true);
|
||||
assert_eq!(parsed.proxy_enforced, true);
|
||||
assert_eq!(
|
||||
parsed.network_proxy_restricting_sid.as_deref(),
|
||||
Some("S-1-5-21-100-200-300-400")
|
||||
);
|
||||
assert_eq!(
|
||||
parsed.proxy_settings_mode,
|
||||
crate::WindowsSandboxProxySettingsMode::Preserve
|
||||
|
||||
Reference in new issue
Block a user