diff --git a/src/core/operations/SeriesChart.mjs b/src/core/operations/SeriesChart.mjs index 7baf594c..3725441b 100644 --- a/src/core/operations/SeriesChart.mjs +++ b/src/core/operations/SeriesChart.mjs @@ -15,6 +15,20 @@ import Utils from "../Utils.mjs"; const d3 = d3temp.default ? d3temp.default : d3temp; const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp; +/** + * Removes D3's internal bound data from a nodom tree before serialization. + * nodom serializes enumerable expando properties such as __data__ as attributes, + * so leaving them on attacker-controlled values can create executable markup. + * + * @param {Object} node + */ +function clearD3BoundData(node) { + delete node.__data__; + + if (!node.childNodes) return; + node.childNodes.forEach(clearD3BoundData); +} + /** * Series chart operation */ @@ -222,6 +236,8 @@ class SeriesChart extends Operation { .text(serie.name); }); + clearD3BoundData(svg.node()); + return svg._groups[0][0].outerHTML; } diff --git a/tests/operations/tests/Charts.mjs b/tests/operations/tests/Charts.mjs index a62b5741..6d56c732 100644 --- a/tests/operations/tests/Charts.mjs +++ b/tests/operations/tests/Charts.mjs @@ -41,6 +41,17 @@ TestRegister.addTests([ } ], }, + { + name: "Series chart escapes x-axis values in serialized SVG", + input: `s,x">