Mariam Reba Alexander

Cross-site scripting (XSS) attack - part 3

Created August 6, 2021

By now you have an understanding of Stored XSS attack and Reflected XSS attack, and some measures to prevent it. Now we will look into the last type of XSS attack, DOM based XSS attack. In the end, I will conclude with best practices to follow, testing XSS and references for reading.

3.DOM based Cross-site scripting

The difference in DOM based XSS from the other type of XSS type is that, the attack happens only via client-side application. In Stored and Reflected type of XSS there are some server-side requests involved.

DOM based XSS mainly happens by injecting malicious javascript via URI fragments and can execute runtime in browser.

URI fragments, how they work

What is this URI fragment ? Have you noticed when you click on certain links for a documentation, it navigates and scrolls down right to the section. Well, that's because the link looks like this and on clicking it the page scrolls down to the section "bar" which has the element with id="bar".

The URI fragment is the optional part of the URL after the # sign.

Popular frameworks like React, Vue and Angular make use of URI fragment for a different reason. In Single Page Apps (SPA), whenever the user refreshes or reload the page, the initial state of the content is lost and therefore a rendering blink can be noticed. To avoid losing the state of the page, these framework uses URI fragment at the end of the URL.

For example, if a page uses pagination, the SPA may make use of the URI fragment to indicate the page number and will update the number as the user goes to the next page. Now, even if user refreshes the browser, the JavaScript code can interpret the content of the URI fragment, and load the relevant page visited previously.

The URI fragments does not interact with the server-side, therefore securing server-side code will not prevent DOM based XSS attacks and will not be recorded in server logs.
The attack happens when an attacker crafts malicious javascript in the URI fragment and tricks a user to click it, and the attack is launched when the Javascript code interprets the content of the fragments unescaped.

The fragment value including the hash can be accessed in the code by the method window.location.hash. These are usually not percent-decoded.

Dom based XSS flow

Defence #1 - You guessed it ! Escape dynamic content from URI fragments

You need to escape anything that comes out of URI fragments before using that value in HTML or in Javascript.

Examples of vulnerable code

var x = location.hash.split("#")[1];
 var x = '<%= taintedVar %>';
 var d = document.createElement('div');
 d.innerHTML = x;

There are a lot of scenarios and contexts that you need to look out for, and it's not easy. Using a web application development framework for your frontend application, will lower the risks of XSS attacks due to its auto-escaping and context-awareness. If not, make use of OWASP Enterprise Security API (ESAPI) that makes it easier to write low-risk application code.

The npm library for ESAPI is node-esapi which includes functions for encoding HTML, HTML attributes, Javascript and CSS.

Examples of usage of this library is as below

 var ESAPI = require('node-esapi');
 element.innerHTML = "<%=ESAPI.encoder().encodeForJS(ESAPI.encoder().encodeForHTML(untrustedData))%>";
 element.outerHTML = "<%=ESAPI.encoder().encodeForJS(ESAPI.encoder().encodeForHTML(untrustedData))%>";
 var ESAPI = require('node-esapi');

Best practices for preventing XSS


Many XSS vulnerabilities are caused by passing user data to Javascript execution sinks (browser mechanisms that will execute scripts from their input). Such APIs include .innerHTML, document.write and eval(). When user-controlled data (in the form of location.*, document.cookie or JavaScript variables containing user data) is returned by the server, calling such functions can lead to XSS.


Make sure you apply proper escaping (including HTML-escaping of characters such as < and >). Do not allow user-supplied data to be returned as the first part of the response (as often happens in JSONP). Do not use eval() to parse the data.

HTML sanitization:

If you need to support user-supplied markup such as images or links, look for technologies that support HTML sanitization. For example, sanitize-html

Testing for XSS

Note: Follow this guide for the testing other alternative kinds of XSS attacks XSS Filter Evasion Cheat Sheet


For more detailed ways of prevention against XSS attacks, read through the following

Here ends the posts for Cross-site scripting attacks. Hope you got a better understanding about XSS now and take necessary measures to protect your code.