Skip to content

fix: block-cli-workarounds denies commands with a quoted regex alternation #147

Closed

Description

@jmadren

Description

block-cli-workarounds.sh denies read-only commands whose arguments merely contain the
blocked words — specifically, any command carrying a quoted regex alternation such as
grep -nE "very_good|flutter test|foo" CLAUDE.md.

This is the failure mode #60 was closed against, resurfacing through a different route. The
current implementation splits the command on shell operators to avoid exactly this, and its
comment states the intent (lines 41–42):

# Split on shell operators and check the first two tokens of each subcommand.
# This avoids false positives from file paths (.dart) or quoted strings.
BLOCKED=$(echo "$COMMAND" | awk '{
  n = split($0, parts, /[;&|]+/)

The split is unquoted-aware only in the sense that it ignores quoting entirely. A | inside
a quoted string is treated as a pipe, so the alternation is chopped into fragments and each
fragment is tested as if it were a command:

grep -nE "very_good|flutter test|foo" CLAUDE.md

splits into grep -nE "very_good, flutter test, foo" CLAUDE.md. The middle fragment is
literally flutter test — no adjacent quote character to spoil the match — so b == "flutter" && s == "test" fires and the command is denied.

Position inside the alternation decides the outcome, which is what makes this confusing in
practice: as the last alternative the closing quote attaches to the token (test"), the
comparison fails, and the identical search is allowed.

Steps To Reproduce

Feed the hook a PreToolUse payload directly:

H=hooks/scripts/block-cli-workarounds.sh
mk() { printf '{"tool_name":"Bash","tool_input":{"command":"%s"}}' "$1"; }

mk 'grep -nE \"very_good|flutter test|foo\" CLAUDE.md' | bash "$H"   # denied
mk 'grep -nE \"very_good|flutter test\" CLAUDE.md'     | bash "$H"   # allowed

Observed:

Command Result Correct?
grep -nE "very_good|flutter test|foo" CLAUDE.md denied no
grep -nE "very_good|flutter test" CLAUDE.md allowed yes
flutter test denied yes
very_good dart test --coverage allowed yes

The genuine-bypass cases still behave correctly — this is purely over-blocking.

Expected Behavior

A read-only command is not denied because one of its arguments contains the blocked words.
Only an actual invocation of flutter/dart/very_good as the command being run should be
blocked.

Additional Context

This is not hypothetical: it fired during an audit of a repo's own agent instructions. The
command was a grep over CLAUDE.md / AGENTS.md files looking for stale guidance about
flutter test and dart test — i.e. searching for references to the very strings the plugin
governs is one of the likelier ways to hit this, which makes it disproportionately annoying
for maintenance and documentation work.

The failure is also silent in the sense that the denial message ("Do not use 'flutter test'
or 'dart test'. Use the very_good_cli MCP 'test' tool instead.") describes an action the
operator did not attempt, so the natural reading is that the harness is broken rather than
that a guard misfired.

Possible directions, in rough order of robustness:

  1. Tokenise with quoting awareness rather than a regex split — e.g. have the hook ask a shell
    to do it, or only inspect the segment before the first unquoted quote character.
  2. Keep the split, but skip any fragment whose originating position falls inside a quoted
    region.
  3. Narrowest fix: require the matched fragment to be at a real command position — i.e. the
    start of the string or immediately after an unquoted ;, &&, ||, or |.

Option 3 preserves the current structure and closes this case, though it would still be
defeated by an unquoted alternation, which is why 1 is the durable answer.

Related: #60 (previous false positive with .dart / test/ paths), #109.

Verified against plugin 0.0.5; hooks/scripts/block-cli-workarounds.sh is byte-identical
to main as of this writing.

Activity

  1. self-assigned this
    on Sep 22, 2026
  2. added 2 commits that reference this issue on Oct 5, 2026
    5c5786c
    cf5c743
  3. added a commit that references this issue on Oct 13, 2026
    7c9c3e8
  4. ryzizub commented on Oct 20, 2026

    @ryzizub
    Contributor

    Row 4 of the acceptance table is wrong. It lists very_good dart test --coverage as allowed. very_good dart is a subcommand, not dart passed as an argument:

    $ very_good --help
      dart   Command for running dart related commands.
      test   Run `flutter test` in a project.
             (Check very_good dart test for running `dart test` instead.)
    

    It really does run the Dart suite, so allowing it was a bypass. #172 denies it and names it as itself in the denial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions