---
name: validate-xss
description: Evidence bar, impact ladder, victim-interaction limits, PoC shape and two-actor report steps for cross-site scripting. Use when validating a finding that claims stored, reflected or DOM XSS.
---

# Validate XSS

## Establish execution

- Confirm execution in a real browser with `agent-browser`; reflection in a response is not enough. Use the smallest context-appropriate payload that calls `alert(document.domain)`, and record the exact origin, injection context, delivery path (stored, reflected or DOM) and the victim interaction required.
- The payload must run in the target's origin with the victim's authenticated session. Execution only in a sandboxed iframe, a `null`, `data:` or `blob:` origin, a user-content or sandbox domain that holds no session, or the attacker's own session (self-XSS) has no cross-user impact unless you chain it into the victim's session and demonstrate the chain.
- Reflection that does not execute, such as in a `text/plain` or `application/json` response, encoded output, or a payload blocked by CSP, is not XSS. Test in current Chrome, and name the browser in the report when execution depends on one.

## Demonstrate impact

- A bare `alert` is low impact. For a high or critical claim, use only researcher-controlled attacker and victim accounts and show, on the attacker's side, the strongest of these the target allows:
  1. **Session theft:** the payload sends the victim's session cookie or bearer token (a non-HttpOnly cookie, a token in `localStorage` or `sessionStorage`, or one returned by a same-origin page or API) to the attacker, who uses it to read the victim's identity.
  2. **Account takeover by action:** when the session cannot be read, the payload acts with it: it fetches any CSRF token, then changes the victim's email, phone or linked login to an attacker-controlled value, or adds an attacker-controlled MFA factor, API key or OAuth grant. The attacker then logs in as the victim. Take the attacker-controlled value as a PoC flag such as `--attacker-email`.
  3. **Sensitive data:** when neither is possible, read the most sensitive victim data the session reaches, such as PII, messages, payment details or API keys, and send it to the attacker.
- For XSS on a secondary subdomain, look for gadgets that reach the main application's session: cookies scoped to the parent domain, an OAuth or SSO `redirect_uri` that accepts the subdomain (steal the code or token), `postMessage` listeners or CORS policies that trust sibling subdomains, or cookie tossing into the main application. Claim the main application's impact only when you demonstrate it.
- Stop at the minimum victim observation the claim needs. Send data only to the PoC's callback, and do not collect unrelated data or make changes beyond the demonstrated takeover of researcher accounts.

## Victim interaction

- The most victim interaction that still counts as a one-click account takeover, accepted as high impact, is: the victim is logged in, then opens one attacker link or page and clicks once. A stored payload that fires when the victim views an ordinary page needs no click.
- More interaction, such as several clicks, typing, drag and drop, pasting or a non-default setting, lowers the impact. State exactly what is needed and do not call it one-click.
- Host an attacker page, when one is needed, with `toadcli serve`.

## PoC

- The attached PoC is the attacker's script. Do not automate the victim's browser in it: the triager plays the victim in their own browser. Its default run:
  - completes every attacker-side prerequisite, such as logging in as the attacker, planting a stored payload or sending the victim a message, taking any victim identifier as a flag;
  - prints the exact URL or page the victim must open;
  - polls the callback the validator instructions name for a triager-facing PoC, with a `--timeout`, then prints what arrived and the victim identity it proves, such as the victim's email read with the stolen token or the account the attacker is now logged in as. It exits non-zero on timeout.
- Before publishing, replay the report's steps exactly: run the script in a terminal and play the victim in `agent-browser` with the researcher-controlled victim account. Confirm the script prints the victim's value.
- When a PoC video is required, play the victim in `agent-browser` while the recording runs so the callback arrives on camera.

## Report

Write the reproduction steps as two actors, in the order the flow needs, inside the submission format's reproduction section. Do not reduce them to a single "run the script" step.

```
**As the attacker**

1. Run the attached PoC. It <attacker-side setup>, prints the URL the victim must open, and waits for the victim:

   uv run <name>.py --attacker-email attacker@example.com

   <verbatim output up to the waiting line>

**As the victim**

2. Log in to https://<target> as the victim.
3. In the same browser, open the URL printed in step 1:

   https://<target>/<path>?q=<payload>

**As the attacker**

4. The PoC receives the victim's <session / data> and prints:

   <verbatim output>
```

- Include the equivalent `--proxy` command and keep output verbatim, as the `write-finding-report` skill requires.
- When the victim must act first, for example to give the attacker an identifier for a stored payload, start with **As the victim** (log in and note the identifier), then the attacker steps that use it, then return to the victim to trigger the payload.
- Show the payload once, decoded, and explain any non-obvious part, such as why it survives the filter or what it calls.
- In the impact section, name what the attacker obtained (the session, account or data) and the exact victim interaction it needed.
