mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
Bind unified exec approvals to shell executables (#39311)
## Why An unfamiliar executable can ignore its arguments, so trust in an apparent inner command must not implicitly trust the executable that runs it. ## What changed - Evaluate unfamiliar shell executables alongside their parsed commands when determining unified exec approval requirements. Inner commands can add restrictions, but cannot grant trust to the executable. - Include the executable in reusable approval keys so approval for one custom shell does not apply to another. - Parse literal PowerShell scripts without launching the requested executable, preserving command policy checks before approval. ## Testing Add cross-platform coverage for spoofed shell paths, allowed and forbidden inner commands, explicit custom-shell approval, and session approval isolation. GitOrigin-RevId: 0dd2c7e9a2ac30965ef5fe5de1a8d2968bb5f9d0
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
mod powershell_parser;
|
||||
// Production safety and exec-policy callers migrate to this lowerer in a follow-up.
|
||||
#[allow(dead_code)]
|
||||
mod powershell_tree_sitter;
|
||||
|
||||
pub mod is_dangerous_command;
|
||||
@@ -8,3 +6,4 @@ pub mod is_safe_command;
|
||||
#[cfg(windows)]
|
||||
pub(crate) mod windows_safe_commands;
|
||||
pub(crate) use powershell_parser::try_parse_powershell_ast_commands;
|
||||
pub(crate) use powershell_tree_sitter::try_parse_powershell_commands;
|
||||
|
||||
@@ -10,7 +10,7 @@ use tree_sitter::Parser;
|
||||
/// Unknown syntax, parse recovery, and dynamic expressions fail closed instead of being guessed
|
||||
/// at. The accepted CST shapes intentionally cover only common literal command forms; rare
|
||||
/// PowerShell syntax and value-conversion cases stay opaque.
|
||||
pub(super) fn try_parse_powershell_commands(script: &str) -> Option<Vec<Vec<String>>> {
|
||||
pub(crate) fn try_parse_powershell_commands(script: &str) -> Option<Vec<Vec<String>>> {
|
||||
lower_with_tree_sitter(script).ok()
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::path::PathBuf;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
|
||||
use crate::command_safety::try_parse_powershell_ast_commands;
|
||||
use crate::command_safety::try_parse_powershell_commands;
|
||||
use crate::shell_detect::ShellType;
|
||||
use crate::shell_detect::detect_shell_type;
|
||||
|
||||
@@ -82,6 +83,14 @@ pub fn parse_powershell_command_into_plain_commands(
|
||||
try_parse_powershell_ast_commands(executable, script)
|
||||
}
|
||||
|
||||
/// Parse literal PowerShell commands without starting a PowerShell executable.
|
||||
///
|
||||
/// Unknown or dynamic syntax stays opaque so unfamiliar executables can be
|
||||
/// evaluated without running them before approval.
|
||||
pub fn parse_powershell_script_into_plain_commands(script: &str) -> Option<Vec<Vec<String>>> {
|
||||
try_parse_powershell_commands(script)
|
||||
}
|
||||
|
||||
/// This function attempts to find a powershell.exe executable on the system.
|
||||
pub fn try_find_powershell_executable_blocking() -> Option<AbsolutePathBuf> {
|
||||
try_find_powershellish_executable_in_path(&["powershell.exe"])
|
||||
@@ -156,6 +165,7 @@ mod tests {
|
||||
use super::extract_powershell_command;
|
||||
#[cfg(windows)]
|
||||
use super::parse_powershell_command_into_plain_commands;
|
||||
use super::parse_powershell_script_into_plain_commands;
|
||||
use super::prefix_powershell_script_with_utf8;
|
||||
|
||||
#[test]
|
||||
@@ -205,6 +215,17 @@ mod tests {
|
||||
assert_eq!(script, "Get-ChildItem | Select-String foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_powershell_command_chains_and_preserves_windows_paths() {
|
||||
assert_eq!(
|
||||
parse_powershell_script_into_plain_commands(r"echo safe && Remove-Item C:\important"),
|
||||
Some(vec![
|
||||
vec!["echo".to_string(), "safe".to_string()],
|
||||
vec!["Remove-Item".to_string(), r"C:\important".to_string()],
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefixes_powershell_command_with_best_effort_utf8() {
|
||||
let cmd = vec![
|
||||
|
||||
Reference in New Issue
Block a user