The cross-side scripting (XSS) is one of the more usual vulnerabilities we can have in our web application. They allow potential attackers to inject malicious scripts in pages viewed by end-users.
But if we follow the common architecture in our projects that separates the HTML templates from the JS controllers, most of our work is done! Due to the fact the majority of the frameworks we use nowadays for rendering our templates escape the HTML code.
Divide and conquer
This old motto has been very present in the life of a developer. It is still very popular today with other cool names like Microservices, however I prefer to call it Component Driven Development.
The smaller our components, the better they will operate. This way, we can think about security less as we don’t have to cover complex scenarios.
Delegate to the browsers
We often forget that the browsers do a good job when we are manipulating the DOM. They also handle security concerns very well . So instead of creating / updating elements from the DOM directly from a string, why don’t we use the JS API?
return '<a href="...">...</a>';
let a = document.createElement('a'); a.href = '...'; let text = document.createTextNode('...'); a.appendChild(text);
Avoiding reverse tabnabbing
Reverse tabnabbing is a phishing attack, where an attacker replaces a page tab with a malicious document by using window.opener.location.assign().
But we can avoid this just simply using noopener and noreferrer in the rel attributes of a link.
By adding the noopener keyword, the new / other page cannot access the window object via window.opener. And the noreferrer keyword tells the browser not to collect HTTP referrer information when the link is followed.
Lint your code
Everybody knows the benefits of a linter. They provide feedback in real-time about our code, according to the rules we specify. But most importantly, they do it automatically.
So, if we want to be sure that all the security rules will be applied, it will be better if we configure our linter for that.
Content security policy
One last thing we can do, is to include a header in the HTTP responses for restricting the domains that can load content in our application.
Content-Security-Policy: script-src 'self' static.ebury.com
The previous policy will allow to run only the scripts hosted in the same server as the application (self) and the ones hosted in static.ebury.com. Hence, it will mitigate potential XSS and data injection attacks performed by scripts hosted in external domains.
In case you now would like to watch the Java Script Security Workshop, it is available on YouTube. Enjoy!