mirror of
https://github.com/inventree/InvenTree.git
synced 2026-08-30 16:58:06 +00:00
Strip potentially dangerous tags from SVG files (#12687)
This commit is contained in:
@@ -64,10 +64,6 @@ _SVG_ALLOWED_CSS_PROPERTIES = frozenset([
|
|||||||
|
|
||||||
ALLOWED_ELEMENTS_SVG = [
|
ALLOWED_ELEMENTS_SVG = [
|
||||||
'a',
|
'a',
|
||||||
'animate',
|
|
||||||
'animateColor',
|
|
||||||
'animateMotion',
|
|
||||||
'animateTransform',
|
|
||||||
'circle',
|
'circle',
|
||||||
'defs',
|
'defs',
|
||||||
'desc',
|
'desc',
|
||||||
@@ -83,13 +79,11 @@ ALLOWED_ELEMENTS_SVG = [
|
|||||||
'marker',
|
'marker',
|
||||||
'metadata',
|
'metadata',
|
||||||
'missing-glyph',
|
'missing-glyph',
|
||||||
'mpath',
|
|
||||||
'path',
|
'path',
|
||||||
'polygon',
|
'polygon',
|
||||||
'polyline',
|
'polyline',
|
||||||
'radialGradient',
|
'radialGradient',
|
||||||
'rect',
|
'rect',
|
||||||
'set',
|
|
||||||
'stop',
|
'stop',
|
||||||
'svg',
|
'svg',
|
||||||
'switch',
|
'switch',
|
||||||
@@ -98,21 +92,20 @@ ALLOWED_ELEMENTS_SVG = [
|
|||||||
'tspan',
|
'tspan',
|
||||||
'use',
|
'use',
|
||||||
]
|
]
|
||||||
|
# SMIL animation elements ('animate', 'set', etc.) are intentionally excluded: nh3's
|
||||||
|
# URL-scheme filtering (e.g. stripping `javascript:` from `href`/`xlink:href`) is only
|
||||||
|
# applied to attributes it recognises as URL-bearing on the element that declares them.
|
||||||
|
# It does not recognise the `to`/`from`/`values` attributes of animation elements as
|
||||||
|
# URL-setting, so a `javascript:` URL placed there survives sanitization and is assigned
|
||||||
|
# to a target element's `href` at render time, bypassing the URL sanitization entirely.
|
||||||
|
|
||||||
ALLOWED_ATTRIBUTES_SVG = [
|
ALLOWED_ATTRIBUTES_SVG = [
|
||||||
'accent-height',
|
'accent-height',
|
||||||
'accumulate',
|
|
||||||
'additive',
|
|
||||||
'alphabetic',
|
'alphabetic',
|
||||||
'arabic-form',
|
'arabic-form',
|
||||||
'ascent',
|
'ascent',
|
||||||
'attributeName',
|
|
||||||
'attributeType',
|
|
||||||
'baseProfile',
|
'baseProfile',
|
||||||
'bbox',
|
'bbox',
|
||||||
'begin',
|
|
||||||
'by',
|
|
||||||
'calcMode',
|
|
||||||
'cap-height',
|
'cap-height',
|
||||||
'class',
|
'class',
|
||||||
'color',
|
'color',
|
||||||
@@ -125,8 +118,6 @@ ALLOWED_ATTRIBUTES_SVG = [
|
|||||||
'dy',
|
'dy',
|
||||||
'descent',
|
'descent',
|
||||||
'display',
|
'display',
|
||||||
'dur',
|
|
||||||
'end',
|
|
||||||
'fill',
|
'fill',
|
||||||
'fill-opacity',
|
'fill-opacity',
|
||||||
'fill-rule',
|
'fill-rule',
|
||||||
@@ -136,7 +127,6 @@ ALLOWED_ATTRIBUTES_SVG = [
|
|||||||
'font-style',
|
'font-style',
|
||||||
'font-variant',
|
'font-variant',
|
||||||
'font-weight',
|
'font-weight',
|
||||||
'from',
|
|
||||||
'fx',
|
'fx',
|
||||||
'fy',
|
'fy',
|
||||||
'g1',
|
'g1',
|
||||||
@@ -150,9 +140,6 @@ ALLOWED_ATTRIBUTES_SVG = [
|
|||||||
'id',
|
'id',
|
||||||
'ideographic',
|
'ideographic',
|
||||||
'k',
|
'k',
|
||||||
'keyPoints',
|
|
||||||
'keySplines',
|
|
||||||
'keyTimes',
|
|
||||||
'lang',
|
'lang',
|
||||||
'marker-end',
|
'marker-end',
|
||||||
'marker-mid',
|
'marker-mid',
|
||||||
@@ -161,8 +148,6 @@ ALLOWED_ATTRIBUTES_SVG = [
|
|||||||
'markerUnits',
|
'markerUnits',
|
||||||
'markerWidth',
|
'markerWidth',
|
||||||
'mathematical',
|
'mathematical',
|
||||||
'max',
|
|
||||||
'min',
|
|
||||||
'name',
|
'name',
|
||||||
'offset',
|
'offset',
|
||||||
'opacity',
|
'opacity',
|
||||||
@@ -178,11 +163,8 @@ ALLOWED_ATTRIBUTES_SVG = [
|
|||||||
'r',
|
'r',
|
||||||
'refX',
|
'refX',
|
||||||
'refY',
|
'refY',
|
||||||
'repeatCount',
|
|
||||||
'repeatDur',
|
|
||||||
'requiredExtensions',
|
'requiredExtensions',
|
||||||
'requiredFeatures',
|
'requiredFeatures',
|
||||||
'restart',
|
|
||||||
'rotate',
|
'rotate',
|
||||||
'rx',
|
'rx',
|
||||||
'ry',
|
'ry',
|
||||||
@@ -204,7 +186,6 @@ ALLOWED_ATTRIBUTES_SVG = [
|
|||||||
'systemLanguage',
|
'systemLanguage',
|
||||||
'target',
|
'target',
|
||||||
'text-anchor',
|
'text-anchor',
|
||||||
'to',
|
|
||||||
'transform',
|
'transform',
|
||||||
'type',
|
'type',
|
||||||
'u1',
|
'u1',
|
||||||
@@ -214,7 +195,6 @@ ALLOWED_ATTRIBUTES_SVG = [
|
|||||||
'unicode',
|
'unicode',
|
||||||
'unicode-range',
|
'unicode-range',
|
||||||
'units-per-em',
|
'units-per-em',
|
||||||
'values',
|
|
||||||
'version',
|
'version',
|
||||||
'viewBox',
|
'viewBox',
|
||||||
'visibility',
|
'visibility',
|
||||||
|
|||||||
@@ -1678,6 +1678,27 @@ class SanitizerTest(TestCase):
|
|||||||
# Test that invalid string is cleaned
|
# Test that invalid string is cleaned
|
||||||
self.assertNotEqual(dangerous_string, sanitize_svg(dangerous_string))
|
self.assertNotEqual(dangerous_string, sanitize_svg(dangerous_string))
|
||||||
|
|
||||||
|
def test_svg_sanitizer_smil_bypass(self):
|
||||||
|
"""Test that SMIL animation elements cannot be used to smuggle a javascript: URL.
|
||||||
|
|
||||||
|
A <set>/<animate>/<animateTransform> element can assign a `javascript:` value to
|
||||||
|
another element's `href`/`xlink:href` at render time via its `to`/`from`/`values`
|
||||||
|
attribute. These attributes are not treated as URLs by the sanitizer, so simply
|
||||||
|
stripping `javascript:` from `href`-like attributes is not sufficient - the
|
||||||
|
elements themselves must not be permitted.
|
||||||
|
"""
|
||||||
|
malicious_string = """<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<a xlink:href="https://example.com">
|
||||||
|
<set attributeName="xlink:href" to="javascript:alert(document.domain)" />
|
||||||
|
<text x="10" y="20">Click me</text>
|
||||||
|
</a>
|
||||||
|
</svg>"""
|
||||||
|
|
||||||
|
cleaned = sanitize_svg(malicious_string)
|
||||||
|
|
||||||
|
self.assertNotIn('javascript:', cleaned)
|
||||||
|
self.assertNotIn('<set', cleaned)
|
||||||
|
|
||||||
|
|
||||||
class MagicLoginTest(InvenTreeTestCase):
|
class MagicLoginTest(InvenTreeTestCase):
|
||||||
"""Test magic login token generation."""
|
"""Test magic login token generation."""
|
||||||
|
|||||||
Reference in New Issue
Block a user