Skip to content

fix(brainstorming): cap WebSocket frame payloads#1555

Open
therahul-yo wants to merge 1 commit into
obra:mainfrom
therahul-yo:fix-1446-brainstorm-ws-frame-limit
Open

fix(brainstorming): cap WebSocket frame payloads#1555
therahul-yo wants to merge 1 commit into
obra:mainfrom
therahul-yo:fix-1446-brainstorm-ws-frame-limit

Conversation

@therahul-yo
Copy link
Copy Markdown

What problem are you trying to solve?

Issue #1446 reports that skills/brainstorming/scripts/server.cjs trusts the 64-bit WebSocket payload length from a client frame and then allocates Buffer.alloc(payloadLen). Because the brainstorm companion server listens on localhost, a local process or browser context can advertise a huge frame length and make the server attempt a very large allocation.

This PR addresses only that concrete payload-size allocation bug from #1446. It does not attempt to fix the other two unrelated items in the bundled issue.

What does this PR change?

Adds a 10 MiB maximum WebSocket frame payload size, rejects oversized advertised payloads before allocation, and exports the limit for protocol tests. Adds a regression test that constructs an oversized 64-bit frame header and verifies decodeFrame() rejects it from the header alone.

Is this change appropriate for the core library?

Yes. The brainstorm companion server is part of the core brainstorming skill, and this hardens its built-in zero-dependency WebSocket parser for all users. It is not project-specific, team-specific, or tied to a third-party integration.

What alternatives did you consider?

I considered limiting only complete frames after buffer.length >= totalLen, but that still leaves the parser willing to wait for an enormous declared payload and keeps the bad length in control flow. Rejecting immediately after reading the extended length avoids the risky allocation path and makes the behavior explicit.

I also considered changing the server to use a WebSocket dependency, but Superpowers is intentionally dependency-light and this bug can be fixed locally in the existing parser.

Does this PR contain multiple unrelated changes?

No. This PR only caps inbound brainstorm WebSocket frame payloads and adds protocol-level coverage for that limit.

Existing PRs

I searched open and closed PRs for 1446, escape_for_json, payload-size, and find-polluter. I found #1504, which hardens a different brainstorm-server path (handleMessage null payload handling), and #1483, which addressed the separate find-polluter.sh spaced-path issue from #1446 and was closed. I did not find an open or merged PR that caps WebSocket frame payload length before allocation.

Environment tested

Harness (e.g. Claude Code, Cursor) Harness version Model Model version/ID
Codex local shell Codex desktop GPT-5 Codex session

System Node/npm on this machine is currently broken because Homebrew Node cannot load /opt/homebrew/opt/llhttp/lib/libllhttp.9.3.dylib. I used the Codex bundled Node runtime for the focused protocol test instead.

New harness support (required if this PR adds a new harness)

Not applicable. This PR does not add or modify harness support.

Clean-session transcript for "Let's make a react todo list"

Not applicable. This PR does not add or modify a harness integration.

Evaluation

Verification commands run:

/Users/rahul/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node tests/brainstorm-server/ws-protocol.test.js
git diff --check

Results:

--- Results: 32 passed, 0 failed ---

Rigor

  • If this is a skills change: I used superpowers:writing-skills and completed adversarial pressure testing (paste results below)
  • This change was tested adversarially, not just on the happy path
  • I did not modify carefully-tuned content (Red Flags table, rationalizations, "human partner" language) without extensive evals showing the change is an improvement

This PR changes parser code and a protocol test, not behavior-shaping skill prose. The regression test exercises an adversarial oversized 64-bit WebSocket frame header designed to trigger the reported allocation path.

Human review

  • A human has reviewed the COMPLETE proposed diff before submission

The complete two-file diff was shown in the Codex session and the human partner explicitly approved opening the PR.

@obra obra added bug Something isn't working brainstorming Brainstorming skill and visual companion needs-rebase-to-dev-branch PR targets main but should target dev labels May 23, 2026
@YOMXXX
Copy link
Copy Markdown

YOMXXX commented May 24, 2026

Review note after reading the issue, PR body, and diff:

This is a focused slice of #1446: it only addresses the WebSocket advertised-payload allocation path and leaves the unrelated escape_for_json / find-polluter.sh reports alone. That scope looks reviewable.

I did not see a code-level blocker in the patch. The important property is that the 64-bit length is checked before Number(...) and before any Buffer.alloc(payloadLen) path, and the test constructs only the header so it proves the rejection happens before payload allocation. The follow-up check for the 16-bit/normal payloadLen path also keeps oversized medium frames from allocating.

Process / verification items for reviewers:

  • This targets main; current repo flow appears to expect dev.
  • After rebase, run the focused protocol test and the server integration test, since nearby open PRs touch the same brainstorm server files: node tests/brainstorm-server/ws-protocol.test.js and node tests/brainstorm-server/server.test.js.
  • The chosen 10 MiB limit is a policy value. If maintainers want a different ceiling, that is likely the only design decision here; the mechanics of rejecting before allocation look sound.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

brainstorming Brainstorming skill and visual companion bug Something isn't working needs-rebase-to-dev-branch PR targets main but should target dev

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants