HarperFast / HarperFast/harper

Unbounded per-subscriber realtime event queue: a slow/stalled subscriber grows server heap without limit (DoS)

Open
#1,566 1 comment 0 reactions 0 assignees View on GitHub
area:security
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## Summary

The realtime event-delivery path (per-subscriber event queue reached via `Table.send()`) has no high-water / backpressure cap. A subscriber (SSE / WebSocket / MQTT) that reads slowly or stalls, combined with a high write rate on the subscribed table, causes the server to buffer that subscriber's events in heap without limit. On socket teardown the buffered queue is not released.

## Impact

- Per-subscriber server heap grows roughly linearly with writes-while-stalled. Blast radius is **self-only** — healthy subscribers are unaffected (no head-of-line blocking).
- A deliberately-stalled subscriber under high write volume, or many naturally-slow subscribers (e.g. slow mobile clients), can drive the process toward OOM.
- Teardown does not release the buffered queue, so the growth persists after the slow subscriber disconnects.

## Suggested direction

- Add a high-water cap to the realtime per-subscriber queue, with a drop-oldest or disconnect-slow-consumer policy on overflow (the backpressure/`waitForDrain` mechanism that exists on the audit-replay path is not applied here).
- Release the queue on socket teardown.

## Scope

- Confirmed on SSE and WebSocket. MQTT QoS-1 persistent-session parity to be confirmed.

_Detailed reproduction, heap measurements, and code references are in the private Security Notes for this issue._

Contributor guide

Open the contributing guide

Research direction

Start at the per-subscriber queue reached through Table.send() and compare the realtime delivery path with the audit-replay backpressure/waitForDrain mechanism. Inspect SSE and WebSocket teardown handling, then confirm MQTT QoS-1 persistent-session parity. Done means the queue is bounded with an overflow policy and is released on socket teardown, validated against the private reproduction and heap measurements.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
backend, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.