Critical Flaw in isolated-vm Can Lead to Sandbox Escape, RCE Threat

Developers for years have been using vm2, an open-source Node.js library, to run untrusted JavaScript inside a secure and isolated sandbox environment. It uses Node.js’s built-in modules and JavaScript Proxies and lets developers whitelist particular built-in Node modules or limit what the script can access.

During that time, vm2 has been the default for safely running untrusted JavaScript, which Cris Staicu, senior security researcher for Endor Labs, calls “one of the hardest problems in the Node.js ecosystem.”

However, over the years, there have been some two dozen instances of code breaking out of the sandbox, including one Endor Labs documented earlier this year. The problem is that vm2 is used to build a security boundary inside a single V8 execution environment using proxies and prototype scrubbing, and untrusted code shares some of the same elements, according to Staicu.

Another method, isolated-vm, uses stronger techniques, a key one being that each sandbox given its own V8 Isolate, an independent and self-contained instance of the V8 JavaScript engine with separate built-ins and no shared object graph with the host.

“This is the same primitive Chrome uses to separate tabs,” Staicu wrote in a new report this week. “Guest code gets no require, no host globals, and no references to host objects unless the embedder explicitly hands them over. That is a real, OS- and VM-enforced boundary, and it is why isolated-vm is trusted to run genuinely adversarial code.”

Finding a Flaw

That said, Endor Labs researchers discovered a critical flaw in isolated-vm that allows code running inside the sandbox to corrupt memory in the host process application. Tracked by Endor Labs as GHSA-864f-rcv7-6rh4 and with a CVE assignment pending, Staicu wrote that they didn’t break the V8 Isolate sandbox; instead, “we broke the code that carries data into it.”

“A type confusion in ExternalCopy’s handling of the transferList option lets code running inside the sandbox corrupt memory in the host process,” he wrote. “Starting from nothing but a single ivm.Reference, the standard way hosts hand a sandbox any capability at all, we escalated the bug from a controlled-address crash all the way to hijacking the host’s control flow, demonstrating a full guest-to-host sandbox escape.”

Such an escape can allow the attacker to crash the host application, which can lead to a denial of service triggered by a guest. More dangerously, it can mean the hacker hijacking the host’s control flow, which Staicu wrote opens a path to remote code execution (RCE) outside of the sandbox and in the host. The maintainer fixed it with patches in versions 7.0.1 and 6.2.0.

Beware the TOCTOU

In JavaScript environments using isolated-vm, ExternalCopy is used to safely serialize data out of one isolate heap and deserialize it into another. When it serializes an object with a transferList, the constructor iterates over the list twice, validating every element and registering it with the serializer in the first step, while transferring each element in the second step without revalidating.

This leads to a time-of-check to time-of-use (TOCTOU) gap, which occurs when a program checks a system state – in this case, the validated transferList in the first step – and then uses it moments later, assuming the state remains the same. In this case, the transfer of each element in the second step doesn’t revalidate each element.

“The attacker registers a stateful getter that hands a genuine ArrayBuffer to the validating walk and something else to the unchecked walk,” Staicu wrote. “transferList is accepted only by the ExternalCopy constructor, which appears to be accessible only on the host side. But the guest does not need the entire ivm module; it only needs a single ivm.Reference: the ordinary mechanism a host uses to expose anything to a sandbox. The externalCopy transfer option pulls the ExternalCopy constructor across the boundary as a live, callable class.”

From there, the guest – the hacker – builds a malicious transferList, which triggers the malicious code from inside the isolate.

Vulnerability in the C++ Glue Code

He reiterated that isolated-vm is a stronger sandbox than vm2 and that the flaw is not related to the V8 Isolate it’s based on. The vulnerability is in the C++ glue code that serializes values across the boundary but is written in a memory-unsafe language.

A worry is that isolated-vm is a popular tool – with more than a million downloads a week – particularly when running AI-related projects, where executing model- or user-generated code safely is a core requirement in the age of AI agents and automation platforms.

That list includes n8n, a workflow-automation platform that has garnered 200,000 GitHub stars, the Mastra agentic AI framework (27,000 stars), platform maker Sim.ai (29,000 stars), and Activepieces, an open source AI-first workflow automation platform (23,000 stars).

The project’s documentation indicates that isolated-vm also is the sandbox on record for such production systems as its own Screeps, a massively multiplayer online (MMO) environment that runs player-supplied code, edge compute system Fly.io, Algolia’s custom crawler, and TripAdvisor, for server-side rendering.

Apply the Fix

Developers need to migrate to isolated-vm 7.0.1 or 6.2.0 on the 6.x line and closely scrutinize their sandboxes, both what’s in them and how they work.

“That gap between ‘the primitive is sound’ and ‘the system is safe’ is where modern sandbox escapes increasingly live, and it is exactly the gap our research has been mapping,” Staicu wrote. “As AI agents and automation platforms make untrusted-code execution a mainstream requirement, the binding layer around your sandbox deserves first-class security attention.”

Read More

Scroll to Top