/ tools / PowerShellTool / destructiveCommandWarning.ts
destructiveCommandWarning.ts
  1  /**
  2   * Detects potentially destructive PowerShell commands and returns a warning
  3   * string for display in the permission dialog. This is purely informational
  4   * -- it doesn't affect permission logic or auto-approval.
  5   */
  6  
  7  type DestructivePattern = {
  8    pattern: RegExp
  9    warning: string
 10  }
 11  
 12  const DESTRUCTIVE_PATTERNS: DestructivePattern[] = [
 13    // Remove-Item with -Recurse and/or -Force (and common aliases)
 14    // Anchored to statement start (^, |, ;, &, newline, {, () so `git rm --force`
 15    // doesn't match — \b would match `rm` after any word boundary. The `{(`
 16    // chars catch scriptblock/group bodies: `{ rm -Force ./x }`. The stopper
 17    // adds only `}` (NOT `)`) — `}` ends a block so flags after it belong to a
 18    // different statement (`if {rm} else {... -Force}`), but `)` closes a path
 19    // grouping and flags after it are still this command's flags:
 20    // `Remove-Item (Join-Path $r "tmp") -Recurse -Force` must still warn.
 21    {
 22      pattern:
 23        /(?:^|[|;&\n({])\s*(Remove-Item|rm|del|rd|rmdir|ri)\b[^|;&\n}]*-Recurse\b[^|;&\n}]*-Force\b/i,
 24      warning: 'Note: may recursively force-remove files',
 25    },
 26    {
 27      pattern:
 28        /(?:^|[|;&\n({])\s*(Remove-Item|rm|del|rd|rmdir|ri)\b[^|;&\n}]*-Force\b[^|;&\n}]*-Recurse\b/i,
 29      warning: 'Note: may recursively force-remove files',
 30    },
 31    {
 32      pattern:
 33        /(?:^|[|;&\n({])\s*(Remove-Item|rm|del|rd|rmdir|ri)\b[^|;&\n}]*-Recurse\b/i,
 34      warning: 'Note: may recursively remove files',
 35    },
 36    {
 37      pattern:
 38        /(?:^|[|;&\n({])\s*(Remove-Item|rm|del|rd|rmdir|ri)\b[^|;&\n}]*-Force\b/i,
 39      warning: 'Note: may force-remove files',
 40    },
 41  
 42    // Clear-Content on broad paths
 43    {
 44      pattern: /\bClear-Content\b[^|;&\n]*\*/i,
 45      warning: 'Note: may clear content of multiple files',
 46    },
 47  
 48    // Format-Volume and Clear-Disk
 49    {
 50      pattern: /\bFormat-Volume\b/i,
 51      warning: 'Note: may format a disk volume',
 52    },
 53    {
 54      pattern: /\bClear-Disk\b/i,
 55      warning: 'Note: may clear a disk',
 56    },
 57  
 58    // Git destructive operations (same as BashTool)
 59    {
 60      pattern: /\bgit\s+reset\s+--hard\b/i,
 61      warning: 'Note: may discard uncommitted changes',
 62    },
 63    {
 64      pattern: /\bgit\s+push\b[^|;&\n]*\s+(--force|--force-with-lease|-f)\b/i,
 65      warning: 'Note: may overwrite remote history',
 66    },
 67    {
 68      pattern:
 69        /\bgit\s+clean\b(?![^|;&\n]*(?:-[a-zA-Z]*n|--dry-run))[^|;&\n]*-[a-zA-Z]*f/i,
 70      warning: 'Note: may permanently delete untracked files',
 71    },
 72    {
 73      pattern: /\bgit\s+stash\s+(drop|clear)\b/i,
 74      warning: 'Note: may permanently remove stashed changes',
 75    },
 76  
 77    // Database operations
 78    {
 79      pattern: /\b(DROP|TRUNCATE)\s+(TABLE|DATABASE|SCHEMA)\b/i,
 80      warning: 'Note: may drop or truncate database objects',
 81    },
 82  
 83    // System operations
 84    {
 85      pattern: /\bStop-Computer\b/i,
 86      warning: 'Note: will shut down the computer',
 87    },
 88    {
 89      pattern: /\bRestart-Computer\b/i,
 90      warning: 'Note: will restart the computer',
 91    },
 92    {
 93      pattern: /\bClear-RecycleBin\b/i,
 94      warning: 'Note: permanently deletes recycled files',
 95    },
 96  ]
 97  
 98  /**
 99   * Checks if a PowerShell command matches known destructive patterns.
100   * Returns a human-readable warning string, or null if no destructive pattern is detected.
101   */
102  export function getDestructiveCommandWarning(command: string): string | null {
103    for (const { pattern, warning } of DESTRUCTIVE_PATTERNS) {
104      if (pattern.test(command)) {
105        return warning
106      }
107    }
108    return null
109  }