diff --git a/CHANGELOG.md b/CHANGELOG.md
index c87275665c..c0ee24cde9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -232,6 +232,14 @@ aggregate instead: an italic *Catalog* line at the end of the version section an
### Fixed
+- **CodeQL alert #103** — an ECharts tooltip called `.replace("\n", " ")` with a string argument,
+ which replaces only the first occurrence
+ (`plots/bar-heart-rate-zones/implementations/javascript/echarts.js`). Nothing renders differently
+ today, since every zone label carries exactly one newline; the defect is latent, and a label
+ gaining a second line break would put a raw newline inside the tooltip's HTML. The pattern occurs
+ exactly once across the catalogue — were it recurring it would belong in the generation prompt,
+ since `plots/` is pipeline output and a regeneration overwrites this file (#10480).
+
- **A database outage would have reopened the hole #10453 closed** — with no catalogue to check
against, the bot routes answered 200 with a fabricated page for any string, self-canonicalising,
exactly the defect that PR removed. Degraded pages now carry `noindex`. The path is unreachable in
diff --git a/plots/bar-heart-rate-zones/implementations/javascript/echarts.js b/plots/bar-heart-rate-zones/implementations/javascript/echarts.js
index 459ff9d930..e0d3f57108 100644
--- a/plots/bar-heart-rate-zones/implementations/javascript/echarts.js
+++ b/plots/bar-heart-rate-zones/implementations/javascript/echarts.js
@@ -52,7 +52,7 @@ chart.setOption({
formatter: (params) => {
const idx = params[0].dataIndex;
return (
- `${zoneNames[idx].replace("\n", " ")}
` +
+ `${zoneNames[idx].replace(/\n/g, " ")}
` +
`Duration: ${minutes[idx]} min
` +
`HR range: ${hrRanges[idx]}`
);