Skip to content

fix(events): stop event run crashing on every piped stdin payload - #4326

Open
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/event-run-stdin-eof-attribute
Open

fix(events): stop event run crashing on every piped stdin payload#4326
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/event-run-stdin-eof-attribute

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

Summary

  • event_run (src/specify_cli/commands/event.py) capped its stdin read at 1 MiB to prevent a DoS (fix: cap stdin read at 1 MiB to prevent DoS #3857), but the truncation check reads sys.stdin.eofthat attribute does not exist on any Python file-like object, including sys.stdin (hasattr(sys.stdin, "eof") is False).
  • Every piped-stdin invocation raised AttributeError: '...' object has no attribute 'eof' instead of running. Piped stdin is this command's documented primary use case ("Resolve and run an event-driven command script with stdin payload" — a native hook feeds it a JSON payload this way), and isatty() is False whenever stdin isn't an interactive terminal, so this fired on essentially every real invocation, not only oversized ones — the fix: cap stdin read at 1 MiB to prevent DoS #3857 DoS fix left the feature entirely broken.
  • The intended oversized-payload branch was also broken a second, independent way: raise typer.Exit(code=1, message="...")typer.Exit.__init__ accepts only code (verified via inspect.signature), not message — so that path raised TypeError instead of the documented clean error.
  • Fix: detect truncation the standard way — after reading the 1 MiB cap, read one more byte; a non-empty result means more data was waiting beyond it. Report the oversized-payload error via typer.echo(..., err=True) before raise typer.Exit(code=1).

Test plan

  • Added tests/test_event_command.py (no prior test coverage existed for this command): a normal piped payload reaches the handler intact, a TTY/no-stdin invocation falls back to "{}", and an oversized piped payload exits 1 with the limit message instead of crashing.
  • Verified all 3 tests fail without the fix — reproduced the exact AttributeError('...' object has no attribute 'eof') on every case, including the "no stdin" one (confirms isatty() is False under non-interactive invocation, matching real hook usage) — and pass with it.
  • Ran the new test module standalone — 3 passed.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01FW9fAYsCBCAgdKWovtSyqt

@Noor-ul-ain001
Noor-ul-ain001 requested a review from mnriem as a code owner August 25, 2026 15:29
`event_run` (src/specify_cli/commands/event.py) capped its stdin read at
1 MiB to prevent a DoS (github#3857), but the truncation check reads a `.eof`
attribute that does not exist on any Python file-like object, including
`sys.stdin` (`hasattr(sys.stdin, "eof")` is False). Every piped-stdin
invocation raised `AttributeError: '...' object has no attribute 'eof'`
instead of running — piped stdin is the command's documented primary use
case (a native hook feeds it a JSON payload this way), and `isatty()` is
False whenever stdin isn't an interactive terminal, so this fired on
essentially every real invocation, not just oversized ones.

Even the intended oversized-payload branch was broken a second way:
`typer.Exit(code=1, message=...)` — `typer.Exit.__init__` only accepts
`code`, not `message` — so that path raised `TypeError` instead of the
documented clean error.

Fix: detect truncation the standard way (read one more byte once the cap
is hit; a non-empty result means more data was waiting beyond it), and
report the oversized-payload error via `typer.echo(..., err=True)` before
`raise typer.Exit(code=1)`.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FW9fAYsCBCAgdKWovtSyqt
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