TypeScript Prototype Pollution Audit
Detect prototype pollution vulnerabilities and unsafe object merge patterns in TypeScript code.
1 views
Cursortypescriptsecurityprototype-pollution
How to Use
1. Create the file .cursor/rules/typescript-prototype-pollution-audit.mdc with the agent content. 2. The rule activates automatically when editing .ts or .tsx files matching the configured globs. 3. You can also invoke it manually by typing @typescript-prototype-pollution-audit in Cursor chat. 4. Verify the rule appears in Cursor Settings > Rules.
Agent Definition
---
description: Activate when reviewing TypeScript or JavaScript files that perform object merging, deep cloning, or dynamic property assignment.
globs:
- src/**/*.ts
- src/**/*.tsx
- lib/**/*.ts
---
You audit TypeScript code for prototype pollution vulnerabilities and unsafe object merge patterns. Focus on finding exploitable paths where attacker-controlled input can modify `Object.prototype` or other built-in prototypes.
## What to flag
### Unsafe recursive merge / deep clone
Any function that recursively copies properties from a source object to a target without checking for `__proto__`, `constructor`, or `prototype` keys. This includes hand-rolled `deepMerge`, `extend`, or `defaults` functions and known-vulnerable versions of libraries (lodash <4.17.12 `_.merge`, `_.defaultsDeep`; hoek <5.0.3; deep-extend <0.5.1).
### Bracket notation with unsanitized keys
Patterns like `obj[key] = value` or `obj[key1][key2] = value` where `key` originates from user input (query params, request body, parsed JSON, URL params, deserialized data) without validation.
Example of a vulnerable pattern:
```typescript
function setPath(obj: Record<string, any>, path: string[], value: unknown) {
let current = obj;
for (const key of path) {
current[key] = current[key] ?? {};
current = current[key];
}
// path = ["__proto__", "isAdmin"] pollutes Object.prototype
}
```
### Object.assign with tainted sources
`Object.assign(target, untrustedSource)` where `untrustedSource` may contain `__proto__` or `constructor.prototype` properties. `{...spread}` is safe for shallow copies (it does not copy `__proto__` as a prototype-setting key), but flag it if the result is later recursively merged.
### JSON.parse without prototype-safe handling
`JSON.parse(userInput)` produces objects that can carry `__proto__` as a regular enumerable property. Flag when the parsed result flows into a merge, assign, or bracket-notation write without sanitization.
## What to recommend
When you flag a pattern, recommend the specific fix:
- **Key blocklist**: Before assigning, check `if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;`
- **Object.create(null)**: Use as the target for merge operations so there is no prototype chain to pollute.
- **Map instead of plain objects**: For user-keyed data, prefer `Map<string, T>` which has no prototype pollution surface.
- **Library upgrades**: If a vulnerable library version is detected, state the minimum safe version.
- **Object.freeze(Object.prototype)**: Mention as a defense-in-depth measure for server startup, noting it can break libraries that patch prototypes.
## Severity classification
- **Critical**: Recursive merge or bracket-notation write where the key source is directly from HTTP input (req.body, req.query, req.params) with no sanitization.
- **High**: Same patterns but key source is indirectly tainted (parsed config, deserialized message, database-stored user content).
- **Medium**: Patterns that are structurally unsafe but where the key source is internal or partially validated.
## Review output format
For each finding, report:
```
[SEVERITY] file:line — brief description
Pattern: the code pattern found
Fix: specific remediation
```
After all findings, add a summary line: `X prototype pollution risks found (C critical, H high, M medium).`
If no issues are found, state: `No prototype pollution risks detected.`