Skip to content

fix(events): cap stdin in the generated dispatcher, not just the CLI command - #4337

Open
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/events-dispatcher-stdin-cap
Open

fix(events): cap stdin in the generated dispatcher, not just the CLI command#4337
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/events-dispatcher-stdin-cap

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

Summary

  • The fix: cap stdin read at 1 MiB to prevent DoS #3857 fix capped stdin at 1 MiB in specify event run (src/specify_cli/commands/event.py), but that CLI command is not the code path native hooks actually invoke.
  • Every installed integration writes a self-contained .specify/events.py dispatcher (the _EVENTS_DISPATCHER_TEMPLATE string in src/specify_cli/events.py), and native hook configs call that dispatcher directly. Its main() did:
    payload = sys.stdin.read() if not sys.stdin.isatty() else "{}"
    with no size cap at all — the exact DoS fix: cap stdin read at 1 MiB to prevent DoS #3857 was meant to close, wide open on the primary invocation path. specify event run is a secondary/manual entry point; the generated dispatcher is what actually runs on every session_start/pre_tool_use/etc. hook fire in real usage.
  • Fix: apply the same byte-capped read (from the binary buffer, so the cap counts encoded bytes rather than decoded characters) inside the dispatcher template, so every newly-installed or refreshed dispatcher enforces the limit.

Test plan

  • Added 3 tests in tests/integrations/test_events.py::TestCommandRunner: an oversized payload exits 1 with the limit message instead of running unbounded, a multibyte payload (~300k emoji, ~1.14 MiB UTF-8 but only 300k characters) is still rejected by the byte-based cap, and a normal under-the-cap payload still reaches the handler script unchanged.
  • Verified both new tests fail without the fix (test-the-test): the oversized-payload test failed because the dispatcher silently accepted the full payload and returned "not found" instead of exiting 1 with the limit message — reproducing the exact bug.
  • Ran the full tests/integrations/test_events.py suite: 124/128 pass; the remaining 4 are pre-existing Windows symlink-elevation failures unrelated to this change.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

https://claude.ai/code/session_01PJHJ2dHP2RVCNncHqN8Qm9

…command

The github#3857 fix capped stdin at 1 MiB in `specify event run`
(src/specify_cli/commands/event.py), but that command is not the code path
native hooks actually invoke. Every installed integration writes a
self-contained `.specify/events.py` dispatcher (the
`_EVENTS_DISPATCHER_TEMPLATE` string in src/specify_cli/events.py) that
native hook configs call directly, and its `main()` did:

    payload = sys.stdin.read() if not sys.stdin.isatty() else "{}"

with no size cap at all — the exact DoS github#3857 was meant to close, wide open
on the primary invocation path. `specify event run` is a secondary/manual
entry point; the generated dispatcher is what actually runs on every
session_start/pre_tool_use/etc. hook fire in real usage.

Fix: apply the same byte-capped read (from the binary buffer, so the cap
counts encoded bytes rather than decoded characters — matching the
just-merged fix for the CLI command) inside the dispatcher template, so
every newly-installed or refreshed dispatcher enforces the limit.

## Test plan
- Added 3 tests in tests/integrations/test_events.py::TestCommandRunner:
  an oversized payload exits 1 with the limit message instead of running
  unbounded, a multibyte payload (~300k emoji, ~1.14 MiB UTF-8 but only
  300k characters) is still rejected by the byte-based cap, and a normal
  under-the-cap payload still reaches the handler script unchanged.
- Verified both new failing-without-fix tests via test-the-test (stashed
  the src fix): the oversized-payload test failed because the dispatcher
  silently accepted the full payload and returned "not found" instead of
  exiting 1 with the limit message — reproducing the exact bug.
- Ran the full tests/integrations/test_events.py suite (124/128 pass; the
  remaining 4 are the pre-existing Windows symlink-elevation failures
  unrelated to this change).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJHJ2dHP2RVCNncHqN8Qm9
@Noor-ul-ain001
Noor-ul-ain001 requested a review from mnriem as a code owner August 26, 2026 09:53
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.

1 participant