Skip to content

fix: avoid dev-hook false positives in non-dev commands#356

Open
tsubasakong wants to merge 3 commits intoaffaan-m:mainfrom
tsubasakong:fix/352-dev-server-hook-heredoc-false-positive
Open

fix: avoid dev-hook false positives in non-dev commands#356
tsubasakong wants to merge 3 commits intoaffaan-m:mainfrom
tsubasakong:fix/352-dev-server-hook-heredoc-false-positive

Conversation

@tsubasakong
Copy link
Contributor

@tsubasakong tsubasakong commented Mar 7, 2026

Description

  • only apply dev-server blocking when the leading command word is actually a dev-command launcher (or shell wrapper), instead of scanning any prose in the segment
  • keep support for env/prefix wrappers like env npm run dev while allowing commands like gh pr create that mention dev commands inside quoted or heredoc text
  • add an integration test covering the heredoc reproduction from False positive: dev-server-block hook triggers on heredoc content in non-dev commands #352

Fixes #352

Validation:

  • node tests/integration/hooks.test.js
  • node scripts/ci/validate-hooks.js

Type of Change

  • fix: Bug fix
  • feat: New feature
  • refactor: Code refactoring
  • docs: Documentation
  • test: Tests
  • chore: Maintenance/tooling
  • ci: CI/CD changes

Checklist

  • Tests pass locally (node tests/run-all.js)
  • Validation scripts pass
  • Follows conventional commits format
  • Updated relevant documentation

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

Token-level parsing is added to the dev-server-block hook: it extracts the leading command word of each shell segment (skipping recognized prefixes) and only applies the dev-pattern/tmux checks when that leading word is a known package-manager command, preventing false positives from heredoc or prose content.

Changes

Cohort / File(s) Summary
Hook Logic Refinement
scripts/hooks/pre-bash-dev-server-block.js
Adds DEV_COMMAND_WORDS, SKIPPABLE_PREFIX_WORDS, PREFIX_OPTION_VALUE_WORDS; implements readToken, isOptionToken, shouldSkipOptionValue, getLeadingCommandWord; reworks per-segment dev detection to use leading command word before applying devPattern and tmuxLauncher checks.
Test Coverage
tests/integration/hooks.test.js
Introduces devServerBlockerPath and invokes blocker script directly; adds tests for heredoc-containing non-dev commands and env/sudo-prefixed dev commands; updates expectations for Windows vs non-Windows behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • affaan-m

Poem

🐰 I sniffed the command, not the tale inside,
No longer do prose and heredoc make me chide.
I hop to the word, skip the padded bits,
And only block when a true dev-run fits.
🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing false positives in the dev hook by targeting non-dev commands.
Linked Issues check ✅ Passed The pull request comprehensively implements all coding requirements from issue #352: it adds tokenization logic to identify leading command words, skips known wrapper prefixes (env, sudo, etc.), applies dev pattern checks only to actual dev-command launchers, adds test coverage for heredocs, and preserves env/prefix wrapper support.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #352: the script refactoring in pre-bash-dev-server-block.js addresses the false positive root cause, and test additions validate the fix without introducing unrelated modifications.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/hooks/pre-bash-dev-server-block.js">

