Repository navigation
fix(windows): forward process bootstrap env into sandboxed children #6998
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b8b5c20
4195d17
5ca37fd
35b11ad
ea3acbd
72dbec8
e09aefe
2cdba4c
6642516
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -17,6 +17,20 @@ use std::path::{Path, PathBuf}; | |||||||||||||||||
| use std::time::Duration; | ||||||||||||||||||
|
|
||||||||||||||||||
| /// Safe environment variables forwarded into sandboxed execution. | ||||||||||||||||||
| /// | ||||||||||||||||||
| /// This list is the *entire* environment a sandboxed child gets: both | ||||||||||||||||||
| /// [`execute_unsandboxed`] and [`execute_local_jail`] call `env_clear()` and | ||||||||||||||||||
| /// re-forward only what is named here. Windows process-bootstrap variables are | ||||||||||||||||||
| /// added only in the host spawn paths below; keeping them out of this policy | ||||||||||||||||||
| /// prevents Windows paths from being passed into Linux Docker containers. | ||||||||||||||||||
| /// | ||||||||||||||||||
| /// They were missing when this defect was found, and it survived the first | ||||||||||||||||||
| /// round of fixes because the four tool launchers (`shell`, `node_exec`, | ||||||||||||||||||
| /// `npm_exec`, `python_exec`) each carry their own copy of the allow-list and | ||||||||||||||||||
| /// had already been patched: the built-in `orchestrator` runs with | ||||||||||||||||||
| /// `sandbox_mode = "sandboxed"`, and all four tools divert to | ||||||||||||||||||
| /// [`crate::sandbox`] *before* reaching those lists, so the host spawn paths | ||||||||||||||||||
| /// below are the ones that must add the Windows-only bootstrap set. | ||||||||||||||||||
| pub const SANDBOX_ENV_PASSTHROUGH: &[&str] = &[ | ||||||||||||||||||
| "PATH", "HOME", "TERM", "LANG", "LC_ALL", "LC_CTYPE", "USER", "SHELL", "TMPDIR", | ||||||||||||||||||
| ]; | ||||||||||||||||||
|
|
@@ -259,9 +273,13 @@ async fn execute_unsandboxed( | |||||||||||||||||
| cmd.env_clear(); | ||||||||||||||||||
| for var in SANDBOX_ENV_PASSTHROUGH { | ||||||||||||||||||
| if let Ok(val) = std::env::var(var) { | ||||||||||||||||||
|
senamakel marked this conversation as resolved.
|
||||||||||||||||||
| if val.is_empty() { | ||||||||||||||||||
| anyhow::bail!("sandbox passthrough environment variable {var} is empty"); | ||||||||||||||||||
| } | ||||||||||||||||||
| cmd.env(var, val); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| platform_shell::forward_windows_bootstrap_env(&mut cmd)?; | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bootstrap forwarding precedes caller overrides in unsandboxed path
Additional
|
||||||||||||||||||
| for (k, v) in extra_env { | ||||||||||||||||||
| cmd.env(k, v); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
@@ -378,6 +396,9 @@ async fn execute_local_jail( | |||||||||||||||||
| jail = jail.add_read_write(&scratch.path); | ||||||||||||||||||
| let stdout_file = capture.stdout(); | ||||||||||||||||||
| let stderr_file = capture.stderr(); | ||||||||||||||||||
| let caller_sets_tmpdir = extra_env.contains_key(std::ffi::OsStr::new("TMPDIR")); | ||||||||||||||||||
| let caller_sets_temp = extra_env.contains_key(std::ffi::OsStr::new("TEMP")); | ||||||||||||||||||
| let caller_sets_tmp = extra_env.contains_key(std::ffi::OsStr::new("TMP")); | ||||||||||||||||||
| // Platform-aware output-capture wrap: `{ … ; } > … 2> …` on sh/bash, | ||||||||||||||||||
| // trailing `> … 2> …` on cmd.exe (no brace grouping). Shell binary is | ||||||||||||||||||
| // picked by `platform_shell` so this path is Windows-safe (#4705). | ||||||||||||||||||
|
|
@@ -387,13 +408,28 @@ async fn execute_local_jail( | |||||||||||||||||
| cmd.env_clear(); | ||||||||||||||||||
| for var in SANDBOX_ENV_PASSTHROUGH { | ||||||||||||||||||
| if let Ok(val) = std::env::var(var) { | ||||||||||||||||||
| if val.is_empty() { | ||||||||||||||||||
| anyhow::bail!("sandbox passthrough environment variable {var} is empty"); | ||||||||||||||||||
| } | ||||||||||||||||||
| cmd.env(var, val); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| cmd.env("TMPDIR", &scratch.path); | ||||||||||||||||||
| platform_shell::forward_windows_bootstrap_env_std(&mut cmd)?; | ||||||||||||||||||
| for (k, v) in extra_env { | ||||||||||||||||||
| cmd.env(k, v); | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+417
to
420
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apply caller TEMP/TMP before forwarding bootstrap variables The standard-command sandbox path has the same ordering problem: caller-provided values are applied after the validated Windows bootstrap environment and can replace it. Reorder these operations so bootstrap variables retain their required values while unrelated per-call overrides remain supported. Additional
|
||||||||||||||||||
| platform_shell::forward_windows_bootstrap_env_std(&mut cmd)?; | |
| for (k, v) in extra_env { | |
| cmd.env(k, v); | |
| } | |
| for (k, v) in extra_env { | |
| cmd.env(k, v); | |
| } | |
| platform_shell::forward_windows_bootstrap_env_std(&mut cmd)?; |
[RULE] environment-precedence ·
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep caller temporary directories inside the jail
The new defaults keep TEMP, TMP, and TMPDIR inside scratch.path only when the caller did not provide those keys. A caller can therefore pass TEMP, TMP, or TMPDIR pointing at an arbitrary host path, while the comment claims that every spelling remains inside the per-call grant. Validate caller-provided temporary paths against the jail, or reject/override values that are outside scratch.path before spawning the child.
[RULE] sandbox-path-containment ·
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep caller temporary directories inside the jail
When extra_env contains TEMP (and likewise TMP), this conditional does not replace it with the per-call scratch directory, leaving the caller's path in effect. A sandboxed child can therefore write temporary data outside the jail despite the stated containment policy. Ignore or validate caller-supplied temporary-directory overrides so every Windows temporary spelling resolves under scratch.path.
[RULE] sandbox-temp-path ·
Uh oh!
There was an error while loading. Please reload this page.