fix(gateguard): deny dd whose input path is not word-initial

DESTRUCTIVE_SQL_DD shared one trailing \b across every alternation arm.
`dd\s+if=` ends in `=`, and a \b after a non-word character only holds when
the NEXT character is a word character, so the arm matched `dd if=x` and
missed every path starting with `/`, `.` or a quote:

  dd if=/dev/zero of=/dev/sda    allowed
  dd if=./disk.img of=/dev/sdb   allowed
  dd if="/dev/zero" of=/dev/sda  allowed

The word-boundary suffix now applies only to the arms that end in a word
character. The split is what keeps the widening bounded: dropping the
trailing \b outright would let `truncate` match `truncated`, and dropping the
leading \b would let `dd if=` match inside `add if=`. Both are covered.

This is the half of #2642 that survived the structural findGitSubcommand()
parser, which already handles `git checkout -- .`.

Not addressed here: `dd of=/dev/sda if=/dev/zero` with the operands reversed
is still allowed, before and after, because the pattern requires `if=`
immediately after `dd`. That is a different defect from the boundary bug and
widening a P0 gate's pattern shape is a maintainer call.

Refs #2642
This commit is contained in:
Nguyen Thanh Dat
2026-09-07 15:47:37 +07:00
parent e04ea0b9cc
commit 76786616f8
2 changed files with 66 additions and 1 deletions
+5 -1
View File
@@ -53,7 +53,11 @@ const ECC_ENABLE_VALUES = new Set(['1', 'true', 'on', 'enabled', 'enable', 'yes'
// phrases without shell-flag ordering concerns. Quoted strings are
// stripped before this regex runs so a commit message mentioning
// "drop table" no longer triggers a false positive.
const DESTRUCTIVE_SQL_DD = /\b(drop\s+table|delete\s+from|truncate|dd\s+if=)\b/i;
// The trailing \b applies only to the arms that end in a word character.
// `dd\s+if=` ends in `=`, so a shared \b demanded that the NEXT character be a
// word character and the disk-wipe spellings slipped through: `dd if=/dev/zero`
// and `dd if=./img` were allowed while `dd if=x` was denied (#2642).
const DESTRUCTIVE_SQL_DD = /\b(?:drop\s+table|delete\s+from|truncate)\b|\bdd\s+if=/i;
// Operator-supplied additional destructive patterns. Lazily compiled from
// `GATEGUARD_BASH_EXTRA_DESTRUCTIVE` (regex source) on first use, then