criticalBashPatterns top-level property

List<CriticalBashPattern> criticalBashPatterns
final

Patterns that force an approval prompt for any matching bash command.

Keep the list tight: add shapes that are virtually never legitimate in automation. A prompt (not a block) is the response — the user decides.

Implementation

final criticalBashPatterns = <CriticalBashPattern>[
  // Recursive destruction (issue #460): recursive means an explicit
  // -r/-R/--recursive flag cluster; root means `/`, a `/*`-style root
  // glob, `~`/`$HOME`, a drive root, or a single top-level component
  // (`/usr`). `rm -f /tmp/x` and `chmod -R 755 /var/www` never match.
  CriticalBashPattern(
    'recursive delete from a root path',
    (command) => _recursiveRootInvocation(command, 'rm'),
  ),
  CriticalBashPattern.regex(
    'sudo rm',
    RegExp(r'\bsudo\s+rm\b', caseSensitive: false),
  ),
  CriticalBashPattern(
    'recursive chmod from a root path',
    (command) => _recursiveRootInvocation(command, 'chmod'),
  ),
  CriticalBashPattern(
    'recursive chown from a root path',
    (command) => _recursiveRootInvocation(command, 'chown'),
  ),

  // Fork bomb (a few common spacings): `:(){ :|:& };:`.
  CriticalBashPattern.regex('fork bomb', RegExp(r':\(\)\s*\{\s*:\s*\|\s*:')),

  // Disk / filesystem destruction.
  CriticalBashPattern.regex(
    'write to a disk device',
    RegExp(r'>\s*/dev/sd[a-z]', caseSensitive: false),
  ),
  CriticalBashPattern.regex(
    'format filesystem',
    RegExp(r'\bmkfs(\.|\b)', caseSensitive: false),
  ),
  CriticalBashPattern.regex(
    'dd to a device',
    RegExp(r'\bdd\s+if=.+of=/dev/', caseSensitive: false),
  ),
  CriticalBashPattern.regex(
    'shred a device',
    RegExp(r'\bshred\s+/dev/', caseSensitive: false),
  ),

  // System-config destruction.
  CriticalBashPattern.regex(
    'overwrite of a system account file',
    RegExp(r'>\s*/etc/(passwd|shadow|sudoers)\b', caseSensitive: false),
  ),
  CriticalBashPattern.regex(
    'tee into a system account file',
    RegExp(
      r'\btee\s+(-a\s+)?/etc/(passwd|shadow|sudoers)\b',
      caseSensitive: false,
    ),
  ),

  // Remote-fetch-then-execute (curl/wget piped to a shell, process-subbed,
  // or evaled).
  CriticalBashPattern.regex(
    'remote fetch piped to a shell',
    // Require curl/wget and the pipe to live in the same shell command so an
    // unrelated `curl` mention (e.g. inside a commit message or a prior `&&`
    // clause) does not false-positive against a later `| bash`.
    RegExp(
      r'\b(curl|wget)\b[^|&;\n]*\|\s*(bash|sh|zsh|fish)\b',
      caseSensitive: false,
    ),
  ),
  CriticalBashPattern.regex(
    'remote fetch via process substitution',
    // `bash <(curl …)`, `source <(curl …)`, `. <(curl …)`; `.`/`source` are
    // anchored to a command boundary so `find . -name` doesn't match.
    RegExp(
      r'(^|[\s;&|(])(bash|sh|zsh|source|\.)\s+<\(\s*(curl|wget)\b',
      caseSensitive: false,
    ),
  ),
  CriticalBashPattern.regex(
    'remote fetch via eval',
    // `eval "$(curl …)"` / `eval $(curl …)`
    RegExp(r'\beval\s+"?\$\(\s*(curl|wget)\b', caseSensitive: false),
  ),
  CriticalBashPattern.regex(
    'remote fetch via eval backticks',
    RegExp(r'\beval\s+`\s*(curl|wget)\b', caseSensitive: false),
  ),

  // Process/host control. The power commands must sit at command position so
  // `npm run reboot-tests` or `echo 'shutdown the queue'` don't match.
  CriticalBashPattern.regex('kill PID 1', RegExp(r'\bkill\s+-9\s+1\b')),
  CriticalBashPattern.regex(
    'host shutdown/reboot',
    RegExp(
      r'(^|[\s;&|(])(shutdown|poweroff|reboot|halt)([\s;|&]|$)',
      caseSensitive: false,
    ),
  ),

  // Force-pushed git history (prompt, not block).
  CriticalBashPattern.regex(
    'git push --force',
    RegExp(r'\bgit\s+push\b[^|;]*\s(--force|-f)\b', caseSensitive: false),
  ),
];