Use DOMPurify to escape malicious input from user

This commit is contained in:
David Larlet 2023-05-19 14:49:02 -04:00
parent 4f5674073f
commit fd3f854a9c
No known key found for this signature in database
5 changed files with 34 additions and 3 deletions

View file

@ -42,6 +42,7 @@ vendors:
mkdir -p umap/static/umap/vendors/togpx/ && cp -r node_modules/togpx/togpx.js umap/static/umap/vendors/togpx/ mkdir -p umap/static/umap/vendors/togpx/ && cp -r node_modules/togpx/togpx.js umap/static/umap/vendors/togpx/
mkdir -p umap/static/umap/vendors/tokml && cp -r node_modules/tokml/tokml.js umap/static/umap/vendors/tokml mkdir -p umap/static/umap/vendors/tokml && cp -r node_modules/tokml/tokml.js umap/static/umap/vendors/tokml
mkdir -p umap/static/umap/vendors/locatecontrol/ && cp -r node_modules/leaflet.locatecontrol/{dist/L.Control.Locate.css,src/L.Control.Locate.js} umap/static/umap/vendors/locatecontrol/ mkdir -p umap/static/umap/vendors/locatecontrol/ && cp -r node_modules/leaflet.locatecontrol/{dist/L.Control.Locate.css,src/L.Control.Locate.js} umap/static/umap/vendors/locatecontrol/
mkdir -p umap/static/umap/vendors/dompurify/ && cp -r node_modules/dompurify/dist/purify.js umap/static/umap/vendors/dompurify/
installjs: installjs:
npm install npm install
testjsfx: testjsfx:

11
package-lock.json generated
View file

@ -10,6 +10,7 @@
"license": "WTFPL", "license": "WTFPL",
"dependencies": { "dependencies": {
"csv2geojson": "5.1.1", "csv2geojson": "5.1.1",
"dompurify": "^3.0.3",
"georsstogeojson": "^0.1.0", "georsstogeojson": "^0.1.0",
"leaflet": "1.3.4", "leaflet": "1.3.4",
"leaflet-contextmenu": "^1.4.0", "leaflet-contextmenu": "^1.4.0",
@ -676,6 +677,11 @@
"domelementtype": "1" "domelementtype": "1"
} }
}, },
"node_modules/dompurify": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
},
"node_modules/domutils": { "node_modules/domutils": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.3.0.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.3.0.tgz",
@ -3719,6 +3725,11 @@
"domelementtype": "1" "domelementtype": "1"
} }
}, },
"dompurify": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
},
"domutils": { "domutils": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.3.0.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.3.0.tgz",

View file

@ -36,6 +36,7 @@
"homepage": "http://wiki.openstreetmap.org/wiki/UMap", "homepage": "http://wiki.openstreetmap.org/wiki/UMap",
"dependencies": { "dependencies": {
"csv2geojson": "5.1.1", "csv2geojson": "5.1.1",
"dompurify": "^3.0.3",
"georsstogeojson": "^0.1.0", "georsstogeojson": "^0.1.0",
"leaflet": "1.3.4", "leaflet": "1.3.4",
"leaflet-contextmenu": "^1.4.0", "leaflet-contextmenu": "^1.4.0",

View file

@ -53,9 +53,6 @@ L.Util.toHTML = (r) => {
// detect newline format // detect newline format
const newline = r.indexOf('\r\n') != -1 ? '\r\n' : r.indexOf('\n') != -1 ? '\n' : '' const newline = r.indexOf('\r\n') != -1 ? '\r\n' : r.indexOf('\n') != -1 ? '\n' : ''
// Escape tags
r = r.replace(/</gm, '&lt;')
// headings and hr // headings and hr
r = r.replace(/^### (.*)/gm, '<h5>$1</h5>') r = r.replace(/^### (.*)/gm, '<h5>$1</h5>')
r = r.replace(/^## (.*)/gm, '<h4>$1</h4>') r = r.replace(/^## (.*)/gm, '<h4>$1</h4>')
@ -109,6 +106,26 @@ L.Util.toHTML = (r) => {
// Preserver line breaks // Preserver line breaks
if (newline) r = r.replace(new RegExp(newline + '(?=[^]+)', 'g'), '<br>' + newline) if (newline) r = r.replace(new RegExp(newline + '(?=[^]+)', 'g'), '<br>' + newline)
r = DOMPurify.sanitize(r, {
USE_PROFILES: { html: true },
ALLOWED_TAGS: [
'h3',
'h4',
'h5',
'hr',
'strong',
'em',
'ul',
'li',
'a',
'div',
'iframe',
'img',
'br',
],
ALLOWED_ATTR: ['target', 'href', 'frameborder', 'src', 'width', 'height'],
})
return r return r
} }
L.Util.isObject = (what) => typeof what === 'object' && what !== null L.Util.isObject = (what) => typeof what === 'object' && what !== null

View file

@ -23,6 +23,7 @@
<script src="{{ STATIC_URL }}umap/vendors/togpx/togpx.js"></script> <script src="{{ STATIC_URL }}umap/vendors/togpx/togpx.js"></script>
<script src="{{ STATIC_URL }}umap/vendors/tokml/tokml.js"></script> <script src="{{ STATIC_URL }}umap/vendors/tokml/tokml.js"></script>
<script src="{{ STATIC_URL }}umap/vendors/locatecontrol/L.Control.Locate.js"></script> <script src="{{ STATIC_URL }}umap/vendors/locatecontrol/L.Control.Locate.js"></script>
<script src="{{ STATIC_URL }}umap/vendors/dompurify/purify.js"></script>
{% endcompress %} {% endcompress %}
{% if locale %} {% if locale %}
<script src="{{ STATIC_URL }}umap/locale/{{ locale }}.js"></script> <script src="{{ STATIC_URL }}umap/locale/{{ locale }}.js"></script>