@floegence/flowersec-core 0.19.2 → 0.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/proxy/serviceWorker.js +43 -10
- package/package.json +1 -1
|
@@ -13,6 +13,28 @@ function normalizePathPrefix(name, v) {
|
|
|
13
13
|
throw new Error(`${name} must not include scheme/host`);
|
|
14
14
|
return s;
|
|
15
15
|
}
|
|
16
|
+
function normalizeRootRelativeScriptURL(name, v) {
|
|
17
|
+
if (typeof v !== "string")
|
|
18
|
+
throw new Error(`${name} must be a string`);
|
|
19
|
+
const s = v.trim();
|
|
20
|
+
if (s === "")
|
|
21
|
+
throw new Error(`${name} must be non-empty`);
|
|
22
|
+
if (s !== v)
|
|
23
|
+
throw new Error(`${name} must not contain leading or trailing whitespace`);
|
|
24
|
+
if (!s.startsWith("/"))
|
|
25
|
+
throw new Error(`${name} must start with "/"`);
|
|
26
|
+
if (s.startsWith("//"))
|
|
27
|
+
throw new Error(`${name} must not start with "//"`);
|
|
28
|
+
if (s.includes("://"))
|
|
29
|
+
throw new Error(`${name} must not include scheme/host`);
|
|
30
|
+
if (s.includes("\\"))
|
|
31
|
+
throw new Error(`${name} must not contain backslash`);
|
|
32
|
+
if (/[\s\u0000-\u001f\u007f]/.test(s))
|
|
33
|
+
throw new Error(`${name} must not contain whitespace or control characters`);
|
|
34
|
+
if (/[<>"'`]/.test(s))
|
|
35
|
+
throw new Error(`${name} must not contain HTML attribute delimiters`);
|
|
36
|
+
return s;
|
|
37
|
+
}
|
|
16
38
|
function normalizePathList(name, input) {
|
|
17
39
|
const out = [];
|
|
18
40
|
if (input == null || input.length === 0)
|
|
@@ -116,13 +138,9 @@ export function createProxyServiceWorkerScript(opts = {}) {
|
|
|
116
138
|
}
|
|
117
139
|
}
|
|
118
140
|
else {
|
|
119
|
-
|
|
120
|
-
"scriptUrl" in injectHTML && typeof injectHTML.scriptUrl === "string"
|
|
121
|
-
? injectHTML.scriptUrl.trim()
|
|
122
|
-
: "";
|
|
123
|
-
if (injectScriptUrl === "") {
|
|
141
|
+
if (!("scriptUrl" in injectHTML))
|
|
124
142
|
throw new Error("injectHTML.scriptUrl must be non-empty");
|
|
125
|
-
|
|
143
|
+
injectScriptUrl = normalizeRootRelativeScriptURL("injectHTML.scriptUrl", injectHTML.scriptUrl);
|
|
126
144
|
}
|
|
127
145
|
}
|
|
128
146
|
return `// Generated by @floegence/flowersec-core/proxy
|
|
@@ -315,16 +333,16 @@ function injectBootstrap(html) {
|
|
|
315
333
|
} else if (INJECT_MODE === "external_module") {
|
|
316
334
|
snippet =
|
|
317
335
|
'<script type="module" src="' +
|
|
318
|
-
INJECT_SCRIPT_URL +
|
|
336
|
+
escapeHTMLAttributeValue(INJECT_SCRIPT_URL) +
|
|
319
337
|
'"' +
|
|
320
|
-
(RUNTIME_GLOBAL ? ' data-flowersec-runtime-global="' + RUNTIME_GLOBAL + '"' : "") +
|
|
338
|
+
(RUNTIME_GLOBAL ? ' data-flowersec-runtime-global="' + escapeHTMLAttributeValue(RUNTIME_GLOBAL) + '"' : "") +
|
|
321
339
|
"></script>";
|
|
322
340
|
} else if (INJECT_MODE === "external_script") {
|
|
323
341
|
snippet =
|
|
324
342
|
'<script src="' +
|
|
325
|
-
INJECT_SCRIPT_URL +
|
|
343
|
+
escapeHTMLAttributeValue(INJECT_SCRIPT_URL) +
|
|
326
344
|
'"' +
|
|
327
|
-
(RUNTIME_GLOBAL ? ' data-flowersec-runtime-global="' + RUNTIME_GLOBAL + '"' : "") +
|
|
345
|
+
(RUNTIME_GLOBAL ? ' data-flowersec-runtime-global="' + escapeHTMLAttributeValue(RUNTIME_GLOBAL) + '"' : "") +
|
|
328
346
|
"></script>";
|
|
329
347
|
}
|
|
330
348
|
|
|
@@ -341,6 +359,21 @@ function injectBootstrap(html) {
|
|
|
341
359
|
return snippet + html;
|
|
342
360
|
}
|
|
343
361
|
|
|
362
|
+
function escapeHTMLAttributeValue(value) {
|
|
363
|
+
return String(value).replace(/[&<>"'\`=]/g, (ch) => {
|
|
364
|
+
switch (ch) {
|
|
365
|
+
case "&": return "&";
|
|
366
|
+
case "<": return "<";
|
|
367
|
+
case ">": return ">";
|
|
368
|
+
case '"': return """;
|
|
369
|
+
case "'": return "'";
|
|
370
|
+
case "\`": return "`";
|
|
371
|
+
case "=": return "=";
|
|
372
|
+
default: return ch;
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
344
377
|
self.addEventListener("fetch", (event) => {
|
|
345
378
|
const url = new URL(event.request.url);
|
|
346
379
|
|