[ previously reported on HackerOne and judged to be low enough severity to open here ]
Summary: NodeJS's HTTP/2 client serialises each HTTP/2 request in a separate TLS record, exposing information to attackers performing traffic analysis.
Description: One of the design goals of HTTP/2 is to make traffic analysis more difficult, by multiplexing multiple requests on the same connection. However, NodeJS's HTTP/2 client side appears to send each request (HEADERS frame) in a separate TLS record, which makes this delineation -- and importantly, the sizes of the requests) -- apparent to observers on the network.
Steps To Reproduce:
Impact: makes the lives of traffic analysis attackers easier. While NodeJS isn't a browser, it's used by a broad variety of applications, and I'd be a bit surprised if someone somewhere wasn't using it as a client in a situation where this wasn't a risk.
In particular, this information could be used to observe the differences in the sizes of requests, thereby allowing an attacker to "fingerprint" the activity more accurately.
This information could also be used by an attacker to more effectively perform attacks like CRIME, BEAST, etc.
Supporting Material/References:
See attached tarball containing a demo client and server - nodetest.zip
Annotated screenshot from Wireshark:

Ping @jasnell
Thank you @mnot.
@nodejs/crypto @indutny ... The underlying challenge here is that the tls impl does not adequately coalesce writes on the same tls socket or provide a way to easily do so. At the http2 layer, these are just writes to the tls.Socket.
This is weird, #27861 solved this exact problem... This seems like a regression.
the tls impl does not adequately coalesce writes on the same tls socket or provide a way to easily do so
TLS sockets should support cork() / uncork() to force grouping buffers into a single segment :thinking:
Interesting. Worth looking at again. It's possible that this ended up being resolved since the issue was reported. Likely worth retesting and/or backporting if it hasn't been. (I don't know offhand if it has or hasn't)
I did a quick test with the supplied code and was unable to reproduce the problem with the latest release, everything appears as one segment:

So yes, it seems to be as you said. The PR landed at v12 and got backported to v10.
Great!
Most helpful comment
I did a quick test with the supplied code and was unable to reproduce the problem with the latest release, everything appears as one segment:
So yes, it seems to be as you said. The PR landed at v12 and got backported to v10.