fix(core) exec_policy parsing fixes (#11951)

## Summary
Fixes a few things in our exec_policy handling of prefix_rules:
1. Correctly match redirects specifically for exec_policy parsing. i.e.
if you have `prefix_rule(["echo"], decision="allow")` then `echo hello >
output.txt` should match - this should fix #10321
2. If there already exists any rule that would match our prefix rule
(not just a prompt), then drop it, since it won't do anything.


## Testing
- [x] Updated unit tests, added approvals ScenarioSpecs
This commit is contained in:
Dylan Hurd
2026-02-16 23:11:59 -08:00
committed by GitHub
parent 02e9006547
commit 0fbe10a807
3 changed files with 113 additions and 43 deletions

View File

@@ -128,9 +128,6 @@ pub fn parse_shell_lc_single_command_prefix(command: &[String]) -> Option<Vec<St
if root.has_error() {
return None;
}
if !has_named_descendant_kind(root, "heredoc_redirect") {
return None;
}
let command_node = find_single_command_node(root)?;
parse_heredoc_command_words(command_node, script)
@@ -237,20 +234,6 @@ fn is_literal_word_or_number(node: Node<'_>) -> bool {
node.named_children(&mut cursor).next().is_none()
}
fn has_named_descendant_kind(node: Node<'_>, kind: &str) -> bool {
let mut stack = vec![node];
while let Some(current) = stack.pop() {
if current.kind() == kind {
return true;
}
let mut cursor = current.walk();
for child in current.named_children(&mut cursor) {
stack.push(child);
}
}
false
}
fn is_allowed_heredoc_attachment_kind(kind: &str) -> bool {
matches!(
kind,
@@ -532,7 +515,10 @@ mod tests {
"-lc".to_string(),
"echo hello > /tmp/out.txt".to_string(),
];
assert_eq!(parse_shell_lc_single_command_prefix(&command), None);
assert_eq!(
parse_shell_lc_single_command_prefix(&command),
Some(vec!["echo".to_string(), "hello".to_string()])
);
}
#[test]
@@ -548,6 +534,16 @@ mod tests {
);
}
#[test]
fn parse_shell_lc_single_command_prefix_rejects_herestring_with_chaining() {
let command = vec![
"bash".to_string(),
"-lc".to_string(),
r#"echo hello > /tmp/out.txt && cat /tmp/out.txt"#.to_string(),
];
assert_eq!(parse_shell_lc_single_command_prefix(&command), None);
}
#[test]
fn parse_shell_lc_single_command_prefix_rejects_herestring_with_substitution() {
let command = vec![