Jun 17, 2026·6 min read·15 visits
Authenticated users can bypass n8n's Python Code Node AST validator, escaping the execution sandbox to access host environment variables and process namespaces.
An authenticated security-bypass vulnerability in n8n allows users with workflow creation or modification privileges to bypass the Python AST security validator. By circumventing AST validation logic, attackers can execute arbitrary statements, access the task executor's root module namespace, and disclose sensitive host environment variables on self-hosted instances.
The n8n workflow automation platform exposes an extensive attack surface through its Code node, which permits administrators and authorized editors to run custom JavaScript or Python scripts. To support Python execution safely, n8n invokes a separate helper runtime called the Python Task Runner. The platform relies on a static analysis protection mechanism to prevent users from executing arbitrary system actions or escaping their local task environment.
This protection mechanism is implemented as an Abstract Syntax Tree (AST) security validator. The validator parses the incoming script structure and prevents execution if it encounters blacklisted nodes, references to dangerous methods, or access to sensitive global fields. This control aims to keep the user script isolated within a limited virtual execution environment.
GHSA-jwm3-qcfw-c5pp describes a critical logic flaw in this validator that allows authenticated workflow creators to evade detection rules. Successful evasion allows the execution of restricted statements that bypass standard execution limits. This escape grants immediate access to the module namespace of the task executor process, risking system-wide credential exposure.
The root cause of this vulnerability lies in the structural incompleteness of the AST verification routines within the n8n Python parsing logic. The security validator utilizes a static checking framework that parses code into an AST and iterates over specific node types to check for prohibited patterns. Specifically, it searches for direct node classifications like ast.Import or standard attribute lookups (ast.Attribute) that match sensitive strings.
However, this implementation fails to recursively and securely analyze nested expressions inside complex AST nodes, such as formatted string literals represented by ast.JoinedStr or dynamic functions like getattr. An f-string containing nested expressions evaluates dynamically during run-time, but its internal variables can easily escape simple static keyword matching systems. By embedding sensitive references within the curly brackets of formatted strings, an attacker forces evaluation at runtime without triggering static parser blocks.
Furthermore, static checks for specific string literals (such as globals or subclasses) are trivial to circumvent using dynamic key retrieval. If the validator permits calls to the built-in getattr() function, an attacker can dynamically piece together forbidden attribute strings through string concatenation. The AST analyzer only sees normal string variables and benign functions, missing the conversion of these inputs into restricted attribute calls.
To analyze this flaw, we can observe the difference between standard static checks and the dynamic bypass paths. In a vulnerable validator implementation, the checking function often matches attribute strings directly against a set of known forbidden attributes.
# Vulnerable logic representation
def validate_node(node):
if isinstance(node, ast.Attribute):
if node.attr in ['__globals__', '__subclasses__', '__builtins__']:
raise SecurityError("Forbidden attribute accessed")The code above fails to catch attempts where the restricted properties are retrieved indirectly. The following representation demonstrates how dynamic access circumvents the static filter entirely.
# Dynamic evasion pattern bypasses ast.Attribute check
class_ref = _get_data.__class__
# getattr accepts a constructed string which is not flagged as ast.Attribute
globals_dict = getattr(class_ref, '__glo' + 'bals__')The fix introduced in n8n enforces robust AST validation paths that intercept dynamic attribute resolution and prohibit hazardous functions such as getattr when executed under the sandbox context. Additionally, nested structures in ast.JoinedStr are subject to strict recursive checking to ensure no execution boundaries are bypassed.
Exploitation of this vulnerability requires the attacker to possess authenticated access to an n8n instance with permissions to create or modify workflows. This requirement is standard for users with Owner or Member privileges on self-hosted deployments. The attack is entirely remote and does not require user interaction from other operators on the system.
The attacker begins by creating a workflow and inserting a Code node configured to execute Python. The attacker then writes a script designed to reconstruct forbidden attributes at runtime. The script leverages built-in objects like _get_data or _context which are automatically injected into the task context by n8n.
# Conceptual payload extracting system environment
def exploit():
g_attr = "{0}{1}{0}".format("__", "globals")
globals_dict = getattr(_get_data, g_attr)
sys_module = globals_dict["sys"]
os_module = sys_module.modules["os"]
return [{"leak": dict(os_module.environ)}]
result = exploit()The payload executes string manipulation to yield the target namespace. Once the attacker obtains the dictionary of globals, they extract the sys module, access the system modules cache, and retrieve the original os module. Finally, the payload extracts host environment variables and outputs them directly as a workflow result, allowing simple extraction via the n8n execution interface.
The impact of this security bypass is classified under unauthorized information disclosure. By gaining access to the root process namespace, an attacker defeats the execution isolation rules designed to restrict the task runner process. On self-hosted environments where environment access is configured, this escape allows the disclosure of sensitive host parameters.
In environments where the configuration flag N8N_BLOCK_RUNNER_ENV_ACCESS is set to true, the wrapper process executes logic to obscure the active environment variables. However, because the AST bypass provides direct access to the parent namespace and raw system module arrays, the attacker can traverse memory structures and recover sensitive configuration items. This bypass negates the protection provided by the isolation flag.
The disclosed information can contain database credentials, server API keys, connection strings, and third-party configuration details used by n8n. These secrets can then be used to pivot deeper into internal network environments. The CVSS score of 5.1 represents a medium severity impact due to the prerequisite of low-privilege authentication.
Remediating this vulnerability requires immediate updates to the underlying n8n deployment. Systems running versions prior to 2.25.7 must be upgraded directly to 2.25.7 or later. Deployments utilizing the 2.26.x branch must be updated to version 2.26.2 or subsequent releases to ensure all parser gaps are fully patched.
When direct upgrades are delayed due to operational requirements, administrators should apply environment controls to mitigate risk. Setting the environment variable NODES_EXCLUDE=["n8n-nodes-base.code"] disables the Code node globally, effectively removing the execution vector. Administrators can also restrict workflow creation privileges strictly to trusted security roles.
Finally, organizations should establish robust detection and log-hunting routines. Analyze workflow execution logs and inspect the n8n database for code structures containing obfuscated attribute lookups or unusual dynamic string functions. Monitor system executions to ensure the Python runner process does not spawn unexpected shell processes or engage in outbound external network traffic.
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
n8n n8n-io | < 2.25.7 | 2.25.7 |
n8n n8n-io | >= 2.26.0, < 2.26.2 | 2.26.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-184 / CWE-265 |
| Attack Vector | Network (Low Privileges) |
| CVSS Score | 5.1 (Medium) |
| EPSS Score | N/A (No CVE Assigned) |
| Impact | Information Disclosure / Sandbox Escape |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
The program checks input values against an incomplete list of disallowed values, allowing attackers to construct alternative representations that bypass filters.
CVE-2026-46696 identifies a critical sandbox bypass vulnerability in the October CMS platform that affects the Twig template security policy when safe mode is enabled. An authenticated backend user with permissions to modify CMS markup templates can chain unrestricted session store method access with Eloquent database query forwarding omissions. This chain allows the attacker to execute arbitrary raw SQL queries to read system secrets and subsequently write those secrets directly to the active session payload, achieving unauthorized administrative privilege escalation.
A security vulnerability in October Content Management System (CMS) involves the deserialization of untrusted data (CWE-502) within the backend SessionMaker trait. Prior to the patched versions, October CMS stored widget session states as base64-encoded serialized PHP objects. When loading these states, the application consumed them using unserialize() without enforcing class restrictions (allowed_classes). In configurations where cms.safe_mode is enabled to sandbox users with markup editor privileges, an attacker can exploit this behavior to instantiate arbitrary PHP classes and execute arbitrary code via accessible gadget chains.
A security vulnerability in ZITADEL's backend implementation of the OAuth2 Token Exchange endpoint allows authenticated clients to perform scope escalation and cross-client audience bypass. Prior to version 4.15.3, the Token Exchange flow lacked crucial validation logic, enabling low-privilege tokens to be exchanged for high-privilege tokens or tokens valid within other client applications, violating the OAuth2 delegation model.
CVE-2026-76081 is a logical vulnerability in ZITADEL's role cascading logic where updating a Project Grant to drop multiple adjacent roles simultaneously fails to clean up associated User Grants due to an in-place slice mutation error in Go.
This report provides a technical analysis of GHSA-2XMM-M4WV-3FJH, an incomplete scheme validation vulnerability in the image resizing utility of October CMS. By exploiting this flaw, authenticated or privileged users can pass dangerous URI schemes to trigger deserialization of untrusted metadata.
An authentication bypass vulnerability in ESPHome Device Builder Dashboard allows unauthenticated remote attackers to gain administrative access. The flaw is caused by a backward compatibility break during an environment variable rename that silently disables dashboard authentication upon upgrade.