<violation number="1" location="scripts/hooks/pre-bash-dev-server-block.js:111">
P2: Wrapper option tokens are treated as the command word, which lets `env`/`sudo`-prefixed dev commands bypass blocking.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/hooks/pre-bash-dev-server-block.js`:
- Around line 20-21: The parsing currently lets env -S/--split-string bypass
because the split-string argument (the following token) is ignored; update the
parser so PREFIX_OPTION_VALUE_WORDS handling treats '-S' and '--split-string' as
options that consume the next token as the command string and skips that
consumed token when computing the leading command; modify getLeadingCommandWord
to recognize and advance past the split-string value (same change for the other
occurrences referenced around lines 128-133) so env -S "npm run dev" yields
"npm" as the leading command.
- Around line 13-17: When a wrapper command from DEV_COMMAND_WORDS is detected,
we should not run devPattern against the entire raw segment because quoted
arguments (e.g., bash -lc 'echo "npm run dev"' or tmux display-message "npm run
dev") cause false positives; instead, extract the inner command string passed to
the wrapper (strip wrapper name and common flags like -c, -lc, --, and
tmux/display-message argument wrappers) or skip quoted/heredoc sections, then
run devPattern only on that extracted/unquoted command; update the logic that
currently calls devPattern on the full raw segment so it first detects wrapper
commands in DEV_COMMAND_WORDS, extracts the actual child command, unquotes or
removes heredoc content, and only then applies devPattern to avoid
wrapper-induced false positives.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d7146ffb-9e1e-4191-b02e-e608fa2114cd

📥 Commits

Reviewing files that changed from the base of the PR and between c39bbab and 4eb8db7.

📒 Files selected for processing (2)
  • scripts/hooks/pre-bash-dev-server-block.js
  • tests/integration/hooks.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/integration/hooks.test.js

Comment on lines +13 to +17
'bash',
'sh',
'zsh',
'fish',
'tmux'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Wrapper commands can still false-positive on quoted text.

Because bash, sh, zsh, fish, and tmux are in DEV_COMMAND_WORDS, Line 165 still runs devPattern on the full raw segment after the wrapper is identified. Cases like bash -lc 'echo "npm run dev"' or tmux display-message "npm run dev" will still be blocked even though they never start a dev server, so the quoted/heredoc false-positive path remains for wrapper commands.

Also applies to: 160-166

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/hooks/pre-bash-dev-server-block.js` around lines 13 - 17, When a
wrapper command from DEV_COMMAND_WORDS is detected, we should not run devPattern
against the entire raw segment because quoted arguments (e.g., bash -lc 'echo
"npm run dev"' or tmux display-message "npm run dev") cause false positives;
instead, extract the inner command string passed to the wrapper (strip wrapper
name and common flags like -c, -lc, --, and tmux/display-message argument
wrappers) or skip quoted/heredoc sections, then run devPattern only on that
extracted/unquoted command; update the logic that currently calls devPattern on
the full raw segment so it first detects wrapper commands in DEV_COMMAND_WORDS,
extracts the actual child command, unquotes or removes heredoc content, and only
then applies devPattern to avoid wrapper-induced false positives.

Comment on lines +20 to +21
const PREFIX_OPTION_VALUE_WORDS = {
env: new Set(['-u', '-C', '-S', '--unset', '--chdir', '--split-string']),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

env -S currently creates a bypass.

-S / --split-string hold the command string that env will execute, but this path skips that value entirely. env -S "npm run dev" therefore returns null from getLeadingCommandWord() and never reaches the blocker, which is the opposite of the wrapper support this PR is adding.

💡 Minimal direction
     if (activeWrapper && isOptionToken(token)) {
       if (shouldSkipOptionValue(activeWrapper, token)) {
+        if (activeWrapper === 'env' && (token === '-S' || token === '--split-string')) {
+          const value = readToken(segment, index);
+          return value ? getLeadingCommandWord(value.token) : null;
+        }
         skipNextValue = true;
       }
       continue;
     }

Also applies to: 128-133

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/hooks/pre-bash-dev-server-block.js` around lines 20 - 21, The parsing
currently lets env -S/--split-string bypass because the split-string argument
(the following token) is ignored; update the parser so PREFIX_OPTION_VALUE_WORDS
handling treats '-S' and '--split-string' as options that consume the next token
as the command string and skips that consumed token when computing the leading
command; modify getLeadingCommandWord to recognize and advance past the
split-string value (same change for the other occurrences referenced around
lines 128-133) so env -S "npm run dev" yields "npm" as the leading command.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

@affaan-m
Copy link
Owner

affaan-m commented Mar 9, 2026

Hey @tsubasakong — this has merge conflicts now. Could you rebase when you get a chance? Thanks!

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

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.

False positive: dev-server-block hook triggers on heredoc content in non-dev commands

2 participants