Compare commits

...

1 Commits

Author SHA1 Message Date
Chris Bookholt
a68d68e30f shell-command: reject PowerShell param blocks 2026-05-22 15:47:04 +00:00
3 changed files with 30 additions and 0 deletions

View File

@@ -42,6 +42,12 @@ function Invoke-ParseRequest {
return @{ id = $RequestId; status = 'parse_errors' }
}
# Script parameter blocks can contain expressions that are evaluated outside
# of the end-block statements we flatten below.
if ($ast.ParamBlock -ne $null) {
return @{ id = $RequestId; status = 'unsupported' }
}
# 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.

View File

@@ -310,4 +310,18 @@ mod tests {
.unwrap();
assert_eq!(parsed, PowershellParseOutcome::Unsupported);
}
#[test]
fn parser_process_rejects_param_blocks() {
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("param([string]$path = (Get-Location)) Write-Output test")
.unwrap();
assert_eq!(parsed, PowershellParseOutcome::Unsupported);
}
}

View File

@@ -412,6 +412,16 @@ mod tests {
])));
}
#[test]
fn rejects_powershell_param_blocks() {
assert!(!is_safe_command_windows(&vec_str(&[
"powershell.exe",
"-NoProfile",
"-Command",
"param([string]$path = (Get-Location)) Write-Output test",
])));
}
#[test]
fn rejects_powershell_commands_with_side_effects() {
assert!(!is_safe_command_windows(&vec_str(&[