Fail closed on deeply nested command wrappers (#39122)

## Why

Dangerous-command inspection has a bounded wrapper depth. Returning no match
after that limit could let a nested dangerous payload escape policy detection.

## What changed

- Classify commands beyond the wrapper-depth limit as dangerous.
- Cover the boundary and overflow cases in the command-safety unit tests.
- Verify that exec policy rejects a deeply `env`-wrapped forced `rm` before it
  can delete a sentinel file when approvals are disabled.

GitOrigin-RevId: a6cdbbb7bdc6274a62745f668189fabaaf46745f
This commit is contained in:
Charlie Marsh
2026-08-18 02:23:57 +00:00
committed by copyberry
parent ede5247893
commit f97e775693
2 changed files with 84 additions and 1 deletions
@@ -25,7 +25,7 @@ fn dangerous_command_match_with_depth(
wrapper_depth: usize,
) -> Option<DangerousCommandMatch> {
if wrapper_depth > MAX_DANGEROUS_COMMAND_WRAPPER_DEPTH {
return None;
return Some(DangerousCommandMatch::Other);
}
if let Some(dangerous_match) = dangerous_command_match_for_exec(command, wrapper_depth) {
@@ -288,6 +288,27 @@ mod tests {
}
}
#[test]
fn deeply_nested_command_wrappers_fail_closed() {
for (depth, expected) in [
(
MAX_DANGEROUS_COMMAND_WRAPPER_DEPTH,
DangerousCommandMatch::ForcedRm,
),
(
MAX_DANGEROUS_COMMAND_WRAPPER_DEPTH + 1,
DangerousCommandMatch::Other,
),
] {
let command = std::iter::repeat_n("env", depth)
.chain(["rm", "-rf", "/tmp/example"])
.map(str::to_owned)
.collect::<Vec<_>>();
assert_eq!(dangerous_command_match(&command), Some(expected));
}
}
#[test]
fn forced_rm_in_complex_shell_syntax_is_dangerous() {
for script in [