# HTTP2 'unknownProtocol' cause Denial of Service by resource exhaustion

Node.js http2 servers leak file descriptors and memory when clients trigger the unknownProtocol event and never read the error response, exhausting resources.

- Payout: hidden
- Severity: critical
- Program: Node.js
- Found by: omicronenergy
- Disclosed: 2021-03-15
- CVE: CVE-2021-22883
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/1043360
- Library page: https://bugbountylibrary.com/r/h1%3A1043360
- Tags: area:devices domain:network impact:dos kind:bounty platform:hackerone sev:critical tech:nodejs technique:recon vuln:dos

**Target:** Node.js http2 server (createSecureServer)
**Root cause:** On unknownProtocol, Node writes an error message to the socket and waits for the peer; if the client never reads/closes, the socket and its file descriptor are never released, leaking fds and memory per connection.
**Steps:**
1. Start an http2.createSecureServer on port 50000.
2. Run a loop: `echo "GET / HTTP/1.1 Host: Anything" | openssl s_client -connect 127.0.0.1:50000 &` to open many non-HTTP2 connections.
3. Each connection triggers the unknownProtocol event; client does not read the error response.
4. Monitor `ls -l /proc/{PID}/fd | wc -l` and RSS; observe fds and memory grow unbounded (~7000 fds, 400MB in 30s).
5. Server eventually hits fd limit and cannot accept connections or open files.
**How found:** Discovered incidentally while running Greenbone/OpenVAS scanner (Fast and ultimate config, TCP-SYN ping) against the server port; observed fd/memory growth and traced it to the unknownProtocol handling code in lib/internal/http2/core.js.
**Exploitation:** Attacker opens a large number of TCP connections sending non-HTTP2 data, triggering unknownProtocol, then never reads the error response or closes the socket, causing unbounded fd and memory growth until the process is exhausted.
**Insight:** Scanner traffic that speaks non-HTTP2 to an http2 port can expose error-path resource leaks; check whether error responses to misbehaving peers are written without a timeout/destroy fallback, and test by connecting and never reading the reply.

