Propagate executor home directories into sandbox contexts (#41204)

## What changed

- Report the executor's user home in environment metadata.
- Cache the reported home on selected turn environments and include it in
  filesystem sandbox contexts, including `apply_patch` requests.
- Preserve compatibility with executors that do not report a home directory.

## Testing

- Cover local, remote, inherited, serialized, and `apply_patch` sandbox
  contexts.

GitOrigin-RevId: ea65e68e33a80bc9bcfc7c53b1486ab944699470
This commit is contained in:
iceweasel-oai authored and copyberry committed 2026-08-27 20:44:47 +00:00
1 parent 5bf0ba3dd6
commit d4d2b293b4
11 files changed
+73 -12

No files matched your search

+29 -6
View File
@@ -137,6 +137,7 @@ type PendingConfigurationResult = Result<EnvironmentConfig, String>;
struct ResolvedEnvironment { struct ResolvedEnvironment {
environment: Arc<Environment>, environment: Arc<Environment>,
shell: Option<Shell>, shell: Option<Shell>,
user_home_dir: Option<PathUri>,
temporary_directories: Option<Vec<PathUri>>, temporary_directories: Option<Vec<PathUri>>,
shell_snapshot: ShellSnapshotTask, shell_snapshot: ShellSnapshotTask,
shell_snapshot_v2_supported: bool, shell_snapshot_v2_supported: bool,
@@ -257,6 +258,7 @@ impl ThreadEnvironments {
futures::future::ready(Ok(ResolvedEnvironment { futures::future::ready(Ok(ResolvedEnvironment {
environment: environment.environment, environment: environment.environment,
shell: environment.shell, shell: environment.shell,
user_home_dir: environment.user_home_dir,
temporary_directories: environment.temporary_directories, temporary_directories: environment.temporary_directories,
shell_snapshot: environment.shell_snapshot, shell_snapshot: environment.shell_snapshot,
shell_snapshot_v2_supported: environment.shell_snapshot_v2_supported, shell_snapshot_v2_supported: environment.shell_snapshot_v2_supported,
@@ -623,10 +625,10 @@ impl ThreadEnvironments {
}; };
// Resolve the attachment only after both prerequisites are ready. // Resolve the attachment only after both prerequisites are ready.
let ((), installed_config) = tokio::try_join!(connection_ready, configuration_ready)?; let ((), installed_config) = tokio::try_join!(connection_ready, configuration_ready)?;
let (shell, temporary_directories, shell_snapshot_v2_supported) = if environment.is_remote() let (shell, user_home_dir, temporary_dirs, snapshot_v2) = if environment.is_remote() {
{
match environment.info().await { match environment.info().await {
Ok(info) => { Ok(info) => {
let user_home_dir = info.user_home_dir;
let temporary_directories = info.temporary_directories; let temporary_directories = info.temporary_directories;
let shell_snapshot_v2_supported = info.capabilities.shell_snapshot_v2; let shell_snapshot_v2_supported = info.capabilities.shell_snapshot_v2;
let shell = match Shell::from_environment_shell_info(info.shell) { let shell = match Shell::from_environment_shell_info(info.shell) {
@@ -638,16 +640,22 @@ impl ThreadEnvironments {
None None
} }
}; };
(shell, temporary_directories, shell_snapshot_v2_supported) (
shell,
user_home_dir,
temporary_directories,
shell_snapshot_v2_supported,
)
} }
Err(err) => { Err(err) => {
tracing::warn!("failed to get info for environment `{environment_id}`: {err}"); tracing::warn!("failed to get info for environment `{environment_id}`: {err}");
(None, None, false) (None, None, None, false)
} }
} }
} else { } else {
( (
Some(local_shell), Some(local_shell),
PathUri::from_host_native_path("~").ok(),
Some(EnvironmentInfo::local_temporary_directories()), Some(EnvironmentInfo::local_temporary_directories()),
cfg!(unix), cfg!(unix),
) )
@@ -662,9 +670,10 @@ impl ThreadEnvironments {
Ok(ResolvedEnvironment { Ok(ResolvedEnvironment {
environment, environment,
shell, shell,
temporary_directories, user_home_dir,
temporary_directories: temporary_dirs,
shell_snapshot: task, shell_snapshot: task,
shell_snapshot_v2_supported, shell_snapshot_v2_supported: snapshot_v2,
installed_config, installed_config,
}) })
} }
@@ -742,6 +751,7 @@ impl TurnEnvironmentState {
turn_environment.shell_snapshot = environment.shell_snapshot; turn_environment.shell_snapshot = environment.shell_snapshot;
turn_environment.shell_snapshot_v2_supported = turn_environment.shell_snapshot_v2_supported =
environment.shell_snapshot_v2_supported; environment.shell_snapshot_v2_supported;
turn_environment.user_home_dir = environment.user_home_dir;
turn_environment.temporary_directories = environment.temporary_directories; turn_environment.temporary_directories = environment.temporary_directories;
Some(Self::Ready(turn_environment)) Some(Self::Ready(turn_environment))
} }
@@ -1018,6 +1028,7 @@ mod tests {
"id": info["id"], "id": info["id"],
"result": { "result": {
"shell": { "name": "zsh", "path": "/bin/zsh" }, "shell": { "name": "zsh", "path": "/bin/zsh" },
"userHomeDir": "file:///home/remote",
"temporaryDirectories": ["file:///tmp/remote"], "temporaryDirectories": ["file:///tmp/remote"],
} }
}) })
@@ -1145,6 +1156,7 @@ url = "ws://127.0.0.1:8765"
let snapshot = turn_environments.snapshot().await; let snapshot = turn_environments.snapshot().await;
let environment = snapshot.primary().expect("local environment"); let environment = snapshot.primary().expect("local environment");
let expected_user_home_dir = PathUri::from_host_native_path("~").ok();
let expected_temporary_directories = EnvironmentInfo::local_temporary_directories(); let expected_temporary_directories = EnvironmentInfo::local_temporary_directories();
assert_eq!(environment.shell.as_ref(), Some(&local_shell)); assert_eq!(environment.shell.as_ref(), Some(&local_shell));
@@ -1157,6 +1169,7 @@ url = "ws://127.0.0.1:8765"
FileSystemSandboxPolicyContext { FileSystemSandboxPolicyContext {
cwd: environment.cwd(), cwd: environment.cwd(),
workspace_roots: &[], workspace_roots: &[],
user_home_dir: expected_user_home_dir.as_ref(),
temporary_directories: Some(expected_temporary_directories.as_slice()), temporary_directories: Some(expected_temporary_directories.as_slice()),
} }
); );
@@ -1472,6 +1485,7 @@ url = "ws://127.0.0.1:8765"
); );
assert_eq!(attached.to_selections(), vec![remote, local]); assert_eq!(attached.to_selections(), vec![remote, local]);
let environment = attached.primary().expect("remote environment"); let environment = attached.primary().expect("remote environment");
let expected_user_home_dir = PathUri::parse("file:///home/remote").expect("remote home");
let expected_temporary_directories = let expected_temporary_directories =
[PathUri::parse("file:///tmp/remote").expect("remote temporary directory")]; [PathUri::parse("file:///tmp/remote").expect("remote temporary directory")];
assert_eq!( assert_eq!(
@@ -1482,6 +1496,7 @@ url = "ws://127.0.0.1:8765"
FileSystemSandboxPolicyContext { FileSystemSandboxPolicyContext {
cwd: environment.cwd(), cwd: environment.cwd(),
workspace_roots: &[], workspace_roots: &[],
user_home_dir: Some(&expected_user_home_dir),
temporary_directories: Some(expected_temporary_directories.as_slice()), temporary_directories: Some(expected_temporary_directories.as_slice()),
} }
); );
@@ -1707,6 +1722,8 @@ url = "ws://127.0.0.1:8765"
Arc::clone(&inherited_environment), Arc::clone(&inherited_environment),
/*shell*/ None, /*shell*/ None,
); );
inherited.user_home_dir =
Some(PathUri::parse("file:///home/inherited").expect("home directory"));
inherited.temporary_directories = Some(vec![ inherited.temporary_directories = Some(vec![
PathUri::parse("file:///tmp/inherited").expect("temporary directory"), PathUri::parse("file:///tmp/inherited").expect("temporary directory"),
]); ]);
@@ -1752,6 +1769,12 @@ url = "ws://127.0.0.1:8765"
let inherited = snapshot.primary().expect("inherited environment"); let inherited = snapshot.primary().expect("inherited environment");
assert!(Arc::ptr_eq(&inherited.environment, &inherited_environment)); assert!(Arc::ptr_eq(&inherited.environment, &inherited_environment));
assert_eq!(inherited.config(), &child_config); assert_eq!(inherited.config(), &child_config);
assert_eq!(
inherited
.sandbox_context(/*additional_permissions*/ None)
.user_home_dir,
Some(PathUri::parse("file:///home/inherited").expect("home directory")),
);
assert_eq!( assert_eq!(
inherited inherited
.sandbox_context(/*additional_permissions*/ None) .sandbox_context(/*additional_permissions*/ None)
+1
View File
@@ -9297,6 +9297,7 @@ async fn capability_discovery_uses_environment_permission_profile() {
permissions: environment.permission_profile().clone().into(), permissions: environment.permission_profile().clone().into(),
cwd: Some(environment.cwd().clone()), cwd: Some(environment.cwd().clone()),
workspace_roots: environment.workspace_roots().to_vec(), workspace_roots: environment.workspace_roots().to_vec(),
user_home_dir: environment.user_home_dir.clone(),
temporary_directories: environment.temporary_directories.clone(), temporary_directories: environment.temporary_directories.clone(),
windows_sandbox_level: WindowsSandboxLevel::Elevated, windows_sandbox_level: WindowsSandboxLevel::Elevated,
windows_sandbox_private_desktop: false, windows_sandbox_private_desktop: false,
@@ -48,6 +48,8 @@ pub(crate) struct TurnEnvironment {
pub(crate) selection: TurnEnvironmentSelection, pub(crate) selection: TurnEnvironmentSelection,
pub(crate) config_origin: EnvironmentConfigOrigin, pub(crate) config_origin: EnvironmentConfigOrigin,
pub(crate) environment: Arc<Environment>, pub(crate) environment: Arc<Environment>,
/// Cached from the selected executor; `None` means it did not report one.
pub(crate) user_home_dir: Option<PathUri>,
/// Cached from the selected executor; `None` means it did not report them. /// Cached from the selected executor; `None` means it did not report them.
pub(crate) temporary_directories: Option<Vec<PathUri>>, pub(crate) temporary_directories: Option<Vec<PathUri>>,
pub(crate) shell: Option<shell::Shell>, pub(crate) shell: Option<shell::Shell>,
@@ -67,6 +69,7 @@ impl TurnEnvironment {
selection, selection,
config_origin, config_origin,
environment, environment,
user_home_dir: None,
temporary_directories: None, temporary_directories: None,
shell, shell,
shell_snapshot: futures::future::ready(None).boxed().shared(), shell_snapshot: futures::future::ready(None).boxed().shared(),
@@ -131,6 +134,7 @@ impl TurnEnvironment {
permissions: permissions.into(), permissions: permissions.into(),
cwd: Some(self.cwd().clone()), cwd: Some(self.cwd().clone()),
workspace_roots: self.workspace_roots().to_vec(), workspace_roots: self.workspace_roots().to_vec(),
user_home_dir: self.user_home_dir.clone(),
temporary_directories: self.temporary_directories.clone(), temporary_directories: self.temporary_directories.clone(),
windows_sandbox_level: executor_windows_sandbox_level( windows_sandbox_level: executor_windows_sandbox_level(
config.windows_sandbox_level, config.windows_sandbox_level,
@@ -165,6 +169,7 @@ impl std::fmt::Debug for TurnEnvironment {
.field("environment", &self.environment) .field("environment", &self.environment)
.field("cwd", &self.selection.cwd) .field("cwd", &self.selection.cwd)
.field("workspace_roots", &self.config().workspace_roots) .field("workspace_roots", &self.config().workspace_roots)
.field("user_home_dir", &self.user_home_dir)
.field("temporary_directories", &self.temporary_directories) .field("temporary_directories", &self.temporary_directories)
.field("shell", &self.shell) .field("shell", &self.shell)
.field("config", self.config()) .field("config", self.config())
@@ -100,6 +100,7 @@ impl ApplyPatchRuntime {
permissions: permissions.into(), permissions: permissions.into(),
cwd: Some(attempt.sandbox_cwd.clone()), cwd: Some(attempt.sandbox_cwd.clone()),
workspace_roots: attempt.workspace_roots.to_vec(), workspace_roots: attempt.workspace_roots.to_vec(),
user_home_dir: req.turn_environment.user_home_dir.clone(),
temporary_directories: None, temporary_directories: None,
windows_sandbox_level: executor_windows_sandbox_level( windows_sandbox_level: executor_windows_sandbox_level(
attempt.windows_sandbox_level, attempt.windows_sandbox_level,
@@ -288,7 +288,7 @@ async fn file_system_sandbox_context_respects_sandbox_request() {
let path = std::env::temp_dir() let path = std::env::temp_dir()
.join("apply-patch-runtime-none.txt") .join("apply-patch-runtime-none.txt")
.abs(); .abs();
let req = ApplyPatchRequest { let mut req = ApplyPatchRequest {
turn_environment: test_turn_environment(codex_exec_server::LOCAL_ENVIRONMENT_ID), turn_environment: test_turn_environment(codex_exec_server::LOCAL_ENVIRONMENT_ID),
action: ApplyPatchAction::new_add_for_test( action: ApplyPatchAction::new_add_for_test(
&PathUri::from_abs_path(&path), &PathUri::from_abs_path(&path),
@@ -329,6 +329,8 @@ async fn file_system_sandbox_context_respects_sandbox_request() {
); );
let cwd = PathUri::parse("file:///C:/workspace").expect("Windows workspace URI"); let cwd = PathUri::parse("file:///C:/workspace").expect("Windows workspace URI");
let user_home_dir = PathUri::parse("file:///C:/Users/remote").expect("Windows home URI");
req.turn_environment.user_home_dir = Some(user_home_dir.clone());
let permissions = PermissionProfile::workspace_write(); let permissions = PermissionProfile::workspace_write();
let attempt = SandboxAttempt { let attempt = SandboxAttempt {
sandbox_requested: true, sandbox_requested: true,
@@ -345,6 +347,7 @@ async fn file_system_sandbox_context_respects_sandbox_request() {
permissions: permissions.into(), permissions: permissions.into(),
cwd: Some(cwd.clone()), cwd: Some(cwd.clone()),
workspace_roots: vec![cwd], workspace_roots: vec![cwd],
user_home_dir: Some(user_home_dir),
temporary_directories: None, temporary_directories: None,
windows_sandbox_level: WindowsSandboxLevel::RestrictedToken, windows_sandbox_level: WindowsSandboxLevel::RestrictedToken,
windows_sandbox_private_desktop: false, windows_sandbox_private_desktop: false,
+1
View File
@@ -513,6 +513,7 @@ impl<'a> SandboxAttempt<'a> {
permissions: exec_server_permissions.into(), permissions: exec_server_permissions.into(),
cwd: Some(exec_request.windows_sandbox_policy_cwd.clone()), cwd: Some(exec_request.windows_sandbox_policy_cwd.clone()),
workspace_roots: self.workspace_roots.to_vec(), workspace_roots: self.workspace_roots.to_vec(),
user_home_dir: None,
temporary_directories: None, temporary_directories: None,
windows_sandbox_level: executor_windows_sandbox_level( windows_sandbox_level: executor_windows_sandbox_level(
self.windows_sandbox_level, self.windows_sandbox_level,
@@ -370,6 +370,7 @@ fn exec_server_env_keeps_command_native_and_carries_sandbox_context() {
permissions: exec_server_permissions.clone().into(), permissions: exec_server_permissions.clone().into(),
cwd: Some(cwd_uri.clone()), cwd: Some(cwd_uri.clone()),
workspace_roots: vec![cwd_uri.clone()], workspace_roots: vec![cwd_uri.clone()],
user_home_dir: None,
temporary_directories: None, temporary_directories: None,
windows_sandbox_level: if cfg!(windows) { windows_sandbox_level: if cfg!(windows) {
codex_protocol::config_types::WindowsSandboxLevel::RestrictedToken codex_protocol::config_types::WindowsSandboxLevel::RestrictedToken
+15 -5
View File
@@ -97,6 +97,9 @@ pub struct EnvironmentInfo {
/// Working directory inherited by the exec-server process. /// Working directory inherited by the exec-server process.
#[serde(default)] #[serde(default)]
pub cwd: Option<PathUri>, pub cwd: Option<PathUri>,
/// Executor user home used to expand `~` in path-bearing values.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_home_dir: Option<PathUri>,
/// Executor-local default directories for resolving `:tmpdir`, when reported. /// Executor-local default directories for resolving `:tmpdir`, when reported.
/// On Windows, a command's `TEMP` or `TMP` overrides take precedence. /// On Windows, a command's `TEMP` or `TMP` overrides take precedence.
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -209,6 +212,7 @@ impl EnvironmentInfo {
Self { Self {
shell: codex_shell_command::shell_detect::default_user_shell().into(), shell: codex_shell_command::shell_detect::default_user_shell().into(),
cwd: cwd.and_then(|cwd| PathUri::from_host_native_path(cwd).ok()), cwd: cwd.and_then(|cwd| PathUri::from_host_native_path(cwd).ok()),
user_home_dir: PathUri::from_host_native_path("~").ok(),
temporary_directories: Some(temporary_directories), temporary_directories: Some(temporary_directories),
temp_dir, temp_dir,
capabilities: EnvironmentCapabilities { capabilities: EnvironmentCapabilities {
@@ -973,6 +977,7 @@ mod tests {
path: "/bin/zsh".to_string(), path: "/bin/zsh".to_string(),
}, },
cwd: None, cwd: None,
user_home_dir: None,
temporary_directories: None, temporary_directories: None,
temp_dir: None, temp_dir: None,
capabilities: EnvironmentCapabilities::default(), capabilities: EnvironmentCapabilities::default(),
@@ -1006,6 +1011,7 @@ mod tests {
let expected = serde_json::json!({ let expected = serde_json::json!({
"shell": { "name": "powershell", "path": "powershell.exe" }, "shell": { "name": "powershell", "path": "powershell.exe" },
"cwd": null, "cwd": null,
"userHomeDir": "file:///C:/Users/remote",
"temporaryDirectories": ["file:///C:/Temp", "file:///D:/Temp"], "temporaryDirectories": ["file:///C:/Temp", "file:///D:/Temp"],
"capabilities": { "capabilities": {
"networkProxyLaunch": false, "networkProxyLaunch": false,
@@ -1050,10 +1056,9 @@ mod tests {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
expected.dedup(); expected.dedup();
assert_eq!( let info = EnvironmentInfo::local();
EnvironmentInfo::local().temporary_directories, assert_eq!(info.temporary_directories, Some(expected));
Some(expected) assert_eq!(info.user_home_dir, PathUri::from_host_native_path("~").ok());
);
} }
#[cfg(unix)] #[cfg(unix)]
@@ -1147,11 +1152,16 @@ mod tests {
file_system, file_system,
network: NetworkSandboxPolicy::Restricted, network: NetworkSandboxPolicy::Restricted,
}; };
let sandbox = let mut sandbox =
FileSystemSandboxContext::from_permission_profile_with_cwd(permissions, cwd.clone()); FileSystemSandboxContext::from_permission_profile_with_cwd(permissions, cwd.clone());
sandbox.user_home_dir = Some(cwd.clone());
let serialized = serde_json::to_value(&sandbox).expect("serialize sandbox"); let serialized = serde_json::to_value(&sandbox).expect("serialize sandbox");
assert_eq!(
serialized["userHomeDir"],
serde_json::json!(cwd.to_string())
);
assert_eq!( assert_eq!(
serialized["permissions"]["file_system"]["entries"][0]["path"]["path"], serialized["permissions"]["file_system"]["entries"][0]["path"]["path"],
serde_json::json!(cwd.to_string()) serde_json::json!(cwd.to_string())
@@ -46,6 +46,10 @@ unselected = "do not return"
let environment = Environment::create_for_tests(Some(server.websocket_url().to_string()))?; let environment = Environment::create_for_tests(Some(server.websocket_url().to_string()))?;
let environment_info = environment.info().await?; let environment_info = environment.info().await?;
assert!(environment_info.capabilities.environment_config_read); assert!(environment_info.capabilities.environment_config_read);
assert_eq!(
environment_info.user_home_dir,
dirs::home_dir().and_then(|home_dir| PathUri::from_host_native_path(home_dir).ok()),
);
let response = environment let response = environment
.read_environment_config(EnvironmentConfigReadParams { .read_environment_config(EnvironmentConfigReadParams {
+5
View File
@@ -333,6 +333,9 @@ pub struct FileSystemSandboxContext {
pub cwd: Option<PathUri>, pub cwd: Option<PathUri>,
#[serde(default, skip_serializing_if = "Vec::is_empty")] #[serde(default, skip_serializing_if = "Vec::is_empty")]
pub workspace_roots: Vec<PathUri>, pub workspace_roots: Vec<PathUri>,
/// Executor-local user home used to resolve home-relative policy paths.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_home_dir: Option<PathUri>,
/// Executor-local default directories used to resolve `:tmpdir` policy entries. /// Executor-local default directories used to resolve `:tmpdir` policy entries.
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
pub temporary_directories: Option<Vec<PathUri>>, pub temporary_directories: Option<Vec<PathUri>>,
@@ -380,6 +383,7 @@ impl FileSystemSandboxContext {
permissions: permissions.into(), permissions: permissions.into(),
cwd, cwd,
workspace_roots, workspace_roots,
user_home_dir: None,
temporary_directories: None, temporary_directories: None,
windows_sandbox_level: WindowsSandboxLevel::Disabled, windows_sandbox_level: WindowsSandboxLevel::Disabled,
windows_sandbox_private_desktop: false, windows_sandbox_private_desktop: false,
@@ -405,6 +409,7 @@ impl FileSystemSandboxContext {
Some(FileSystemSandboxPolicyContext { Some(FileSystemSandboxPolicyContext {
cwd: self.cwd.as_ref()?, cwd: self.cwd.as_ref()?,
workspace_roots: &self.workspace_roots, workspace_roots: &self.workspace_roots,
user_home_dir: self.user_home_dir.as_ref(),
temporary_directories: self.temporary_directories.as_deref(), temporary_directories: self.temporary_directories.as_deref(),
}) })
} }
+7
View File
@@ -263,6 +263,7 @@ pub struct RawFileSystemSandboxPolicy {
pub struct FileSystemSandboxPolicyContext<'a> { pub struct FileSystemSandboxPolicyContext<'a> {
pub cwd: &'a PathUri, pub cwd: &'a PathUri,
pub workspace_roots: &'a [PathUri], pub workspace_roots: &'a [PathUri],
pub user_home_dir: Option<&'a PathUri>,
pub temporary_directories: Option<&'a [PathUri]>, pub temporary_directories: Option<&'a [PathUri]>,
} }
@@ -1784,10 +1785,12 @@ fn with_local_policy_context<T>(
let cwd = AbsolutePathBuf::from_absolute_path(cwd).ok()?; let cwd = AbsolutePathBuf::from_absolute_path(cwd).ok()?;
let path = PathUri::from(resolve_candidate_path(path, cwd.as_path())?); let path = PathUri::from(resolve_candidate_path(path, cwd.as_path())?);
let cwd = PathUri::from(cwd); let cwd = PathUri::from(cwd);
let user_home_dir = PathUri::from_host_native_path("~").ok();
let temporary_directories = local_temporary_directories(); let temporary_directories = local_temporary_directories();
let context = FileSystemSandboxPolicyContext { let context = FileSystemSandboxPolicyContext {
cwd: &cwd, cwd: &cwd,
workspace_roots: std::slice::from_ref(&cwd), workspace_roots: std::slice::from_ref(&cwd),
user_home_dir: user_home_dir.as_ref(),
temporary_directories: Some(&temporary_directories), temporary_directories: Some(&temporary_directories),
}; };
Some(evaluate(&path, &context)) Some(evaluate(&path, &context))
@@ -2451,6 +2454,7 @@ mod tests {
let context = FileSystemSandboxPolicyContext { let context = FileSystemSandboxPolicyContext {
cwd: &cwd, cwd: &cwd,
workspace_roots: &workspace_roots, workspace_roots: &workspace_roots,
user_home_dir: None,
temporary_directories: Some(&temporary_directories), temporary_directories: Some(&temporary_directories),
}; };
let policy = FileSystemSandboxPolicy::restricted(vec![ let policy = FileSystemSandboxPolicy::restricted(vec![
@@ -2530,6 +2534,7 @@ mod tests {
let context = FileSystemSandboxPolicyContext { let context = FileSystemSandboxPolicyContext {
cwd: &cwd, cwd: &cwd,
workspace_roots: std::slice::from_ref(&cwd), workspace_roots: std::slice::from_ref(&cwd),
user_home_dir: None,
temporary_directories: None, temporary_directories: None,
}; };
let candidate = path("file:///workspace/private/secret/key"); let candidate = path("file:///workspace/private/secret/key");
@@ -2575,6 +2580,7 @@ mod tests {
let context = FileSystemSandboxPolicyContext { let context = FileSystemSandboxPolicyContext {
cwd: &cwd, cwd: &cwd,
workspace_roots: &[], workspace_roots: &[],
user_home_dir: None,
temporary_directories: None, temporary_directories: None,
}; };
let policy = FileSystemSandboxPolicy::restricted(vec![ let policy = FileSystemSandboxPolicy::restricted(vec![
@@ -2605,6 +2611,7 @@ mod tests {
let opaque_context = FileSystemSandboxPolicyContext { let opaque_context = FileSystemSandboxPolicyContext {
cwd: &opaque, cwd: &opaque,
workspace_roots: std::slice::from_ref(&opaque), workspace_roots: std::slice::from_ref(&opaque),
user_home_dir: None,
temporary_directories: None, temporary_directories: None,
}; };
let opaque_policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry::new( let opaque_policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry::new(