A recent vulnerability called 'React2Shell' (CVE-2025–55182) has been all over the internet. Even the Government of Canada posted about it. That's how you know it's bad. This vulnerability is perhaps the worst vulnerability since Log4j 4 years ago. It's also a very similar type of vulnerability. It's remote code execution from improperly deserializing.

There have been a lot of posts going on discussing this vulnerability, but I don't think they adequately discussed it. Because React2Shell tells us a lot about the problems of JavaScript. Because JavaScript runs everywhere, I wrote about it in my post The Rise And Rise Of JavaScript.

The developers behind JavaScript tools were so preoccupied with whether or not they could run JavaScript everywhere, they didn't stop to ask themselves if they should. I think React2Shell should be a wake-up call. And just like how C is a problem due to memory bugs, I think JavaScript should be considered a problem due to duck typing bugs.

So how does the vulnerability work? Well, React has something called the Flight protocol. This allows the client to send JSON-like data and for this data to be deserialized on the server. Normally to do this you'd use something like JSON.parse(). This works, however the object that's created is just a map or list. If you wanted to call a function with this map or list you'd have to somehow implement your own custom logic.

Geez, wouldn't it be so much easier if we could take the data sent by the user and create an arbitrary JavaScript object? Red alarms should be sounding right now. This is an absolutely terrible security practice. But JavaScript allows it because it is interpreted and so the React Team decided to do it. How much do the developers at (at the time) Facebook get paid again? If you ever need an example of how pay does not correlate with competency it would be this.

Although, in all fairness, this serialization process worked quite well. But eventually someone found a problem with it. And that problem was the then keyword. If you give a JS object a then property and then you await it that then gets executed. Hallelujah, you now have remote code execution.

And this was a pretty big security issue. It was announced on December 3rd. On December 5th it was already being exploited. And this CVE has a severity of 10 meaning it's very bad.

Apparently Cloudflare tried to block the exploitation of this vulnerability fairly soon which is good. Makes me feel better about my decision to not give up cloudflare. However the fix took down Cloudflare.

This is why everyone hates JavaScript developers

Although, personally, I didn't notice any outage. So either they fixed it quickly or it did not affect me.

So what can we learn from this? First stop running React. Or at least React Server. I mean, sure, they patched this one, but what if someone finds another way to execute code using the Flight protocol? This is not the way JavaScript was designed to be used. You can't just create untrusted JavaScript objects. That's a bad idea.

Even if you made sure there are no exploits, what if the next version of ECMAScript has some new feature in it that makes it exploitable again? The only safe way to deserialize data is to use one of the built-in JSON deserializers.

And, honestly, I'm a little weary of any back-end system written in JavaScript now. You know why React wanted to make this completely moronic design decision, right? Because they didn't want the developer to have to learn another language. They wanted it to be extremely noob friendly. Well, turns out that they made it so noob friendly that it had an RCE vulnerability.

And also this vulnerability would only be possible on duck-typed languages like JavaScript. Because only in these languages can strings be treated as code. I didn't really consider this dangerous before, but now I'm starting to reconsider. If an attacker managed to convert a string to code in React Server could there be similar hidden RCEs in other JavaScript frameworks? Could there be one in Node? In Bun? Possibly. Especially if you added support for some similar deserialization system manually.

I now believe JavaScript and other duck-typed languages should not be used for backend due to vulnerabilities like this. Just learn another language, it's not going to kill you. Personally I'm using PocketBase and Go and it seems to work pretty well.

One last thing. Stop running your server as root. I keep on seeing it over and over again. Like even in the PocketBase Systemd instructions:

PocketBase Systemd instructions showing commands to run as root

If you run your server as root and your server is compromised then your entire machine is compromised. It means they can install a crypto miner or some sort of botnet program or a back door or some other junk. And then when they do that your only recourse is to wipe the whole thing and start again.

Now, it's very unlikely that your server will be compromised in this way which I guess is why people do it. But creating a dedicated user to run your server is extremely easy. Just ask an LLM how to do it.

I don't think this React2Shell vulnerability will change the world in any meaningful way. People are still going to use React Server, and people are still going to use JavaScript on the server. And maybe for existing projects this could make sense, rewriting everything is a pain. And if they don't deserialize user input it might not matter. But for new projects, I don't think JavaScript on the server is a good choice. There are so many other languages and frameworks out there.