Skip to content

Commit df19bfe

Browse files
fix(site): parse the bounce ?p= value through URL before restoring
Build the restored URL by feeding `p` into the URL constructor and appending any extra search params from the bounce URL. The old version concatenated strings, which produced a malformed `/foo?a=1?x=2` if `p` already carried a query (or an extra param landed on the bounce URL). Also reject `p` values that don't look like same-origin relative paths so a crafted `?p=//host/foo` can't try to flip the visible origin. Addresses Copilot feedback on #15.
1 parent c3a0da1 commit df19bfe

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

site/index.html

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,22 @@
1616
(function () {
1717
var url = new URL(window.location.href);
1818
var p = url.searchParams.get("p");
19-
if (p) {
20-
url.searchParams.delete("p");
21-
window.history.replaceState(null, "", p + url.search + url.hash);
22-
}
19+
// Only restore same-origin relative paths so a crafted ?p= can't try
20+
// to replace the visible origin (replaceState would throw anyway).
21+
if (!p || p[0] !== "/" || p[1] === "/") return;
22+
url.searchParams.delete("p");
23+
// Parse `p` through URL so its own query/hash compose cleanly with
24+
// whatever extra params or hash were on the bounce URL.
25+
var restored = new URL(p, window.location.origin);
26+
url.searchParams.forEach(function (value, key) {
27+
restored.searchParams.append(key, value);
28+
});
29+
if (!restored.hash) restored.hash = url.hash;
30+
window.history.replaceState(
31+
null,
32+
"",
33+
restored.pathname + restored.search + restored.hash,
34+
);
2335
})();
2436
</script>
2537

0 commit comments

Comments
 (0)