mirror of
https://github.com/openai/codex.git
synced 2026-11-14 06:48:26 +00:00
fix(sandboxing): reject WSL1 bubblewrap sandboxing (#17559)
## Summary - detect WSL1 before Codex probes or invokes the Linux bubblewrap sandbox - fail early with a clear unsupported-operation message when a command would require bubblewrap on WSL1 - document that WSL2 follows the normal Linux bubblewrap path while WSL1 is unsupported ## Why Codex 0.115.0 made bubblewrap the default Linux sandbox. WSL1 cannot create the user namespaces that bubblewrap needs, so shell commands currently fail later with a raw bwrap namespace error. This makes the unsupported environment explicit and keeps non-bubblewrap paths unchanged. The WSL detection reads /proc/version, lets an explicit WSL<version> marker decide WSL1 vs WSL2+, and only treats a bare Microsoft marker as WSL1 when no explicit WSL version is present. addresses https://github.com/openai/codex/issues/16076 --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
1 parent
a4d5112b37
commit
cb870a169a
7 files changed
+169
-2
No files matched your search
@@ -14,6 +14,11 @@ const MISSING_BWRAP_WARNING: &str = concat!(
|
||||
);
|
||||
const USER_NAMESPACE_WARNING: &str =
|
||||
"Codex's Linux sandbox uses bubblewrap and needs access to create user namespaces.";
|
||||
pub(crate) const WSL1_BWRAP_WARNING: &str = concat!(
|
||||
"Codex's Linux sandbox uses bubblewrap, which is not supported on WSL1 ",
|
||||
"because WSL1 cannot create the required user namespaces. ",
|
||||
"Use WSL2 for sandboxed shell commands."
|
||||
);
|
||||
const USER_NAMESPACE_FAILURES: [&str; 4] = [
|
||||
"loopback: Failed RTM_NEWADDR",
|
||||
"loopback: Failed RTM_NEWLINK",
|
||||
@@ -38,6 +43,10 @@ fn should_warn_about_system_bwrap(sandbox_policy: &SandboxPolicy) -> bool {
|
||||
}
|
||||
|
||||
fn system_bwrap_warning_for_path(system_bwrap_path: Option<&Path>) -> Option<String> {
|
||||
if is_wsl1() {
|
||||
return Some(WSL1_BWRAP_WARNING.to_string());
|
||||
}
|
||||
|
||||
let Some(system_bwrap_path) = system_bwrap_path else {
|
||||
return Some(MISSING_BWRAP_WARNING.to_string());
|
||||
};
|
||||
@@ -68,6 +77,29 @@ fn system_bwrap_has_user_namespace_access(system_bwrap_path: &Path) -> bool {
|
||||
output.status.success() || !is_user_namespace_failure(&output)
|
||||
}
|
||||
|
||||
pub(crate) fn is_wsl1() -> bool {
|
||||
std::fs::read_to_string("/proc/version")
|
||||
.is_ok_and(|proc_version| proc_version_indicates_wsl1(&proc_version))
|
||||
}
|
||||
|
||||
fn proc_version_indicates_wsl1(proc_version: &str) -> bool {
|
||||
let proc_version = proc_version.to_ascii_lowercase();
|
||||
let mut remaining = proc_version.as_str();
|
||||
while let Some(marker) = remaining.find("wsl") {
|
||||
let version_start = marker + "wsl".len();
|
||||
let version_digits: String = remaining[version_start..]
|
||||
.chars()
|
||||
.take_while(char::is_ascii_digit)
|
||||
.collect();
|
||||
if let Ok(version) = version_digits.parse::<u32>() {
|
||||
return version == 1;
|
||||
}
|
||||
remaining = &remaining[version_start..];
|
||||
}
|
||||
|
||||
proc_version.contains("microsoft") && !proc_version.contains("microsoft-standard")
|
||||
}
|
||||
|
||||
fn is_user_namespace_failure(output: &Output) -> bool {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
USER_NAMESPACE_FAILURES
|
||||
|
||||
Reference in new issue
Block a user