VeryGoodOpenSource / VeryGoodOpenSource/vgv-ai-flutter-plugin

fix: check-vgv-cli decides for every tool, not just Very Good CLI ones

Open
#154 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Shell
Stars
162
Forks
23
Avg merge
2d 22h
Merged PRs (30d)
4

Description

Description

check-vgv-cli.sh never reads its stdin payload. It runs check_vgv_cli and emits a
deny/allow decision for whatever tool invoked it, trusting the matcher in
hooks/hooks.json to scope it. On a host where that matcher does not select correctly, the
hook decides for every tool call — a Dart tool-version check blocking browser-automation MCP
tools in a TypeScript/Next.js project with no Dart in it.

Reported from Cursor, where the plugin's hooks are picked up from a global
~/.claude/plugins/ install. Three faults stack.

1. The matcher cannot match under Cursor's tool-naming convention

The matcher is written in Claude Code's MCP naming, mcp__<server>__<tool>:

{ "matcher": "mcp__.*very-good-cli__.*", "hooks": [{ "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-vgv-cli.sh" }] }

Cursor names MCP tools MCP:<tool>. Captured preToolUse payload from Cursor 3.20.17 for a
browser MCP call, with the hook logging its own stdin:

{
  "tool_name": "MCP:browser_tabs",
  "tool_input": { "action": "list" },
  "hook_event_name": "preToolUse",
  "cursor_version": "3.20.17"
}

mcp__.*very-good-cli__.* cannot match MCP:browser_tabs — different separator, no server
segment. And the hook ran anyway, which is how that payload was captured. So under Cursor a
non-matching matcher is not exclusionary.

Note tool_name carries no server name under Cursor — a Very Good CLI test call arrives as
MCP:test, indistinguishable by name from any other server's test.

2. Both PreToolUse hooks decide without checking tool identity

check-vgv-cli.sh reads no payload at all:

$ echo '{"tool_name":"MCP:browser_tabs","tool_input":{"action":"list"}}' | bash hooks/scripts/check-vgv-cli.sh
{"hookSpecificOutput":{"permissionDecision":"deny","permissionDecisionReason":"Very Good CLI is not installed. ..."}}

The inverse is worse: when the CLI is present the same blind path returns allow, silently
auto-approving unrelated MCP tool calls and bypassing the permission prompt.

block-cli-workarounds.sh has the same class of bug with a narrower trigger. It filters on
.tool_input.command — a field name, not tool identity — so any MCP tool carrying a command
argument is inspected and can be denied:

$ echo '{"tool_name":"MCP:run_terminal_cmd","tool_input":{"command":"flutter test"}}' | bash hooks/scripts/block-cli-workarounds.sh
{"hookSpecificOutput":{"permissionDecision":"deny","permissionDecisionReason":"Do not use 'flutter test' or 'dart test'. ..."}}

Its matcher: "Bash" cannot match Cursor's Shell tool either, so it is equally unscoped there.
analyze.sh and format.sh are the only hooks that reliably stand aside.

3. The CLI lookup fails on a restricted PATH even when the CLI is installed

check_vgv_cli() resolves the binary with command -v very_good and nothing else.
dart pub global activate installs to ~/.pub-cache/bin, which is added by an interactive shell
rc and is not in /etc/paths. On the affected machine very_good --version reports 1.5.0,
yet the hook reported it missing.

A pub-cache fallback alone is not sufficient. The installed very_good is a sh shim that execs
dart:

$ env -i HOME=$HOME PATH=/usr/bin:/bin:/usr/sbin:/sbin ~/.pub-cache/bin/very_good --version
~/.pub-cache/bin/very_good: line 8: dart: command not found   (exit 127)

So an inconclusive check is currently indistinguishable from "not installed", and both produce a
deny.

Steps To Reproduce

  1. Install the plugin on a machine where very_good lives in ~/.pub-cache/bin.
  2. Open any project — a non-Dart one makes the point clearest.
  3. Call any MCP tool that is not a Very Good CLI tool (e.g. a browser MCP navigate).
  4. The call is denied with "Very Good CLI is not installed".

Driving the scripts directly reproduces each fault without a host:

$ echo '{"tool_name":"MCP:browser_tabs","tool_input":{"action":"list"}}' | bash hooks/scripts/check-vgv-cli.sh
$ echo '{"tool_name":"MCP:run_terminal_cmd","tool_input":{"command":"flutter test"}}' | bash hooks/scripts/block-cli-workarounds.sh
$ env -i HOME=$HOME PATH=/usr/bin:/bin:/usr/sbin:/sbin ~/.pub-cache/bin/very_good --version

Expected Behavior

A hook decides only for the tools it is responsible for. A Very Good CLI version check should
stand aside for any tool that is not a Very Good CLI tool, regardless of how a host applies
matcher, and should never deny — or silently auto-approve — an unrelated MCP call.

An inconclusive version check should not be reported as "not installed".

Additional Context

  • Version: vgv-ai-flutter-plugin 0.0.5 via very-good-claude-code-marketplace 1.0.5.
  • Related but distinct: #147 is over-blocking in block-cli-workarounds.sh via command-string
    parsing; the fault here is that the script inspects tools that are not its business at all.
  • #48 places Cursor at experimental tier with no guaranteed hook parity. This is not a request
    for parity — the hooks are already active on that host today and are blocking unrelated work.
    Fault 2 makes the plugin safe there regardless of whether parity is ever pursued.
  • #126 workstream 4 covers factoring hooks for multi-host adaptation. Scoping every hook on
    tool_name is a prerequisite for that work.
  • Open question for a follow-up, not required for the fix: because Cursor's preToolUse
    tool_name has no server segment, a *very-good-cli* guard stands aside for genuine Very Good
    CLI calls under Cursor, so the auto-approve is lost there. That is fail-safe. Restoring it
    needs either matching bare tool names (create, test, ...), which collide across MCP
    servers, or Cursor's dedicated beforeMCPExecution event.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with hooks/hooks.json, hooks/scripts/check-vgv-cli.sh, and hooks/scripts/block-cli-workarounds.sh, then reproduce the supplied stdin cases under a restricted PATH. Trace how each script identifies tools and reports version-check outcomes. Done means unrelated tool calls are left alone and inconclusive CLI checks are not reported as missing.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, shell
Domain
cli, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.