irc://blog.northstartproductionstudio.com/#shipped ← back to log

No telemetry. No tracking. No cookies. No accounts.

* ~ghost has joined #shipped

What a 10.0 CVSS React bug teaches agent builders about trusting structured input

· ~ghost

This isn't a post about something we built. It's a note on a bug class we think everyone building on top of LLM tool-calling should have on their radar, because the same shape of mistake is one implicit type coercion away from showing up in a different runtime.

CVE-2025-55182 — publicly nicknamed React2Shell — is a critical, unauthenticated, single-request remote code execution vulnerability in React Server Components, disclosed at Black Hat 2026. Cloudflare alone recorded over half a billion exploit attempts against it in its first week; across vendors, threat-intel reporting put the total past a billion attempts industry-wide in that same window. It's one of the more significant JavaScript-ecosystem vulnerabilities in recent memory, and the mechanism behind it is worth understanding even if you never touch React.

the mechanism, compressed

React Server Components ship a serialization protocol (informally called "Flight") for sending structured data between server and client — JSON, but extended with its own syntax for references, promises, and richer types JSON doesn't natively carry. An object sent through it can carry a reference to a function the framework itself implements — including, critically, the Function constructor, which dynamically builds a new function from a string of code.

JavaScript's own runtime does something relevant here that has nothing to do with React specifically: when it needs to coerce a non-string value into a string (string concatenation, comparison, a lot of ordinary operations), it looks for a toString or valueOf method on that value and calls it implicitly. If an attacker controls the object and can plant a reference to Function's constructor where that implicit call lands, the runtime ends up calling attacker-influenced code without anyone writing an explicit eval anywhere in the codebase. The researcher's own exploit chain used exactly this: a "thenable" object (something with a .then method, which JavaScript's await will call automatically) planted where React expected its own internal promise-resolution logic — letting a single crafted request from an unauthenticated client end in code execution on the server.

why this isn't a "just patch React" story

The specific bug is fixed. The pattern it exploited isn't specific to React. Any system that (a) accepts structured data from an untrusted source, and (b) has a runtime that will implicitly invoke methods on that data during ordinary processing — type coercion, serialization, comparison — has the same shape of exposure, scaled to whatever that runtime's implicit-call surface actually is.

Which is where this connects to agentic tooling. A tool-calling framework routinely hands an LLM's output — a JSON blob describing which tool to call and with what arguments — to code that parses it, and in some architectures, to code that partially executes based on its shape (dynamic dispatch keyed off a field in that JSON, templated prompts built by string-interpolating fields from it, or worse, a runtime that evaluates part of it directly). The specific "attacker plants a thenable with a poisoned .then" trick is JavaScript-specific. The general lesson isn't: structured, machine-generated input is not inherently safer than a raw string just because it's typed and shaped like something your code expects. An LLM's output is attacker-influenced the moment any part of its context comes from outside your own trust boundary — which, for most agent deployments, is most of the time.

what we're not claiming

We don't ship a Next.js or React Server Components product, and this isn't a "we fixed this" post — there's nothing of ours this CVE touches directly. What we do build is prompt-injection and agentic-behavior detection (Agent Guardrails) and an egress firewall for agent tool calls (Iron-Thread, part of Leviathan Control), and the honest reason this is worth writing down now, not after it becomes relevant: if either of those ever grows a validator for structured tool-call/MCP-style JSON specifically, "never let attacker-influenced structured data implicitly pick up executable behavior via the runtime's own coercion rules" is exactly the kind of threat-model entry that needs to exist before that work starts, sourced to a real incident, not reconstructed from memory after the fact.

For now: if you're building or evaluating an agent framework, the concrete question worth asking is narrower than "do you validate tool-call JSON" — it's whether anything in your parsing path lets a field's value influence what code runs, not just what data gets read. That's the distinction React2Shell actually turned on.


Leviathan Control is open about its scope, not open source (yet) — reach out via northstartproductionstudio.com if you want to look at the code before you rely on it.

#security #javascript #agents #llm

* ~ghost has left #shipped