Commit Graph

6 Commits

Author SHA1 Message Date
Jamkris
e2eaf4ac2f fix(hooks): cover brace groups + yarn-run/bun-bare dev variants
Two false-negatives surfaced in PR #1889 review:

1. Brace-group bypass (Greptile).
   `{ npm run dev; }` evaluates the dev command in the *current*
   shell — semantically distinct from `( ... )` but with the same
   effect for this hook. `splitShellSegments` correctly cleaves the
   group at `;` into `["{ npm run dev", "}"]`, but the first segment's
   leading token under `readToken` is the bare `{`, which was not in
   `DEV_COMMAND_WORDS`, so the dev-pattern check was skipped.

   Fix: treat `{` and `}` as no-op tokens in `getLeadingCommandWord`
   so we keep walking to the real command word. Matches how shell
   itself parses brace groups (the braces are reserved words, not
   commands). Bash requires a space after `{` and a terminator before
   `}` for an actual group, so `{npm run dev}` correctly remains
   allowed (single token `{npm`, not in `DEV_COMMAND_WORDS`).

2. Missing yarn-run / bun-bare variants (CodeRabbit).
   Both `yarn dev` *and* `yarn run dev` are valid (the latter is what
   `package.json` actually wires `dev` to under yarn 1.x). The same
   `(run )?` symmetry applies to bun. The previous `DEV_PATTERN` only
   matched `yarn\s+dev` and `bun\s+run\s+dev`, allowing the cross
   forms to pass through silently.

   Fix: `yarn(?:\s+run)?\s+dev` and `bun(?:\s+run)?\s+dev` — same
   shape `pnpm(?:\s+run)?\s+dev` was already using.

Verified after this commit (every form now exits 2):

  { npm run dev; }
  { npm run dev ; }
  echo hi && { npm run dev; }
  ({ npm run dev; })
  $( { npm run dev; } )
  yarn run dev
  bun dev

Verified still allowed (no regression):

  echo "{ npm run dev; }"   # literal inside double quotes
  {npm run dev}             # not a brace group per bash syntax
2026-05-14 12:23:55 +09:00
Jamkris
a7e51e8046 fix(hooks): close subshell bypass in pre-bash-dev-server-block
Before this commit the dev-server-block hook ran the leading-command
and dev-pattern check only against the top-level segments returned by
`splitShellSegments`, which doesn't split on `$(...)`, backticks, or
plain `(...)`. That left the policy bypassable by wrapping a dev
command in any of those constructs:

  $(npm run dev)
  `npm run dev`
  echo $(npm run dev)
  (npm run dev)

Each verified by piping a synthetic PreToolUse payload into the hook
on this branch: every form above returned exit 0 (allow) where a plain
`npm run dev` correctly returned exit 2 (block).

Fix: expand the check space before running the leading-command rule.
A small BFS walks the raw command, harvesting bodies from
`extractCommandSubstitutions` (`$(...)` and backticks) and from
`extractSubshellGroups` (plain `(...)`), then splits each harvested
body through `splitShellSegments` and feeds the result into the
existing `isBlockedDevSegment` check.

This preserves every existing allow case (`tmux new-session -d -s dev
"npm run dev"`, quoted-string mentions like `git commit -m "npm run
dev fix"`, `echo hi`) because the leading-command rule is unchanged —
only the set of segments it runs against grew.

Known limitation, not fixed here: `eval "$(echo npm run dev)"` still
slips through because the substitution body's leading command is
`echo`, and statically modeling echo's output to recover the executed
command is out of scope. The same class affects `gateguard-fact-force`
(via `eval "$(echo rm -rf /)"` etc.) and is best addressed in both
hooks together as a follow-up rather than as a one-off here.
2026-05-14 11:21:41 +09:00
Affaan Mustafa
af51fcacb7 fix: resolve PR 371 portability regressions 2026-03-09 22:49:43 -07:00
Affaan Mustafa
440178d697 fix: harden hook portability and plugin docs 2026-03-09 22:49:43 -07:00
zzzhizhi
177dd36e23 fix(hooks): allow tmux-wrapped dev server commands (#321)
* fix(hooks): fix shell splitter redirection/escape bugs, extract shared module

- Fix single & incorrectly splitting redirection operators (&>, >&, 2>&1)
- Fix escaped quotes (\", \') not being handled inside quoted strings
- Extract splitShellSegments into shared scripts/lib/shell-split.js
  to eliminate duplication between hooks.json, before-shell-execution.js,
  and pre-bash-dev-server-block.js
- Add comprehensive tests for shell splitting edge cases

* fix(hooks): handle backslash escapes outside quotes in shell splitter

Escaped operators like \&& and \; outside quotes were still being
treated as separators. Add escape handling for unquoted context.
2026-03-07 14:47:49 -08:00
Affaan Mustafa
48b883d741 feat: deliver v1.8.0 harness reliability and parity updates 2026-03-04 14:48:06 -08:00