/ tools / BashTool / destructiveCommandWarning.ts
destructiveCommandWarning.ts
  1  /**
  2   * Detects potentially destructive bash commands and returns a warning string
  3   * for display in the permission dialog. This is purely informational — it
  4   * 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    // Git — data loss / hard to reverse
 14    {
 15      pattern: /\bgit\s+reset\s+--hard\b/,
 16      warning: 'Note: may discard uncommitted changes',
 17    },
 18    {
 19      pattern: /\bgit\s+push\b[^;&|\n]*[ \t](--force|--force-with-lease|-f)\b/,
 20      warning: 'Note: may overwrite remote history',
 21    },
 22    {
 23      pattern:
 24        /\bgit\s+clean\b(?![^;&|\n]*(?:-[a-zA-Z]*n|--dry-run))[^;&|\n]*-[a-zA-Z]*f/,
 25      warning: 'Note: may permanently delete untracked files',
 26    },
 27    {
 28      pattern: /\bgit\s+checkout\s+(--\s+)?\.[ \t]*($|[;&|\n])/,
 29      warning: 'Note: may discard all working tree changes',
 30    },
 31    {
 32      pattern: /\bgit\s+restore\s+(--\s+)?\.[ \t]*($|[;&|\n])/,
 33      warning: 'Note: may discard all working tree changes',
 34    },
 35    {
 36      pattern: /\bgit\s+stash[ \t]+(drop|clear)\b/,
 37      warning: 'Note: may permanently remove stashed changes',
 38    },
 39    {
 40      pattern:
 41        /\bgit\s+branch\s+(-D[ \t]|--delete\s+--force|--force\s+--delete)\b/,
 42      warning: 'Note: may force-delete a branch',
 43    },
 44  
 45    // Git — safety bypass
 46    {
 47      pattern: /\bgit\s+(commit|push|merge)\b[^;&|\n]*--no-verify\b/,
 48      warning: 'Note: may skip safety hooks',
 49    },
 50    {
 51      pattern: /\bgit\s+commit\b[^;&|\n]*--amend\b/,
 52      warning: 'Note: may rewrite the last commit',
 53    },
 54  
 55    // File deletion (dangerous paths already handled by checkDangerousRemovalPaths)
 56    {
 57      pattern:
 58        /(^|[;&|\n]\s*)rm\s+-[a-zA-Z]*[rR][a-zA-Z]*f|(^|[;&|\n]\s*)rm\s+-[a-zA-Z]*f[a-zA-Z]*[rR]/,
 59      warning: 'Note: may recursively force-remove files',
 60    },
 61    {
 62      pattern: /(^|[;&|\n]\s*)rm\s+-[a-zA-Z]*[rR]/,
 63      warning: 'Note: may recursively remove files',
 64    },
 65    {
 66      pattern: /(^|[;&|\n]\s*)rm\s+-[a-zA-Z]*f/,
 67      warning: 'Note: may force-remove files',
 68    },
 69  
 70    // Database
 71    {
 72      pattern: /\b(DROP|TRUNCATE)\s+(TABLE|DATABASE|SCHEMA)\b/i,
 73      warning: 'Note: may drop or truncate database objects',
 74    },
 75    {
 76      pattern: /\bDELETE\s+FROM\s+\w+[ \t]*(;|"|'|\n|$)/i,
 77      warning: 'Note: may delete all rows from a database table',
 78    },
 79  
 80    // Infrastructure
 81    {
 82      pattern: /\bkubectl\s+delete\b/,
 83      warning: 'Note: may delete Kubernetes resources',
 84    },
 85    {
 86      pattern: /\bterraform\s+destroy\b/,
 87      warning: 'Note: may destroy Terraform infrastructure',
 88    },
 89  ]
 90  
 91  /**
 92   * Checks if a bash command matches known destructive patterns.
 93   * Returns a human-readable warning string, or null if no destructive pattern is detected.
 94   */
 95  export function getDestructiveCommandWarning(command: string): string | null {
 96    for (const { pattern, warning } of DESTRUCTIVE_PATTERNS) {
 97      if (pattern.test(command)) {
 98        return warning
 99      }
100    }
101    return null
102  }