From b952bd264927d6824a9d5dafcbaceb111cfe8548 Mon Sep 17 00:00:00 2001 From: iceweasel-oai Date: Tue, 18 Nov 2025 16:43:34 -0800 Subject: [PATCH] smoketest for browser vuln, rough draft of Windows security doc (#6822) --- .../windows-sandbox-rs/sandbox_smoketests.py | 23 ++++++++++++++----- docs/windows_sandbox_security.md | 20 ++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 docs/windows_sandbox_security.md diff --git a/codex-rs/windows-sandbox-rs/sandbox_smoketests.py b/codex-rs/windows-sandbox-rs/sandbox_smoketests.py index fb8f90121..0fc049d4e 100644 --- a/codex-rs/windows-sandbox-rs/sandbox_smoketests.py +++ b/codex-rs/windows-sandbox-rs/sandbox_smoketests.py @@ -477,12 +477,23 @@ def main() -> int: rc, out, err = run_sbx("workspace-write", ["cmd", "/c", f"echo leak > {outside_after_timeout}"], WS_ROOT) add("WS: post-timeout outside write still denied", rc != 0 and assert_not_exists(outside_after_timeout), f"rc={rc}") - # 41. WS: additional protected path variation (.ssh) - ssh_var = WS_ROOT / ".SsH" / "config" - remove_if_exists(ssh_var.parent) - ssh_var.parent.mkdir(exist_ok=True) - rc, out, err = run_sbx("workspace-write", ["cmd", "/c", "echo key > .SsH\\config"], WS_ROOT) - add("WS: protected path variation (.ssh) denied", rc != 0 and assert_not_exists(ssh_var), f"rc={rc}") + # 41. RO: Start-Process https blocked (KNOWN FAIL until GUI escape fixed) + rc, out, err = run_sbx( + "read-only", + [ + "powershell", + "-NoLogo", + "-NoProfile", + "-Command", + "Start-Process 'https://codex-invalid.local/smoke'", + ], + WS_ROOT, + ) + add( + "RO: Start-Process https denied (KNOWN FAIL)", + rc != 0, + f"rc={rc}, stdout={out}, stderr={err}", + ) return summarize(results) diff --git a/docs/windows_sandbox_security.md b/docs/windows_sandbox_security.md new file mode 100644 index 000000000..3dab0449d --- /dev/null +++ b/docs/windows_sandbox_security.md @@ -0,0 +1,20 @@ +# Windows Sandbox Status + +## Implementation Overview + +When commands run via `codex sandbox windows …` (or when the CLI/TUI calls into the same crate in-process for sandboxed turns), the launcher configures a restricted Windows token and an allowlist policy scoped to the declared workspace roots. Writes are blocked everywhere except inside those roots (plus `%TEMP%` when workspace-write mode is requested), and common escape vectors such as alternate data streams, UNC paths, and device handles are denied proactively. The CLI also injects stub executables (for example, wrapping `ssh`) ahead of the host PATH so we can intercept dangerous tools before they ever leave the sandbox. + +## Known Security Limitations + +Running `python windows-sandbox-rs/sandbox_smoketests.py` with full filesystem and network access currently results in **37/42** passing cases. The list below focuses on the four high-value failures numbered #32 and higher in the smoketests (earlier tests are less security-focused). + +| Test | Purpose | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| ADS write denied (#32) | Ensures alternate data streams cannot be written inside the workspace, preventing tools from hiding payloads in ADS. The sandbox currently allows the write (process returns `rc=0`). | +| protected path case-variation denied (#33) | Confirms that protected directories such as `.git` remain blocked even when attackers use case tricks like `.GiT`. The current allowlist treats `.GiT` as distinct, so the write succeeds. | +| PATH stub bypass denied (#35) | Verifies that a workspace-provided `ssh.bat` shim placed ahead of the host PATH runs instead of the real `ssh`. The sandbox exits early before emitting the shim's `stubbed` output, so we cannot prove the interception works. | +| Start-Process https denied (KNOWN FAIL) (#41) | Validates that read-only runs cannot launch the host's default browser via `Start-Process 'https://...'`. Today the command succeeds (exit code 0) because Explorer handles the ShellExecute request outside the sandbox. The failure is captured by `windows-sandbox-rs/sandbox_smoketests.py` (last case). | + +## Want to Help? + +If you are a security-minded Windows user, help us get these tests passing! Improved implementations that make these smoke tests pass meaningfully reduce Codex's escape surface. After iterating, rerun `python windows-sandbox-rs/sandbox_smoketests.py` to validate the fixes and help us drive the suite toward 42/42.