Where does the bug appear (feature/product)?
Something else… — Workspace hooks (.cursor/hooks.json, beforeShellExecution)
Describe the Bug
On Windows, the JSON payload delivered to hook scripts via stdin is prefixed
with a UTF-8 BOM (\uFEFF). Any hook that does a standard
JSON.parse(readFileSync(0, "utf8")) throws on it. If the script handles the
parse error defensively (e.g. catch { return {} }), a security guard
silently degrades to allow-everything — no error surfaces anywhere.
We initially chased a phantom “subagents bypass beforeShellExecution” bug;
raw-logging stdin revealed the hook fires correctly on every channel (main
agent AND Multitask subagents, each with its own conversation_id) and the
payload is complete — it just starts with a BOM. So this is purely an
encoding issue, not a lifecycle one.
Steps to Reproduce
- Create
.cursor/hooks.jsonwith abeforeShellExecutionhook pointing to
a Node.mjsscript. - In the script, log the raw stdin:
appendFileSync("log.txt", JSON.stringify(readFileSync(0, "utf8")))
and thenJSON.parseit without stripping anything. - Ask the agent to run any shell command.
- Inspect
log.txt: the payload starts with\uFEFF{. TheJSON.parse
throwsSyntaxError: Unexpected token.
Workaround that fixes it:
const raw = readFileSync(0, "utf8").replace(/^\uFEFF/, "");
Expected Behavior
The stdin payload should be plain UTF-8 JSON without a BOM (or the BOM should
be documented so hook authors know to strip it). Given that hooks are used as
security guardrails, a silently unparseable payload is a safety issue: the
natural defensive catch turns the guard into allow-all.
Operating System
Windows 10/11 (repo checkout on the Windows filesystem; also verified the
same BOM from both PowerShell and WSL-side inspection)
Version Information
Cursor 3.13.10 (Windows 11)
For AI issues: which model did you use?
N/A — not model-related (reproduced identically with the hook fired by
main-agent and Multitask subagent sessions).
Additional Information
The hook lifecycle itself works correctly on Windows: we verified with a
controlled matrix that beforeShellExecution fires for the main agent and
for Multitask background subagents, and that deny responses are respected on
both channels once the BOM is stripped. The integrated (human) terminal
correctly does not trigger hooks. Only the BOM prefix is the problem.
Does this stop you from using Cursor?
No - Cursor works, but with this issue (though it can silently neutralize
security-oriented hooks, so the impact is worse than it looks).