highJul 22, 2026

n8n Edit Fields (Set) Node Prototype Pollution Denial of Service

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

An authenticated n8n user can name a workflow field '__proto__.hasOwnProperty' in the Edit Fields node, corrupting a shared global in the main Node.js process and crashing authentication for every…

Packagen8n
Ecosystemnpm
Affected< 1.123.67
Fixed in1.123.67

The problem

The Edit Fields (Set) node in n8n accepted arbitrary dot-notation field names and wrote them to output objects using an unrestricted path-setter (equivalent to lodash _.set). No key-segment validation was applied.

Because __proto__ is a valid path segment in such setters, a field named __proto__.hasOwnProperty (or any other inherited built-in) writes directly onto Object.prototype. That global mutation persists for the entire lifetime of the Node.js process. The poisoned property sat on the request-authentication code path, causing every subsequent authenticated request to throw, producing an instance-wide denial of service until the process was restarted.

Proof of concept

A working proof-of-concept for this issue in n8n, with the exact payload below.

javascript
// In the Edit Fields (Set) node, add a new field with:
// Field Name:  __proto__.hasOwnProperty
// Field Value: 1   (any truthy value)
//
// When the workflow runs, the Set node internally calls something like:
//   _.set(outputItem, '__proto__.hasOwnProperty', 1)
// This writes onto Object.prototype:
//   Object.prototype.hasOwnProperty = 1
// All subsequent calls to obj.hasOwnProperty(...) in the process throw
// a TypeError instead of returning a boolean, breaking the auth path.

// Equivalent JS that demonstrates the primitive:
const _ = require('lodash'); // or n8n's own dot-notation setter
const obj = {};
_.set(obj, '__proto__.hasOwnProperty', 1);
console.log(({}).hasOwnProperty('x')); // TypeError: hasOwnProperty is not a function

The root cause is CWE-1321: the dot-notation path-setter split the field name on . and blindly walked the prototype chain, so the segment __proto__ resolved to Object.prototype rather than a plain object key. The patch (commit f69dfc6) added a denylist or safe-key guard that rejects any path segment equal to __proto__, constructor, or prototype before the setter runs, preventing traversal up the prototype chain.

The gadget that turned this into a DoS was n8n's authentication middleware reading obj.hasOwnProperty as a function on every request. Once Object.prototype.hasOwnProperty was overwritten with a non-function scalar, that call threw a TypeError instance-wide, not just in the offending workflow.

The fix

Upgrade to n8n 1.123.67, 2.31.5, or 2.32.1. The patch blocks any dot-notation path segment that matches __proto__, constructor, or prototype in the Edit Fields (Set) node before the path-setter is invoked. If an immediate upgrade is not possible: restrict workflow creation and execution to fully trusted users, and monitor for unexpected process-wide HTTP 500 errors, restarting the process promptly if they occur.

Reported by csuermann (n8n Security Team).

References: [1][2][3][4][5][6]

Related research