From 9deb4f9c86426c40ba1e189831d7bc3634dd7b94 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 7 Jul 2026 17:50:39 -0400 Subject: [PATCH] Handle mixed-case URLs in Windows command safety (#30879) ## Summary - recognize embedded HTTP(S) URL prefixes case-insensitively in Windows dangerous-command detection - add regression coverage for uppercase and mixed-case schemes inside `Start-Process` invocations ## Why PowerShell and URL parsing treat schemes case-insensitively, but the pre-parser only searched for lowercase `http://` and `https://`. When a URL appeared in the same shlex token as surrounding PowerShell syntax, such as `Start-Process('HTTPS://example.com');`, the prefix was not stripped and the command was incorrectly classified as not dangerous. Validated with the scoped `codex-shell-command` suite (138 tests) and a direct classifier reproduction that failed before the change and passed afterward. --- .../windows_dangerous_commands.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/codex-rs/shell-command/src/command_safety/windows_dangerous_commands.rs b/codex-rs/shell-command/src/command_safety/windows_dangerous_commands.rs index 9e5089d08d..8bcaf76266 100644 --- a/codex-rs/shell-command/src/command_safety/windows_dangerous_commands.rs +++ b/codex-rs/shell-command/src/command_safety/windows_dangerous_commands.rs @@ -315,9 +315,10 @@ fn looks_like_url(token: &str) -> bool { Lazy::new(|| Regex::new(r#"^[ "'\(\s]*([^\s"'\);]+)[\s;\)]*$"#).ok()); // If the token embeds a URL alongside other text (e.g., Start-Process('https://...')) // as a single shlex token, grab the substring starting at the first URL prefix. - let urlish = token + let lowercase_token = token.to_ascii_lowercase(); + let urlish = lowercase_token .find("https://") - .or_else(|| token.find("http://")) + .or_else(|| lowercase_token.find("http://")) .map(|idx| &token[idx..]) .unwrap_or(token); @@ -434,6 +435,19 @@ mod tests { ]))); } + #[test] + fn powershell_start_process_mixed_case_urls_are_dangerous() { + for script in [ + "Start-Process('HTTP://example.com');", + "Start-Process('hTtPs://example.com');", + ] { + assert!( + is_dangerous_command_windows(&vec_str(&["powershell", "-Command", script])), + "{script}" + ); + } + } + #[test] fn powershell_start_process_local_is_not_flagged() { assert!(!is_dangerous_command_windows(&vec_str(&[