Skip to content

Commit 0d0d0c6

Browse files
fix: address CodeQL XSS finding in timeline.html
- Sanitize branch param before using as script src - Use textContent + createElement instead of innerHTML for subtitle - Fix label extraction to use .pop() (matches underscore separator)
1 parent 0184b64 commit 0d0d0c6

1 file changed

Lines changed: 11 additions & 10 deletions

File tree

bench/timeline.html

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ <h1 id="title">Memory Timeline (Peak RSS)</h1>
3131
if (!commitId) {
3232
document.getElementById("subtitle").textContent = "No commit specified. Click a point on a stacked chart to view its timeline.";
3333
} else {
34-
// Load data.js for this branch
34+
// Load data.js for this branch (sanitize branch to prevent path traversal)
35+
const safeBranch = branch.replace(/[^a-zA-Z0-9_\-\/\.]/g, "");
3536
const script = document.createElement("script");
36-
script.src = branch + "/data.js";
37+
script.src = safeBranch + "/data.js";
3738
script.onload = function() {
3839
if (!window.BENCHMARK_DATA) {
3940
document.getElementById("subtitle").textContent = "Could not load benchmark data.";
@@ -53,9 +54,7 @@ <h1 id="title">Memory Timeline (Peak RSS)</h1>
5354
const extra = b.extra || "";
5455
const match = extra.match(/^stacked:(.+)$/);
5556
if (match && (!chartFilter || match[1] === chartFilter)) {
56-
// Use last 2 path segments as label
57-
const parts = b.name.split("/");
58-
const label = parts.length >= 2 ? parts.slice(-2).join("/") : parts.pop();
57+
const label = b.name.split("/").pop();
5958
stages.push({ label: label, value: b.value, unit: b.unit || "MB" });
6059
}
6160
});
@@ -74,11 +73,13 @@ <h1 id="title">Memory Timeline (Peak RSS)</h1>
7473
const commitMsg = entry.commit.message || "";
7574

7675
document.getElementById("title").textContent = commitId.slice(0, 7) + " Memory Timeline";
77-
const backHref = "index.html?branch=" + encodeURIComponent(branch);
78-
document.getElementById("subtitle").innerHTML =
79-
stages.length + " stages | Peak: " + peakVal + " " + unit +
80-
" at " + stages[peakIdx].label +
81-
' | <a href="' + backHref + '">&larr; Back to dashboard</a>';
76+
const subtitle = document.getElementById("subtitle");
77+
subtitle.textContent = stages.length + " stages | Peak: " + peakVal + " " + unit +
78+
" at " + stages[peakIdx].label + " | ";
79+
const backLink = document.createElement("a");
80+
backLink.href = "index.html?branch=" + encodeURIComponent(branch);
81+
backLink.textContent = "\u2190 Back to dashboard";
82+
subtitle.appendChild(backLink);
8283

8384
const labels = stages.map(s => s.label.length > 55 ? s.label.slice(0, 52) + "..." : s.label);
8485
const fullLabels = stages.map(s => s.label);

0 commit comments

Comments
 (0)