On December 19, 2025, a critical vulnerability was published for n8n, a popular open-source workflow automation platform. Assigned CVE-2025–68613 with a severity score of 9.9 (Critical), this vulnerability allows authenticated users to bypass sandbox restrictions and execute arbitrary system commands.

In this post, we are going to dissect the architecture of n8n, understand how the JavaScript sandbox escape works, and look at how to detect this activity in the wild.

What is n8n?

Before diving into the exploit, we need to understand the target. n8n is designed to visually connect applications and services. You build "workflows" composed of nodes, where each node performs an action — like making an API request, processing JSON, or sending an email.

Under the hood, n8n is built on Node.js. Crucially, it features an Expression Evaluation System. This allows users to use dynamic expressions wrapped in double curly braces {{ }} to reference data from previous nodes or perform simple logic.

For example, a user might write:

This expression is evaluated as JavaScript code during execution. This feature is the core of the vulnerability.

The Vulnerability: Sandbox Escape

The vulnerability resides in versions 0.211.0 through 1.120.3. While n8n intends for these expressions to run in a restricted sandbox, the isolation was incomplete.

The core flaw is an Expression Injection vulnerability. Specifically, the evaluator did not properly isolate the execution context from the Node.js global environment. An attacker can use specific JavaScript properties to "climb out" of the sandbox and access the host system.

The Payload

Let's look at the Proof of Concept (PoC) payload provided by wioui:

At first glance, this is a standard Immediately Invoked Function Expression (IIFE). But the magic happens inside the function. Let's break down the escalation chain:

  • this: In the context of the sandbox, this refers to the global object. Because the isolation is flawed, it gives us a foothold into the Node.js execution context.
  • process: This is a global Node.js object that provides information about the current Node.js process.
  • mainModule: This references the root module of the application. This is the critical breach—we have now bypassed the user-expression sandbox and are touching the application's core internals.
  • require('child_process'): Typically, require is forbidden in user expressions. However, by accessing it through mainModule, we can load the child_process module, which allows us to spawn new processes on the OS.
  • execSync('id'): We execute the system command id.

The Escalation Chain:

Sandbox -> Node.js Global (this) -> Module System (mainModule) -> RCE (child_process)

reproducing the Exploit

To demonstrate this, we don't need complex tools — just a browser and a vulnerable instance of n8n.

Step 1: The Setup

After logging into the n8n dashboard, we create a new workflow "from scratch."

Step 2: The Trigger

We add a Manual Trigger node. This simply allows us to run the workflow with a click.

Step 3: The Injection

We connect a generic "Edit Fields (Set)" node to our trigger. This node allows us to define variables.

In the value field, instead of a static string, we change the input type to "Expression" and paste our payload:

Step 4: Execution

When we click "Execute Step," the n8n engine evaluates the expression. Instead of returning a string, it executes the JavaScript, escapes the sandbox, runs id on the server, and returns the output.

The output in the preview window confirms we are running code as the root (or service) user.

Detection and Defense

The vulnerability was patched in versions 1.120.4, 1.121.1, and 1.122.0. Updating is the only sure fix. However, for Blue Teams, detecting attempts is crucial.

The Logging Problem

By default, n8n logs are often insufficient for detecting payload specifics. The best approach is to inspect the HTTP Request Body at your reverse proxy (e.g., Nginx) or WAF.

Sigma Rule

A Sigma rule to detect this behavior focuses on the specific JavaScript keywords used in the escape chain appearing in POST requests to /rest/workflows.

Note: This detection looks for the specific method of accessing child_process. Attackers might obfuscate this, so monitoring process creation events (e.g., node spawning sh, bash, or powershell) on the n8n host is also mandatory.

Conclusion

CVE-2025–68613 serves as a stark reminder of the dangers of evaluating user input as code. Even with sandboxing, JavaScript's dynamic nature makes true isolation difficult.

The vulnerability isn't just about improper input validation; it's about fundamentally flawed trust boundaries between user-provided code and the application runtime environment.

For those running n8n, patch immediately. For security researchers, this is a classic example of how "feature-rich" expression engines can turn into critical vulnerabilities.