* Checks if an rm/rmdir command targets dangerous paths that should always * require explicit user approval, even if allowlist rules exist. * This prevents catastrophic data loss from commands like `rm -rf /`.
( command: 'rm' | 'rmdir', args: string[], cwd: string, )
| 68 | * This prevents catastrophic data loss from commands like `rm -rf /`. |
| 69 | */ |
| 70 | function checkDangerousRemovalPaths( |
| 71 | command: 'rm' | 'rmdir', |
| 72 | args: string[], |
| 73 | cwd: string, |
| 74 | ): PermissionResult { |
| 75 | // Extract paths using the existing path extractor |
| 76 | const extractor = PATH_EXTRACTORS[command] |
| 77 | const paths = extractor(args) |
| 78 | |
| 79 | for (const path of paths) { |
| 80 | // Expand tilde and resolve to absolute path |
| 81 | // NOTE: We check the path WITHOUT resolving symlinks, because dangerous paths |
| 82 | // like /tmp should be caught even though /tmp is a symlink to /private/tmp on macOS |
| 83 | const cleanPath = expandTilde(path.replace(/^['"]|['"]$/g, '')) |
| 84 | const absolutePath = isAbsolute(cleanPath) |
| 85 | ? cleanPath |
| 86 | : resolve(cwd, cleanPath) |
| 87 | |
| 88 | // Check if this is a dangerous path (using the non-symlink-resolved path) |
| 89 | if (isDangerousRemovalPath(absolutePath)) { |
| 90 | return { |
| 91 | behavior: 'ask', |
| 92 | message: `Dangerous ${command} operation detected: '${absolutePath}'\n\nThis command would remove a critical system directory. This requires explicit approval and cannot be auto-allowed by permission rules.`, |
| 93 | decisionReason: { |
| 94 | type: 'other', |
| 95 | reason: `Dangerous ${command} operation on critical path: ${absolutePath}`, |
| 96 | }, |
| 97 | // Don't provide suggestions - we don't want to encourage saving dangerous commands |
| 98 | suggestions: [], |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | // No dangerous paths found |
| 104 | return { |
| 105 | behavior: 'passthrough', |
| 106 | message: `No dangerous removals detected for ${command} command`, |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * SECURITY: Extract positional (non-flag) arguments, correctly handling the |
no test coverage detected