Back to Skills

prototype-pollution

Prototype pollution testing for JavaScript stacks. Use when user input is merged into objects (query parsers, JSON bodies, deep assign), when configuring libraries via untrusted keys, or when hunting RCE gadgets via polluted Object.prototype in Node or the browser.

1,297stars177forksUpdated 7/7/2026

Security Assessment

Critical Risk(0/100)

Detected risks:

Remote Code Execution([SKILL.md] exec()
Sensitive File Access([SKILL.md] .env)
Command Injection([SKILL.md] child_process)
Security Score0/100

About prototype-pollution

A security-testing playbook for finding and exploiting prototype pollution in JavaScript stacks, both client and server side. It becomes relevant whenever untrusted input is merged into objects — query-string parsers, JSON bodies, deep assign or deep merge helpers, GraphQL variables, or YAML converted to JSON — and it prioritizes cases that use libraries such as lodash.merge, deep-extend, hoek.applyToDefaults, or qs.

The document explains the mechanism: because property lookups walk the prototype chain up to Object.prototype, a merge that treats a literal __proto__ or constructor.prototype key as a path can attach attacker-controlled properties to the shared prototype, so unrelated later code reads them as if legitimate. It stresses testing both the __proto__ and constructor.prototype paths, since filtering and parser differences make them non-equivalent.

Detection is split into client-side probes (URL-fragment payloads like #__proto__[polluted]=1, DOM and attribute injection ideas, and console verification that a test key persists on Object.prototype) and black-box server-side probes. The server section provides a table of side-effect payloads — polluting qs settings like parameterLimit, ignoreQueryPrefix, and allowDots, or Express behaviors such as 'json spaces', exposedHeaders, and status — and advises sending a pollution request followed by a clean request to observe global persistence. An exploitation section catalogs gadget chains: EJS template options leading to RCE via child_process, the historical Timelion CVE-2019-7609 expression chain, polluting spawn/fork option objects like shell, argv0, env, and NODE_OPTIONS, and using the constructor path to bypass weak __proto__-only filters. It lists research tooling (pp-finder, silent-spring, PPScan, and others) and closes with a decision tree, while cautioning that automated testing can cause side effects and should target only authorized systems.

FAQ

What is prototype pollution?

A JavaScript vulnerability where merging attacker-controlled keys like __proto__ or constructor.prototype attaches properties to Object.prototype, so unrelated later code reads those polluted values as if legitimate.

When should I raise the priority of this test?

When the target uses deep merges or recursive assign, JSON.parse followed by Object.assign, URL queries converted to nested objects, or libraries like lodash.merge, deep-extend, hoek.applyToDefaults, or qs.

How do you detect server-side pollution in black-box testing?

Send payloads that pollute parser or framework settings (for example qs parameterLimit and allowDots, or Express 'json spaces' and status), then send a clean follow-up request to observe global side effects.

Why test both __proto__ and constructor.prototype?

They are not always equivalent — filtering, JSON parsing, and Node/Bun differences mean one path may be blocked while the other works, and the constructor path also bypasses filters that only block __proto__.

What gadgets can turn pollution into remote code execution?

The playbook describes EJS template-option gadgets executing child_process, the Timelion CVE-2019-7609 chain, and polluting spawn/fork option objects such as shell, argv0, env, and NODE_OPTIONS.

Install prototype-pollution

Download and extract the skill files to your .claude/skills/ directory.

Quick Setup:

  1. Copy the skill folder to .claude/skills/
  2. Claude will automatically detect and use the skill