From b090482bd0c01cc478d2daec9cf8e019723b65c1 Mon Sep 17 00:00:00 2001
From: GCHQ Developer 85297 <95289555+C85297@users.noreply.github.com>
Date: Mon, 18 May 2026 11:57:16 +0100
Subject: [PATCH] Series Chart HTML Formatting fix (#2403)
---
src/core/operations/SeriesChart.mjs | 16 ++++++++++++++++
tests/operations/tests/Charts.mjs | 11 +++++++++++
2 files changed, 27 insertions(+)
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">