Fun story, when first developing the web socket protocol we had to deal with kind of nonsense (especially for large commercial routers that did "deep packet inspection"). The solution is that the websocket protocol essentially does this:
1. generate random key
2. send random key (no key exchange, just send the raw bytes)
3. starting sending data, encrypted using the key from (2)
This is because so many routers try to analyze traffic going through them (especially those big commercial ones with "deep packet inspection"), but are really bad at it. As a result providing arbitrary JS running on arbitrary webpages exact bit level control of the data stream would allow people to compromise routers. The same basic issue came up when java applets were first a thing and the result was significant restrictions on networking by applets
Alas the whole point of websockets was to give sites "arbitrary byte" streams so the solution was to make it so that while you had complete logical control of the bytes the actual bytes on the wire are opaque to the JS running in the browser. The goal was not to protect the privacy or confidentiality of the data stream, but to ensure that no existing router software could read the stream and then try to inspect it without knowing that they were parsing arbitrary data, and any new implementation that did try would have hopefully learned about the danger of parsing arbitrary data badly (hint: they did not)
Discovered some bugs in an HTTP library used in upnp software found in Zyxel and some other brands routers. Unfortunately no code execution but did get reliable crashes!
There was some "reference" upnp implementation (I don't remember where it came from, but it was used in real products) where you could do http://<hostname>/getfile/$(echo ../../etc/passwd |base64) ... and get /etc/passwd.
I wasn't expecting this to get much attention because it didn't require very much effort on my part but it looks like someone has smiled upon on my post :) Anyways, this is the kind of thing a simple setup can find, see mongoose's (another embedded web server) fuzzer in oss-fuzz: https://github.com/google/oss-fuzz/blob/master/projects/mong....
1. generate random key
2. send random key (no key exchange, just send the raw bytes)
3. starting sending data, encrypted using the key from (2)
This is because so many routers try to analyze traffic going through them (especially those big commercial ones with "deep packet inspection"), but are really bad at it. As a result providing arbitrary JS running on arbitrary webpages exact bit level control of the data stream would allow people to compromise routers. The same basic issue came up when java applets were first a thing and the result was significant restrictions on networking by applets
Alas the whole point of websockets was to give sites "arbitrary byte" streams so the solution was to make it so that while you had complete logical control of the bytes the actual bytes on the wire are opaque to the JS running in the browser. The goal was not to protect the privacy or confidentiality of the data stream, but to ensure that no existing router software could read the stream and then try to inspect it without knowing that they were parsing arbitrary data, and any new implementation that did try would have hopefully learned about the danger of parsing arbitrary data badly (hint: they did not)
[edit: add extra new lines to the list]