n8n versions prior to 2.0.0 implemented a Python 'Code Node' using Pyodide (Python in WebAssembly). Due to improper isolation, the Python environment retained access to the host Node.js runtime. Attackers with workflow-editing permissions can bridge this gap to execute system commands, effectively compromising the entire host and any secrets stored within n8n.
A critical sandbox bypass in the n8n workflow automation platform allows authenticated users to escape the Pyodide environment and execute arbitrary code on the host server. Rated CVSS 9.9, this vulnerability turns a standard workflow tool into a remote command execution terminal.
In the modern DevOps landscape, n8n has carved out a massive niche as the 'fair-code' alternative to Zapier. It is the glue that holds the internet together for thousands of companies, piping data from Stripe to Slack, or from Postgres to AWS. To make this glue stickier, n8n introduced the 'Code Node'—a feature allowing users to inject custom JavaScript or Python logic directly into the pipeline.
Adding Python support to a Node.js application is technically annoying. You usually have two choices: spawn a heavy child process (safe but slow) or do something 'clever' like running Python via WebAssembly (Wasm) inside the V8 engine using Pyodide. n8n chose the latter for its speed and ease of distribution. It seemed like a brilliant idea: run Python in a Wasm sandbox within the main process. What could go wrong?
As it turns out, everything. The assumption was that Wasm provides a perfect, impenetrable jail cell. But in the world of language interoperability, bridges are built to be crossed. CVE-2025-68668 is the story of how that bridge was left unguarded, turning a feature designed for data transformation into a root shell for anyone with a login.
The core issue lies in how Pyodide communicates with its host environment. Pyodide is designed to allow Python code to interact with JavaScript objects. This is a feature, not a bug, when running in a browser—you want your Python script to manipulate the DOM.
However, when running server-side (in Node.js), that same 'feature' becomes a catastrophic liability if not aggressively neutered. In n8n versions prior to 2.0.0, the Python Code Node was instantiated using Pyodide without sufficiently stripping access to the host's JavaScript context. Specifically, the js module in Pyodide acts as a proxy to the host's global scope.
Because n8n runs on Node.js, the global scope contains powerful primitives. If the sandbox doesn't explicitly block access to require, process, or the global object, a Python script can simply import the js module and ask the host Node.js runtime to require('child_process'). It is effectively an inception-style attack: Python asks Wasm to ask JavaScript to ask the OS to run a shell command. The 'sandbox' was merely a suggestion.
Let's look at what this looks like architecturally. The vulnerability stems from the initialization of the Pyodide runtime. While we don't have the exact source diffs in front of us, the mechanism is standard for this class of vulnerability.
The Vulnerable Architecture:
The fix in version 2.0.0 (and the mitigations via environment variables) involves a fundamental architectural shift. Instead of running Python in-process via Wasm/Pyodide where the memory space is shared or bridged, n8n introduced the Task Runner.
The Task Runner moves execution out of the main process entirely. It spawns a separate worker/process that communicates via IPC (Inter-Process Communication). Even if you escape the Python environment in the new architecture, you are trapped in a sterile worker process that theoretically shouldn't have access to the main application's secrets or the ability to spawn arbitrary shells on the host.
Exploiting this requires authenticated access to the n8n UI, specifically the ability to create or edit a workflow. This reduces the risk of random internet scanning, but for an insider threat or a compromised user account, it is trivial.
The Attack Chain:
js bridge.A theoretical payload looks something like this (pseudocode for educational purposes):
import js
# Access the host process
proc = js.process
# Import child_process from the host Node.js environment
child_process = proc.mainModule.require("child_process")
# Execute a command
child_process.exec("cat /etc/passwd > /tmp/pwned")
return {"status": "exploited"}When the workflow executes, the Python code runs, bridges into the Node.js runtime, imports the standard library child_process, and executes the command. The attacker now has the same privileges as the user running the n8n service (often root in Docker containers).
Why is this a CVSS 9.9? It's not just about running calc.exe on the server. n8n is an integration platform. By design, it holds the API keys, database credentials, OAuth tokens, and webhooks for every service a company uses.
If an attacker gains RCE on the n8n host, they can simply dump the environment variables or the database encryption keys. With those, they can decrypt the credentials stored in the n8n database.
Potential Fallout:
This is a 'Game Over' vulnerability for the hosting infrastructure.
The remediation is straightforward but requires action. n8n has effectively deprecated the insecure Pyodide implementation in favor of a native runner architecture.
Immediate Actions:
export N8N_RUNNERS_ENABLED=true
export N8N_NATIVE_PYTHON_RUNNER=trueexport N8N_PYTHON_ENABLED=falseDevelopers using Wasm for sandboxing must learn this lesson: Wasm is safe, but the bindings you expose to it are often not. If you give a prisoner a bridge to the warden's office, don't be surprised when they take the keys.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
n8n n8n | < 2.0.0 | 2.0.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-693 (Protection Mechanism Failure) |
| Attack Vector | Network (Authenticated) |
| CVSS | 9.9 (Critical) |
| Impact | Remote Command Execution (RCE) |
| Vulnerable Component | Python Code Node (Pyodide) |
| Exploit Status | Trivial for Authenticated Users |
Protection Mechanism Failure
Get the latest CVE analysis reports delivered to your inbox.