Compare commits

...

1 Commits

Author SHA1 Message Date
David Wiesen
8862516db2 Avoid PowerShell profiles in Windows sandbox 2026-04-08 12:52:04 -07:00
3 changed files with 90 additions and 0 deletions

View File

@@ -431,6 +431,39 @@ fn record_windows_sandbox_spawn_failure(
}
}
#[cfg(target_os = "windows")]
fn is_powershell_executable(path: &str) -> bool {
matches!(
Path::new(path)
.file_name()
.and_then(|name| name.to_str())
.unwrap_or(path)
.to_ascii_lowercase()
.as_str(),
"powershell" | "powershell.exe" | "pwsh" | "pwsh.exe"
)
}
#[cfg(target_os = "windows")]
fn ensure_powershell_no_profile_for_sandbox(mut command: Vec<String>) -> Vec<String> {
let Some(program) = command.first() else {
return command;
};
if !is_powershell_executable(program) {
return command;
}
if command
.iter()
.skip(1)
.any(|arg| arg.eq_ignore_ascii_case("-NoProfile") || arg.eq_ignore_ascii_case("/NoProfile"))
{
return command;
}
command.insert(1, "-NoProfile".to_string());
command
}
#[cfg(target_os = "windows")]
async fn exec_windows_sandbox(
params: ExecParams,
@@ -455,6 +488,7 @@ async fn exec_windows_sandbox(
if let Some(network) = network.as_ref() {
network.apply_to_env(&mut env);
}
let command = ensure_powershell_no_profile_for_sandbox(command);
// TODO(iceweasel-oai): run_windows_sandbox_capture should support all
// variants of ExecExpiration, not just timeout.

View File

@@ -77,6 +77,61 @@ fn sandbox_detection_uses_aggregated_output() {
));
}
#[cfg(target_os = "windows")]
#[test]
fn windows_sandbox_powershell_inserts_no_profile() {
let command = ensure_powershell_no_profile_for_sandbox(vec![
"powershell.exe".to_string(),
"-Command".to_string(),
"Write-Output ok".to_string(),
]);
assert_eq!(
command,
vec![
"powershell.exe".to_string(),
"-NoProfile".to_string(),
"-Command".to_string(),
"Write-Output ok".to_string(),
]
);
}
#[cfg(target_os = "windows")]
#[test]
fn windows_sandbox_powershell_preserves_existing_no_profile() {
let command = ensure_powershell_no_profile_for_sandbox(vec![
"pwsh.exe".to_string(),
"-NoLogo".to_string(),
"-NoProfile".to_string(),
"-Command".to_string(),
"Write-Output ok".to_string(),
]);
assert_eq!(
command,
vec![
"pwsh.exe".to_string(),
"-NoLogo".to_string(),
"-NoProfile".to_string(),
"-Command".to_string(),
"Write-Output ok".to_string(),
]
);
}
#[cfg(target_os = "windows")]
#[test]
fn windows_sandbox_powershell_detects_full_path() {
let command = ensure_powershell_no_profile_for_sandbox(vec![
r"C:\Program Files\PowerShell\7\pwsh.exe".to_string(),
"-Command".to_string(),
"Write-Output ok".to_string(),
]);
assert_eq!(command[1], "-NoProfile");
}
#[test]
fn sandbox_detection_ignores_network_policy_text_with_zero_exit_code() {
let output = make_exec_output(

View File

@@ -174,6 +174,7 @@ fn multi_agent_v2_tools_config() -> ToolsConfig {
session_source: SessionSource::Cli,
sandbox_policy: &SandboxPolicy::DangerFullAccess,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
image_generation_tool_auth_allowed: true,
})
}