From 0951c8bc59f8679af1ee4589ef18e09b90503f71 Mon Sep 17 00:00:00 2001 From: KRATOS <84986124+gnanam1990@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:32:02 +0530 Subject: [PATCH] fix: run dangerous path check before auto-allowing rm/rmdir in acceptEdits mode (#246) In acceptEdits mode, filesystem commands (rm, rmdir, mv, cp, sed, mkdir, touch) were returned as 'allow' before checkDangerousRemovalPaths ran. This meant rm -rf ~ and rm -rf / bypassed the dangerous path guard entirely. Fix: - Export checkDangerousRemovalPaths from pathValidation.ts - In modeValidation.ts, call it for rm/rmdir before returning allow - Safe paths (rm file.txt) continue to auto-allow unchanged - Dangerous paths (rm -rf ~) now return 'ask' requiring user approval This is a defense-in-depth guard that matters most for 3P models (local Ollama, DeepSeek etc.) that lack built-in refusal training and would blindly execute destructive commands in acceptEdits mode. Fixes finding 3 from issue #244. Co-authored-by: Claude Sonnet 4.6 --- src/tools/BashTool/modeValidation.ts | 13 +++++++++++++ src/tools/BashTool/pathValidation.ts | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/tools/BashTool/modeValidation.ts b/src/tools/BashTool/modeValidation.ts index 2993c3e7..5e5147d1 100644 --- a/src/tools/BashTool/modeValidation.ts +++ b/src/tools/BashTool/modeValidation.ts @@ -1,8 +1,10 @@ import type { z } from 'zod/v4' import type { ToolPermissionContext } from '../../Tool.js' import { splitCommand_DEPRECATED } from '../../utils/bash/commands.js' +import { getCwd } from '../../utils/cwd.js' import type { PermissionResult } from '../../utils/permissions/PermissionResult.js' import type { BashTool } from './BashTool.js' +import { checkDangerousRemovalPaths } from './pathValidation.js' const ACCEPT_EDITS_ALLOWED_COMMANDS = [ 'mkdir', @@ -39,6 +41,17 @@ function validateCommandForMode( toolPermissionContext.mode === 'acceptEdits' && isFilesystemCommand(baseCmd) ) { + // Guard: always run dangerous path check for rm/rmdir before auto-allowing. + // This prevents rm -rf ~ / rm -rf / from bypassing checkDangerousRemovalPaths + // which is otherwise skipped when acceptEdits returns allow early. + if (baseCmd === 'rm' || baseCmd === 'rmdir') { + const args = trimmedCmd.split(/\s+/).slice(1) + const dangerousResult = checkDangerousRemovalPaths(baseCmd, args, getCwd()) + if (dangerousResult.behavior !== 'passthrough') { + return dangerousResult + } + } + return { behavior: 'allow', updatedInput: { command: cmd }, diff --git a/src/tools/BashTool/pathValidation.ts b/src/tools/BashTool/pathValidation.ts index 8da98f8b..6fa8ca04 100644 --- a/src/tools/BashTool/pathValidation.ts +++ b/src/tools/BashTool/pathValidation.ts @@ -67,7 +67,7 @@ export type PathCommand = * require explicit user approval, even if allowlist rules exist. * This prevents catastrophic data loss from commands like `rm -rf /`. */ -function checkDangerousRemovalPaths( +export function checkDangerousRemovalPaths( command: 'rm' | 'rmdir', args: string[], cwd: string,