This is more of a "can you please confirm this is correct" type of question, as I think I resolved it in the process of writing the question but hopefully it will be of help to other people who are a bit hesitant when it comes to implementing DOMPurify.
Short Version
Is it safe/valid to import and use DOMPurify
like this in frontend js file:
npm install dompurify --save
import DOMPurify from 'dompurify';
var clean = DOMPurify.sanitize('<img src=x onerror=alert(1)//>', {SAFE_FOR_JQUERY: true});
Detailed Version
Currently my main frontend js file imports using these conventions:
import ClipboardJS from 'clipboard';
// date-fns functions
import getYear from 'date-fns/get_year';
import getMonth from 'date-fns/get_month';
import getDaysInMonth from 'date-fns/get_days_in_month';
import startOfMonth from 'date-fns/start_of_month';
import getDay from 'date-fns/get_day';
import format from 'date-fns/format';
import Cookies from './js.cookie';
I tried the following:
npm install dompurify --save
import DOMPurify from 'dompurify';
console.log(DOMPurify.sanitize('<img src=x onerror=alert(1)//>', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<svg><g/onload=alert(2)//<p>', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<p>abc<iframe/\/src=jAva	script:alert(3)>def', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<math><mi//xlink:href="data:x,<script>alert(4)</script>">', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<TABLE><tr><td>HELLO</tr></TABL>', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<UL><li><A HREF=//google.com>click</UL>', {SAFE_FOR_JQUERY: true}));
The string examples are from here:
https://github.com/cure53/DOMPurify#some-purification-samples-please
And use the SAFE_FOR_JQUERY
flag mentioned here:
https://github.com/cure53/DOMPurify#can-i-configure-it
Everything is logging as expected, ie:
<img src="x">
<svg><g></g></svg>
<p>abcdef</p>
<math><mi></mi></math>
<table><tbody><tr><td>HELLO</td></tr></tbody></table>
<ul><li><a href="//google.com">click</a></li></ul>
So that is good.
Question
The official DOMPurify readme shows the following ways to import and use:
// method 01
<script type="text/javascript" src="dist/purify.min.js"></script>
var clean = DOMPurify.sanitize(dirty);
// method 02
require(['dompurify'], function(DOMPurify) {
var clean = DOMPurify.sanitize(dirty);
});
// method 03
npm install dompurify
const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const window = (new JSDOM('')).window;
const DOMPurify = createDOMPurify(window);
const clean = DOMPurify.sanitize(dirty);
// method 04
const createDOMPurify = require('dompurify');
const jsdom = require('jsdom').jsdom;
const window = jsdom('').defaultView;
const DOMPurify = createDOMPurify(window);
const clean = DOMPurify.sanitize(dirty);
Even though the way I have implemented it is not listed, is this still a safe/valid way to do it:
npm install dompurify --save
import DOMPurify from 'dompurify';
PS, if required for context...
The implementation scenario is:
01)
A user starts with a span:
<span class="editable" data-previous_value="here is previously saved value">here is previously saved value</span>
02)
When the span is clicked on, the value of data-previous_value
is added to an input
element which replaces the span
.
03)
A user modifies the text in the input
element and clicks save.
04)
I use markdown-it with the html
option set to false
and markdown-it-attrs (to add css styles) and markdown-it-span (to define spans
) to render any markdown as html (links, images, classes, spans etc).
05)
The new value is added to a new span
element (rendered with markdown-it
) and data
attribute (unrendered) which replaces the input
element.
06)
The new, unrendered, value is saved in MongoDB
database via Node/Express
.
As an example, the following input:
![img](/img/my_thumb.jpg){.video_thumb} [Video](https://www.youtube.com/watch?v=dQw4w9WgXcQ)
is converted to this html:
<span class="editable" data-previous_value="![img](/img/my_thumb.jpg){.video_thumb} [Video](https://www.youtube.com/watch?v=dQw4w9WgXcQ)">
<img src="/img/my_thumb.jpg" alt="img" class="video_thumb">
<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">Video</a>
</span>
I am thinking of sanitizing the input with DOMPurify
before it gets to markdown-it
(before step 04).