Skip to content

Security: Long-poll endpoint accumulates EventEmitter listeners without cleanup on client disconnect #291

Description

@LucasMaupin

Summary

The POST /production/:productionId/line/:lineId/participants long-poll endpoint registers a productionManager.once('users:change', handler) listener per request but does not clean it up when the client disconnects before the 25-second timeout.

Location

  • src/api_productions.ts — long-poll endpoint (~lines 922–934)
  • src/production_manager.tsProductionManager EventEmitter (~line 35)

Details

Two problems:

  1. Memory/listener leak: When a client disconnects mid-poll, the once listener and the setTimeout remain in memory until the 25-second timeout fires. Under load, this creates a growing number of stale listeners.

  2. MaxListeners warning: Node.js's default EventEmitter maxListeners is 10. With more than 10 concurrent polling clients, Node.js emits MaxListenersExceededWarning to stderr, potentially leaking concurrency information in log output.

Note: Rate limiting issues #201 and #256 would reduce exposure, but this cleanup issue is independent.

Recommendation

  1. Add a request.raw.on('close', ...) handler to remove the listener and clear the timeout on client disconnect:
const cleanup = () => {
  productionManager.off('users:change', handler);
  clearTimeout(timer);
  resolve([]);
};
request.raw.on('close', cleanup);
  1. Call productionManager.setMaxListeners(0) during initialization to suppress spurious warnings.

Severity

LOW

Activity

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

Metadata

Metadata

Assignees

Labels

securitySecurity vulnerability or hardening

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions