Skip to content

security: maxBodySize bypassed by chunked transfer encoding (no Content-Length header) #151

@paulbreuler

Description

@paulbreuler

Severity: High

The HTTP server's `maxBodySize` limit checks the `Content-Length` request header only. Clients using chunked transfer encoding without a `Content-Length` header bypass the limit and can send arbitrarily large bodies.

Root cause

`src/server-http.ts` reads `req.headers['content-length']` and rejects early if it exceeds `maxBodySize`. But if the header is absent (chunked encoding), the full body is buffered with no byte-count enforcement.

Fix

Buffer the request stream manually and enforce the limit on actual bytes received:

```typescript
async function readBody(req: IncomingMessage, maxBytes: number): Promise {
return new Promise((resolve, reject) => {
const chunks: Buffer[] = [];
let total = 0;
req.on('data', (chunk: Buffer) => {
total += chunk.length;
if (total > maxBytes) {
reject(Object.assign(new Error('Payload Too Large'), { code: 'PAYLOAD_TOO_LARGE' }));
req.destroy();
return;
}
chunks.push(chunk);
});
req.on('end', () => resolve(Buffer.concat(chunks)));
req.on('error', reject);
});
}
```

Files to modify

  • `src/server-http.ts` — replace header-based size check with stream byte counting
  • `tests/server-http.test.ts` — add test: chunked body exceeding maxBodySize without Content-Length header

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity vulnerability or concern

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions