Skip to content

Commit 14ec968

Browse files
authored
Merge pull request #696 from CloudCannon/fix/dom-clobber
Add safety checks around accesses for `document.currentScript.src`
2 parents 012ac7e + 9528ef5 commit 14ec968

File tree

3 files changed

+39
-13
lines changed

3 files changed

+39
-13
lines changed

pagefind_ui/default/svelte/ui.svelte

+13-3
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,21 @@
9999
[
100100
`Pagefind couldn't be loaded from ${this.options.bundlePath}pagefind.js`,
101101
`You can configure this by passing a bundlePath option to PagefindUI`,
102-
`[DEBUG: Loaded from ${
103-
document?.currentScript?.src ?? "no known script location"
104-
}]`,
105102
].join("\n")
106103
);
104+
// Important: Check that the element is indeed a <script> node, to avoid a DOM clobbering vulnerability
105+
if (
106+
document?.currentScript &&
107+
document.currentScript.tagName.toUpperCase() === "SCRIPT"
108+
) {
109+
console.error(
110+
`[DEBUG: Loaded from ${
111+
document.currentScript.src ?? "bad script location"
112+
}]`
113+
);
114+
} else {
115+
console.error("no known script location");
116+
}
107117
}
108118
109119
if (!excerpt_length) {

pagefind_ui/default/ui-core.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import PagefindSvelte from "./svelte/ui.svelte";
22

33
let scriptBundlePath;
44
try {
5-
scriptBundlePath = new URL(document.currentScript.src).pathname.match(
6-
/^(.*\/)(?:pagefind-)?ui.js.*$/
7-
)[1];
5+
// Important: Check that the element is indeed a <script> node, to avoid a DOM clobbering vulnerability
6+
if (document?.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') {
7+
scriptBundlePath = new URL(document.currentScript.src).pathname.match(
8+
/^(.*\/)(?:pagefind-)?ui.js.*$/
9+
)[1];
10+
}
811
} catch (e) {
912
scriptBundlePath = "/pagefind/";
1013
}

pagefind_ui/modular/modular-core.js

+20-7
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ const sleep = async (ms = 50) =>
88

99
let scriptBundlePath;
1010
try {
11-
scriptBundlePath = new URL(document.currentScript.src).pathname.match(
12-
/^(.*\/)(?:pagefind-)?modular-ui.js.*$/
13-
)[1];
11+
// Important: Check that the element is indeed a <script> node, to avoid a DOM clobbering vulnerability
12+
if (document?.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') {
13+
scriptBundlePath = new URL(document.currentScript.src).pathname.match(
14+
/^(.*\/)(?:pagefind-)?modular-ui.js.*$/
15+
)[1];
16+
}
1417
} catch (e) {
1518
scriptBundlePath = "/pagefind/";
1619
}
@@ -166,12 +169,22 @@ export class Instance {
166169
console.error(
167170
[
168171
`Pagefind couldn't be loaded from ${this.options.bundlePath}pagefind.js`,
169-
`You can configure this by passing a bundlePath option to PagefindComposable Instance`,
170-
`[DEBUG: Loaded from ${
171-
document?.currentScript?.src ?? "no known script location"
172-
}]`,
172+
`You can configure this by passing a bundlePath option to PagefindComposable Instance`
173173
].join("\n")
174174
);
175+
// Important: Check that the element is indeed a <script> node, to avoid a DOM clobbering vulnerability
176+
if (
177+
document?.currentScript &&
178+
document.currentScript.tagName.toUpperCase() === "SCRIPT"
179+
) {
180+
console.error(
181+
`[DEBUG: Loaded from ${
182+
document.currentScript?.src ?? "bad script location"
183+
}]`
184+
);
185+
} else {
186+
console.error("no known script location");
187+
}
175188
}
176189

177190
await imported_pagefind.options(this.pagefindOptions || {});

0 commit comments

Comments
 (0)