crossbario / crossbario/autobahn-python

[META] Transport payload-size limits: consistent, correct, cross-transport enforcement

Open
#1,907 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

CI-CD websocket
Dominant language
Python
Stars
2.5k
Forks
768
PR merge metrics
No merged PRs in 30d

Description

Summary

This is a tracking epic for a coordinated hardening of payload/message size
limits
across the Autobahn|Python transports (WebSocket + RawSocket) and their
use in Crossbar.io. It originates from a reported denial-of-service issue
(security advisory GHSA-hxp9-w8x3-p566, "permessage-deflate bypasses
maxMessagePayloadSize after inflation", reported by Team Atlanta), but the
investigation surfaced a small cluster of related defects and design gaps that
are best fixed together so the size-limit model is finally coherent.

No development happens on this issue. Each child below is fixed on its own
issue + branch + PR, following our TDD red/green workflow (add the failing test
first, prove it red in CI, then fix, prove it green — all on the child's PR).
This epic is closed manually once all children are done.

The core problem: one knob, four possible meanings

There are two independent axes to a "size limit":

on-the-wire (compressed) at-the-application (uncompressed)
per-frame maxFramePayloadSize (correct) (no knob — covered transitively)
per-message (no knob — covered transitively) maxMessagePayloadSize

Today maxMessagePayloadSize is documented as bounding the "re-assembled
payload" (uncompressed), enforced on send against the uncompressed message,
and enforced by RawSocket against the (uncompressed, no-compression) wire
message — but on the WebSocket receive path (Hybi/v13) it is enforced against
the compressed frame length
, before inflation. A tiny compressed frame can
therefore inflate past the configured limit and reach the application. Hixie
(v0) already accounts uncompressed bytes correctly; Hybi is the outlier.

Agreed design (see child issues for detail)

  • D1 — semantic anchor. maxMessagePayloadSize = maximum size of a single
    serialized WAMP message (transport payload), measured uncompressed
    — i.e.
    before compression on send, after decompression on receive. This is already
    true on send, on RawSocket, and on Hixie receive; we bring Hybi receive in
    line. Default stays 0 (unlimited), so no existing deployment changes.
  • D2 — two knobs, correctly defined. maxMessagePayloadSize (per-message,
    uncompressed) + maxFramePayloadSize (per-frame, wire). The other two matrix
    cells are covered transitively (enforcing the uncompressed per-message cap
    during inflation also bounds a single-frame bomb; bounding uncompressed
    transitively bounds accepted wire bytes). We deliberately do not add more
    knobs — the existing two, defined correctly, are sufficient and less confusing.
  • Enforcement site. Backend-agnostic, at the inflation site in
    onFrameData, so it works identically in message mode and streaming
    (frame-based) mode
    (which differ only by which onMessage* callbacks a
    consumer overrides), and independently of the compression backend
    (deflate / snappy / bzip2 / brotli).

Children (dependency-ordered)

  1. https://github.com/crossbario/autobahn-python/issues/1908
  2. https://github.com/crossbario/autobahn-python/issues/1909
  3. https://github.com/crossbario/autobahn-python/issues/1910
  4. https://github.com/crossbario/autobahn-python/issues/1911
  5. https://github.com/crossbario/crossbar/issues/2250

Cross-references

  • Security advisory: GHSA-hxp9-w8x3-p566 (public; developed in the open).
  • Related class: CVE-2016-10544 (ws / Node.js — same compressed-vs-decompressed
    boundary mistake).
  • Ties into the Track T testing epic (parametrized both-backend / both-transport
    / multi-codec size-limit coverage; Crossbar zip-bomb functest into CI).

This work is being completed with AI assistance (Claude Code); all commits are
human-reviewed per AI_POLICY.md.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

This is a tracking epic, so start with child issues 1908, 1909, 1910, 1911, and Crossbar issue 2250 rather than making changes here. Read the agreed design and the onFrameData enforcement point; the epic is done when each child has its own tested PR and all listed work is complete.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, networking
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
15/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.