vibesec
Version:
Security scanner for AI-generated code - detects vulnerabilities in vibe-coded projects
262 lines (236 loc) • 7.96 kB
YAML
# Prototype Pollution Security Rules
# Detects JavaScript/Node.js prototype pollution vulnerabilities
rules:
- id: unsafe-object-merge
name: Unsafe Object Merge
description: Merging user input into objects without protection can pollute prototypes
severity: high
category: injection
languages:
- javascript
- typescript
enabled: true
patterns:
- regex: "Object\\.assign\\s*\\([^,)]*,\\s*req\\.(body|query|params)"
flags: gi
- regex: "\\{\\s*\\.\\.\\.req\\.(body|query|params)"
flags: gi
- regex: "\\.extend\\s*\\([^,)]*,\\s*req\\.(body|query|params)"
flags: gi
- regex: "merge\\s*\\([^,)]*,\\s*req\\.(body|query|params)(?!.*\\{[^}]*prototype\\s*:\\s*false)"
flags: gi
fix:
template: |
Validate and sanitize object keys before merging user input.
Before:
const config = Object.assign({}, req.body);
After:
// Option 1: Use Object.create(null) for objects without prototype
const config = Object.assign(Object.create(null), req.body);
// Option 2: Filter dangerous keys
const safeMerge = (target, source) => {
const dangerousKeys = ['__proto__', 'constructor', 'prototype'];
for (const key in source) {
if (!dangerousKeys.includes(key) && source.hasOwnProperty(key)) {
target[key] = source[key];
}
}
return target;
};
const config = safeMerge({}, req.body);
// Option 3: Use libraries with prototype pollution protection
const _ = require('lodash');
const config = _.merge({}, req.body); // lodash v4.17.21+ is safe
references:
- https://owasp.org/www-community/vulnerabilities/Prototype_Pollution
- https://portswigger.net/web-security/prototype-pollution
metadata:
cwe: CWE-1321
owasp: "A03:2021"
tags:
- prototype-pollution
- javascript
- injection
- id: dangerous-recursive-merge
name: Dangerous Recursive Object Merge
description: Recursive merge functions without prototype pollution protection
severity: high
category: injection
languages:
- javascript
- typescript
enabled: true
patterns:
- regex: "function\\s+merge\\s*\\([^)]*\\)\\s*\\{[^}]*for\\s*\\([^)]*in\\s+[^)]*\\)(?!.*hasOwnProperty)"
flags: gi
- regex: "const\\s+merge\\s*=\\s*\\([^)]*\\)\\s*=>\\s*\\{[^}]*for\\s*\\([^)]*in\\s+[^)]*\\)(?!.*hasOwnProperty)"
flags: gi
fix:
template: |
Add prototype pollution checks to recursive merge functions.
Before:
function merge(target, source) {
for (const key in source) {
if (typeof source[key] === 'object') {
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
After:
function merge(target, source) {
const dangerousKeys = ['__proto__', 'constructor', 'prototype'];
for (const key in source) {
if (!source.hasOwnProperty(key) || dangerousKeys.includes(key)) {
continue;
}
if (typeof source[key] === 'object' && source[key] !== null) {
target[key] = target[key] || {};
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
references:
- https://owasp.org/www-community/vulnerabilities/Prototype_Pollution
- https://github.com/HoLyVieR/prototype-pollution-nsec18
metadata:
cwe: CWE-1321
owasp: "A03:2021"
tags:
- prototype-pollution
- recursive-merge
- id: lodash-vulnerable-version
name: Vulnerable Lodash Version
description: Using lodash version vulnerable to prototype pollution
severity: critical
category: dependencies
languages:
- javascript
- typescript
enabled: true
patterns:
- regex: "\"lodash\"\\s*:\\s*\"[^\"]*[0-3]\\.|\"lodash\"\\s*:\\s*\"4\\.([0-9]|1[0-6])\\."
flags: gi
fix:
template: |
Update lodash to version 4.17.21 or later.
Before:
"lodash": "^4.17.15"
After:
"lodash": "^4.17.21"
Run: npm update lodash
references:
- https://github.com/lodash/lodash/pull/5065
- https://snyk.io/vuln/SNYK-JS-LODASH-1018905
metadata:
cwe: CWE-1321
owasp: "A06:2021"
tags:
- prototype-pollution
- lodash
- dependencies
- id: direct-proto-assignment
name: Direct __proto__ Assignment
description: Directly assigning to __proto__ property
severity: medium
category: injection
languages:
- javascript
- typescript
enabled: true
patterns:
- regex: "\\.__proto__\\s*=|\\[\\s*[\"']__proto__[\"']\\s*\\]\\s*="
flags: gi
- regex: "Object\\.setPrototypeOf\\s*\\([^,)]*,\\s*req\\.(body|query|params)"
flags: gi
fix:
template: |
Avoid direct prototype manipulation. Use Object.create() instead.
Before:
obj.__proto__ = userInput;
After:
// Don't do this. If you need to set prototype:
const obj = Object.create(safePrototype);
references:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
metadata:
cwe: CWE-1321
owasp: "A03:2021"
tags:
- prototype-pollution
- proto
- id: unsafe-json-parse
name: Unsafe JSON.parse with Reviver
description: JSON.parse with user-controlled reviver function
severity: medium
category: injection
languages:
- javascript
- typescript
enabled: true
patterns:
- regex: "JSON\\.parse\\s*\\([^,)]*,\\s*req\\.(body|query|params)"
flags: gi
- regex: "JSON\\.parse\\s*\\([^,)]*,\\s*function\\s*\\([^)]*\\)\\s*\\{.*__proto__"
flags: gi
fix:
template: |
Avoid user-controlled reviver functions in JSON.parse.
Before:
const data = JSON.parse(str, req.body.reviver);
After:
// Use JSON.parse without reviver
const data = JSON.parse(str);
// Or use a safe, predefined reviver
const safeReviver = (key, value) => {
if (key === '__proto__' || key === 'constructor') {
return undefined;
}
return value;
};
const data = JSON.parse(str, safeReviver);
references:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
metadata:
cwe: CWE-1321
owasp: "A03:2021"
tags:
- prototype-pollution
- json-parse
- id: unsafe-property-access
name: Unsafe Dynamic Property Access
description: Accessing object properties with unsanitized user input
severity: medium
category: injection
languages:
- javascript
- typescript
enabled: true
patterns:
- regex: "\\[\\s*req\\.(body|query|params)\\.[^\\]]+\\]\\s*="
flags: gi
- regex: "config\\[\\s*userInput\\s*\\]\\s*="
flags: gi
fix:
template: |
Validate property names before dynamic access.
Before:
config[req.query.key] = req.query.value;
After:
const allowedKeys = ['theme', 'language', 'timezone'];
const key = req.query.key;
if (allowedKeys.includes(key) && key !== '__proto__' &&
key !== 'constructor' && key !== 'prototype') {
config[key] = req.query.value;
}
references:
- https://owasp.org/www-community/vulnerabilities/Prototype_Pollution
metadata:
cwe: CWE-1321
owasp: "A03:2021"
tags:
- prototype-pollution
- property-access