Skip to content

fix(hooks): block rm long flags (--recursive --force) in denylist - #324

Merged
dngioidev merged 1 commit into
mainfrom
fix/312-denylist-rm-long-flags
Aug 1, 2026
Merged

fix(hooks): block rm long flags (--recursive --force) in denylist#324
dngioidev merged 1 commit into
mainfrom
fix/312-denylist-rm-long-flags

Conversation

@dngioidev

Copy link
Copy Markdown
Owner

What & why

The denylist recursive-delete rule captured only single-dash combined short flags via /((-[a-zA-Z]+\s*)+)/, so GNU long flags never matched — rm --recursive --force src/ (in any order) slipped past the block outside the safe-target dirs. The uppercase -R short form was also missed (the check was /r/, lowercase-only).

Now recursive is detected via short -r/-R or long --recursive, and force via short -f or long --force; both are required, in any order, still gated by SAFE_RM_TARGETS. The (?:^|\s)- anchor keeps double-dash long flags and mid-word dashes (file-r.txt) out of the short-flag bucket, so no false short-flag match. Short-flag behavior, the {blocked, rule, msg} shape, and the fail-open guard are unchanged. #311's full-string pipe-to-shell/eval rules are untouched.

Acceptance criteria

  • AC.1 — the rm rule blocks long-flag equivalents (--recursive AND --force, in any order) outside the SAFE_RM_TARGETS allowlist. Verified by AC-312.1 test (rm --recursive --force src/, rm --force --recursive src/, -R --force, chained segment) all → rule: 'recursive-delete'. --recursive alone (no force) still passes, by design.
  • AC.2 — tests cover rm --recursive --force src/ (blocked) and a safe-target delete like rm -rf node_modules (allowed). Verified by AC-312.1 and AC-312.2 tests (rm -rf node_modules, rm --recursive --force node_modules, rm --force --recursive dist build coverage all allowed).

Verification

pnpm verify green: 558/558 tests pass (50 files), including the agy denylist-parity test (AC-289.2) that exercises recursive-delete. No ReDoS: the new regex /(?:^|\s)-([a-zA-Z]+)/g is linear. No false positive on common safe deletes (safe-target gate preserved; --recursive-only still allowed).

Closes #312

🤖 Generated with Claude Code

The recursive-delete rule captured only single-dash combined short flags
via /((-[a-zA-Z]+\s*)+)/, so GNU long flags never matched and
`rm --recursive --force src/` (in any order) slipped past the denylist.
The -R uppercase short form was also missed (test was /r/, lowercase-only).

Detect recursive via short -r/-R or long --recursive, and force via short
-f or long --force, both required and in any order, still gated by
SAFE_RM_TARGETS so build/temp deletes stay allowed. The `(?:^|\s)-` anchor
keeps double-dash long flags and mid-word dashes out of the short-flag
bucket. Short-flag behavior, the {blocked,rule,msg} shape, and the
fail-open guard are unchanged. #311 full-string rules untouched.

Closes #312

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SATRHKa6mDHDuirhP6QuwL
@dngioidev
dngioidev merged commit 486f1b4 into main Aug 1, 2026
6 checks passed
@dngioidev
dngioidev deleted the fix/312-denylist-rm-long-flags branch August 1, 2026 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

denylist: rm rule misses long flags (recursive + force)

1 participant