Skip to content

tunnel: 10MB MAX_MESSAGE_SIZE cap is inconsistent with the 20MB body-limit default and ignores base64 framing overhead #567

Description

@melvincarvalho

Follow-up surfaced in the #563 / #566 review (default request body limit raised 10MB → 20MB).

Problem

The tunnel proxy has its own hard-coded 10 MB cap that #563's body-limit change does not touch, so the tunnel path is now the bottleneck — and it's inconsistent in three ways.

src/tunnel/index.js:

const MAX_MESSAGE_SIZE = 10 * 1024 * 1024; // 10MB   (line 82)
...
socket.on('message', (data) => {
  const raw = Buffer.isBuffer(data) ? data : Buffer.from(data);
  if (raw.byteLength > MAX_MESSAGE_SIZE) {           // line 137
    socket.send(JSON.stringify({ type: 'error', message: 'Message too large' }));
    return;
  }

1. Inconsistent with the new 20MB HTTP body default

config.defaults.bodyLimit is now 20 MiB (#563) and configurable via --body-limit / JSS_BODY_LIMIT. MAX_MESSAGE_SIZE is a separate, hard-coded 10 MB constant with no knob. A deployment that raises --body-limit to accept larger payloads still silently caps anything traversing a tunnel at 10 MB.

2. Direction-specific, and the cap bites responses

MAX_MESSAGE_SIZE is enforced only in socket.on('message') — i.e. messages the relay receives from the tunnel client, which are the response frames carrying the HTTP response body. So a tunnelled download (e.g. git clone/fetch of a repo, or any large GET) whose body exceeds the cap fails with Message too large. The request direction (relay→client, e.g. a push upload) is governed instead by the relay's HTTP bodyLimit on intake — a different limit on a different leg. The two legs of one tunnelled round-trip are bounded by two unrelated, unaligned numbers.

3. base64 framing overhead isn't accounted for

Bodies are base64-encoded into the JSON frames (tunnelReq.body = …toString('base64'), and the response side likewise). base64 inflates ~33%, so the effective content limit is ~7.5 MB, not 10 MB — and a body sized right at a configured limit won't fit once framed.

Suggested direction

  • Derive the tunnel message cap from the effective bodyLimit (plus base64 headroom, ~×1.4) instead of a separate constant, OR make it independently configurable and document the relationship.
  • Apply a consistent bound to both legs (request frame out, response frame in) so a tunnelled round-trip has one predictable size budget.
  • Account for base64 inflation so a payload at the body limit actually traverses the tunnel.

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is neededtunnelTunnel: WebRTC tunnel, /.tunnel WS, client/relay modes (src/tunnel)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions