Back to all agents

TypeScript Prototype Pollution Audit

Detect prototype pollution vulnerabilities and unsafe object merge patterns in TypeScript code.

1 views
Cursor
typescriptsecurityprototype-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.`