Files
Alex Newman f03d918a47 fix(codex): stop an unparseable Bash command from blocking the tool call (#4001)
`extractFromBash` calls shell-quote's `parse()` on every Bash PreToolUse
command to enrich the payload with `filePaths` for read commands. `parse()`
throws on substitutions it cannot resolve, the throw was not caught here, and
it reached the generic hook handler — which logs `Hook error:` and returns
BLOCKING_ERROR. A best-effort convenience field was turning an ordinary shell
command into a blocked tool call.

Reproduced against the version actually installed here, not just the 1.8.4 in
the report:

    shell-quote 1.10.0
    parse("cat ${}")               -> throws  Bad substitution: ${}
    parse("echo hi && cat ${}")    -> throws  Bad substitution: ${}

The trigger is an *empty* substitution. `${FOO}`, `${#FOO}`, `${FOO:?err}` and
`${arr[@]}` all parse fine on 1.10.0, which is why the form matters: the guard
is needed on current dependencies, not only on the older one.

It also matters that `plugin/scripts/worker-service.cjs` — the file that ships —
carries a bundled copy containing the same `Bad substitution` throw, so the
behaviour does not depend on what a fresh `npm install` resolves.

The parse is now guarded and yields no paths on failure. Failing to enrich is
invisible; blocking the user's command is not.

Three tests, two of which fail without the guard (7 pass / 2 fail):

  - an unparseable substitution yields [] instead of throwing
  - the same when it rides alongside a genuinely readable file, so the failure
    is attributable to tokenisation rather than to a bad path
  - a command that parses still extracts its paths — the guard must not
    swallow the feature it protects

`bun test tests/cli tests/hooks` — 116 passed.

The committed bundle is left alone: rebuilding it here diverges from the
committed artifact for unrelated reasons, so it should be regenerated by the
normal release build rather than by this PR.

Co-authored-by: Nguyen Thanh Dat <ntdat812@gmail.com>
2026-09-10 22:21:34 -07:00
..