[codex] treat PowerShell stop-parsing forms as unsupported (#22643)

## Summary
- Treat PowerShell stop-parsing token forms as unsupported in the
AST-backed command flattener.
- Add focused regressions at the parser layer and Windows command-safety
layer.

## Why
The command-safety parser lowers PowerShell AST elements into argv-like
words. Stop-parsing syntax preserves a native-command argument shape
that this lowering does not model, so these forms should stay on the
conservative unsupported path.

## Validation
- `cargo fmt --manifest-path codex-rs/Cargo.toml --all --check`
- `cargo test --manifest-path codex-rs/Cargo.toml -p
codex-shell-command`
This commit is contained in:
Chris Bookholt
2026-05-14 06:28:34 -07:00
committed by GitHub
parent deedf3b2c4
commit 9ea38136b0
3 changed files with 33 additions and 0 deletions

View File

@@ -42,6 +42,15 @@ function Invoke-ParseRequest {
return @{ id = $RequestId; status = 'parse_errors' }
}
# PowerShell's stop-parsing marker hands the remaining source text to native
# commands with runtime argument handling that does not match the AST shape we
# flatten below. Keep that form out of the argv-like lowering path entirely.
foreach ($token in $tokens) {
if ($token.Text -eq '--%') {
return @{ id = $RequestId; status = 'unsupported' }
}
}
# Only accept AST shapes we can flatten into a list of argv-like command words.
# Anything more dynamic than that becomes "unsupported" instead of being guessed at.
$commands = [System.Collections.ArrayList]::new()

View File

@@ -296,4 +296,18 @@ mod tests {
]),
);
}
#[test]
fn parser_process_rejects_stop_parsing_forms() {
let Some(powershell) = try_find_powershell_executable_blocking() else {
return;
};
let powershell = powershell.as_path().to_str().unwrap();
let mut parser = PowershellParserProcess::spawn(powershell).unwrap();
let parsed = parser
.parse("git log --% HEAD --output=codex_poc.txt")
.unwrap();
assert_eq!(parsed, PowershellParseOutcome::Unsupported);
}
}

View File

@@ -402,6 +402,16 @@ mod tests {
);
}
#[test]
fn rejects_stop_parsing_git_forms() {
assert!(!is_safe_command_windows(&vec_str(&[
"powershell.exe",
"-NoProfile",
"-Command",
"git log --% HEAD --output=codex_poc.txt",
])));
}
#[test]
fn rejects_powershell_commands_with_side_effects() {
assert!(!is_safe_command_windows(&vec_str(&[