From c2a28bcadf58a78e400c9c3a47ad405bf29c90c9 Mon Sep 17 00:00:00 2001 From: Nazar Kanaev Date: Wed, 7 Apr 2021 14:34:57 +0100 Subject: [PATCH] allow svg in sanitizer --- doc/thirdparty.txt | 6 +- doc/todo.txt | 2 - src/content/sanitizer/sanitizer.go | 13 +- src/content/sanitizer/whitelist.go | 256 +++++++++++++++++++++++++++++ 4 files changed, 269 insertions(+), 8 deletions(-) diff --git a/doc/thirdparty.txt b/doc/thirdparty.txt index 6cb2413..65e3e73 100644 --- a/doc/thirdparty.txt +++ b/doc/thirdparty.txt @@ -11,8 +11,10 @@ The licenses are included, and the authorship comments are left intact. - sanitizer https://github.com/miniflux/v2 (commit:3cb04b2) Apache 2.0 - changed allowed tags to the one from https://github.com/cure53/DOMPurify - changed allowed uri schemes to the one from https://github.com/cure53/DOMPurify + whitelist changed to the ones from https://github.com/cure53/DOMPurify: + - allowed tags + - allowed uri schemes + - added svg whitelist - systray https://github.com/getlantern/systray (commit:2c0986d) Apache 2.0 diff --git a/doc/todo.txt b/doc/todo.txt index 9062ed2..81591e2 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -1,5 +1,3 @@ -- fix: sanitizer/readability clearing out svg? - https://preshing.com/20210315/how-cpp-resolves-a-function-call/ - fix: text is garbled in https://www.tedinski.com/2019/11/17/book-status-update.html - fix: focus on the newly added feed diff --git a/src/content/sanitizer/sanitizer.go b/src/content/sanitizer/sanitizer.go index ea29dd6..3285e18 100644 --- a/src/content/sanitizer/sanitizer.go +++ b/src/content/sanitizer/sanitizer.go @@ -51,7 +51,7 @@ func Sanitize(baseURL, input string) string { buffer.WriteString(html.EscapeString(token.Data)) case html.StartTagToken: - tagName := token.DataAtom.String() + tagName := token.Data parentTag = tagName if isValidTag(tagName) { @@ -70,14 +70,14 @@ func Sanitize(baseURL, input string) string { blacklistedTagDepth++ } case html.EndTagToken: - tagName := token.DataAtom.String() + tagName := token.Data if isValidTag(tagName) && inList(tagName, tagStack) { buffer.WriteString(fmt.Sprintf("", tagName)) } else if isBlockedTag(tagName) { blacklistedTagDepth-- } case html.SelfClosingTagToken: - tagName := token.DataAtom.String() + tagName := token.Data if isValidTag(tagName) { attrNames, htmlAttributes := sanitizeAttributes(baseURL, tagName, token.Attr) @@ -157,13 +157,18 @@ func getExtraAttributes(tagName string) ([]string, []string) { } func isValidTag(tagName string) bool { - return allowedTags.has(tagName) + x := allowedTags.has(tagName) || allowedSvgTags.has(tagName) || allowedSvgFilters.has(tagName) + //fmt.Println(tagName, x) + return x } func isValidAttribute(tagName, attributeName string) bool { if attrs, ok := allowedAttrs[tagName]; ok { return attrs.has(attributeName) } + if allowedSvgTags.has(tagName) { + return allowedSvgAttrs.has(attributeName) + } return false } diff --git a/src/content/sanitizer/whitelist.go b/src/content/sanitizer/whitelist.go index 49b7577..d13e8ee 100644 --- a/src/content/sanitizer/whitelist.go +++ b/src/content/sanitizer/whitelist.go @@ -138,6 +138,78 @@ var allowedTags = sset([]string{ "wbr", }) +var allowedSvgTags = sset([]string{ + "svg", + "a", + "altglyph", + "altglyphdef", + "altglyphitem", + "animatecolor", + "animatemotion", + "animatetransform", + "circle", + "clippath", + "defs", + "desc", + "ellipse", + "filter", + "font", + "g", + "glyph", + "glyphref", + "hkern", + "image", + "line", + "lineargradient", + "marker", + "mask", + "metadata", + "mpath", + "path", + "pattern", + "polygon", + "polyline", + "radialgradient", + "rect", + "stop", + //"style", + "switch", + "symbol", + "text", + "textpath", + "title", + "tref", + "tspan", + "view", + "vkern", +}) + +var allowedSvgFilters = sset([]string{ + "feBlend", + "feColorMatrix", + "feComponentTransfer", + "feComposite", + "feConvolveMatrix", + "feDiffuseLighting", + "feDisplacementMap", + "feDistantLight", + "feFlood", + "feFuncA", + "feFuncB", + "feFuncG", + "feFuncR", + "feGaussianBlur", + "feMerge", + "feMergeNode", + "feMorphology", + "feOffset", + "fePointLight", + "feSpecularLighting", + "feSpotLight", + "feTile", + "feTurbulence", +}) + var allowedAttrs = map[string]set{ "img": sset([]string{"alt", "title", "src", "srcset", "sizes"}), "audio": sset([]string{"src"}), @@ -153,6 +225,190 @@ var allowedAttrs = map[string]set{ "iframe": sset([]string{"width", "height", "frameborder", "src", "allowfullscreen"}), } +var allowedSvgAttrs = sset([]string{ + "accent-height", + "accumulate", + "additive", + "alignment-baseline", + "ascent", + "attributename", + "attributetype", + "azimuth", + "basefrequency", + "baseline-shift", + "begin", + "bias", + "by", + "class", + "clip", + "clippathunits", + "clip-path", + "clip-rule", + "color", + "color-interpolation", + "color-interpolation-filters", + "color-profile", + "color-rendering", + "cx", + "cy", + "d", + "dx", + "dy", + "diffuseconstant", + "direction", + "display", + "divisor", + "dur", + "edgemode", + "elevation", + "end", + "fill", + "fill-opacity", + "fill-rule", + "filter", + "filterunits", + "flood-color", + "flood-opacity", + "font-family", + "font-size", + "font-size-adjust", + "font-stretch", + "font-style", + "font-variant", + "font-weight", + "fx", + "fy", + "g1", + "g2", + "glyph-name", + "glyphref", + "gradientunits", + "gradienttransform", + "height", + "href", + "id", + "image-rendering", + "in", + "in2", + "k", + "k1", + "k2", + "k3", + "k4", + "kerning", + "keypoints", + "keysplines", + "keytimes", + "lang", + "lengthadjust", + "letter-spacing", + "kernelmatrix", + "kernelunitlength", + "lighting-color", + "local", + "marker-end", + "marker-mid", + "marker-start", + "markerheight", + "markerunits", + "markerwidth", + "maskcontentunits", + "maskunits", + "max", + "mask", + "media", + "method", + "mode", + "min", + "name", + "numoctaves", + "offset", + "operator", + "opacity", + "order", + "orient", + "orientation", + "origin", + "overflow", + "paint-order", + "path", + "pathlength", + "patterncontentunits", + "patterntransform", + "patternunits", + "points", + "preservealpha", + "preserveaspectratio", + "primitiveunits", + "r", + "rx", + "ry", + "radius", + "refx", + "refy", + "repeatcount", + "repeatdur", + "restart", + "result", + "rotate", + "scale", + "seed", + "shape-rendering", + "specularconstant", + "specularexponent", + "spreadmethod", + "startoffset", + "stddeviation", + "stitchtiles", + "stop-color", + "stop-opacity", + "stroke-dasharray", + "stroke-dashoffset", + "stroke-linecap", + "stroke-linejoin", + "stroke-miterlimit", + "stroke-opacity", + "stroke", + "stroke-width", + //"style", + "surfacescale", + "systemlanguage", + "tabindex", + "targetx", + "targety", + "transform", + "text-anchor", + "text-decoration", + "text-rendering", + "textlength", + "type", + "u1", + "u2", + "unicode", + "values", + "viewbox", + "visibility", + "version", + "vert-adv-y", + "vert-origin-x", + "vert-origin-y", + "width", + "word-spacing", + "wrap", + "writing-mode", + "xchannelselector", + "ychannelselector", + "x", + "x1", + "x2", + "xmlns", + "y", + "y1", + "y2", + "z", + "zoomandpan", +}) + var allowedURISchemes = sset([]string{ "http", "https",