@instructure/platform-sanitize 0.3.14 → 0.3.15
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/index.js +80 -65
- package/dist/sanitizeHtml.d.ts.map +1 -1
- package/dist/sanitizeUrl.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
const
|
|
1
|
+
import u from "dompurify";
|
|
2
|
+
const m = /* @__PURE__ */ new Set([
|
|
3
3
|
// layout
|
|
4
4
|
"display",
|
|
5
5
|
"float",
|
|
@@ -236,7 +236,7 @@ const p = /* @__PURE__ */ new Set([
|
|
|
236
236
|
"caret-color",
|
|
237
237
|
"accent-color",
|
|
238
238
|
"appearance"
|
|
239
|
-
]),
|
|
239
|
+
]), w = /* @__PURE__ */ new Set([
|
|
240
240
|
"src",
|
|
241
241
|
"href",
|
|
242
242
|
"action",
|
|
@@ -247,7 +247,7 @@ const p = /* @__PURE__ */ new Set([
|
|
|
247
247
|
"cite",
|
|
248
248
|
"longdesc",
|
|
249
249
|
"xlink:href"
|
|
250
|
-
]),
|
|
250
|
+
]), h = [
|
|
251
251
|
"background",
|
|
252
252
|
"background-image",
|
|
253
253
|
"list-style",
|
|
@@ -256,7 +256,7 @@ const p = /* @__PURE__ */ new Set([
|
|
|
256
256
|
// content: url(...) triggers an HTTP GET even on non-pseudo elements in some
|
|
257
257
|
// browsers; strip it as defense-in-depth against tracking-pixel exfiltration.
|
|
258
258
|
"content"
|
|
259
|
-
],
|
|
259
|
+
], y = /url\s*\(\s*['"]?(?:[a-z][a-z0-9+\-.]*:|\/\/)/i, k = /* @__PURE__ */ new Set([
|
|
260
260
|
"allow-downloads",
|
|
261
261
|
"allow-forms",
|
|
262
262
|
"allow-modals",
|
|
@@ -269,7 +269,7 @@ const p = /* @__PURE__ */ new Set([
|
|
|
269
269
|
"allow-scripts",
|
|
270
270
|
"allow-storage-access-by-user-activation",
|
|
271
271
|
"allow-top-navigation-by-user-activation"
|
|
272
|
-
]),
|
|
272
|
+
]), f = {
|
|
273
273
|
ADD_TAGS: ["iframe"],
|
|
274
274
|
ADD_ATTR: [
|
|
275
275
|
"allowfullscreen",
|
|
@@ -312,17 +312,17 @@ const p = /* @__PURE__ */ new Set([
|
|
|
312
312
|
// confusion attacks where fragments like <svg> could influence parse context.
|
|
313
313
|
FORCE_BODY: !0
|
|
314
314
|
};
|
|
315
|
-
let
|
|
316
|
-
function
|
|
317
|
-
return
|
|
318
|
-
if (!(
|
|
319
|
-
const
|
|
320
|
-
for (let n = 0; n <
|
|
321
|
-
const
|
|
322
|
-
|
|
315
|
+
let a = null;
|
|
316
|
+
function A() {
|
|
317
|
+
return a || (a = typeof u == "function" ? u(window) : u, a.addHook("afterSanitizeAttributes", (e) => {
|
|
318
|
+
if (!(e instanceof Element) || !e.hasAttribute("style")) return;
|
|
319
|
+
const r = e.style, t = [];
|
|
320
|
+
for (let n = 0; n < r.length; n++) {
|
|
321
|
+
const i = r.item(n);
|
|
322
|
+
m.has(i) || t.push(i);
|
|
323
323
|
}
|
|
324
|
-
for (const n of
|
|
325
|
-
const
|
|
324
|
+
for (const n of t) r.removeProperty(n);
|
|
325
|
+
const o = /* @__PURE__ */ new Set([
|
|
326
326
|
"static",
|
|
327
327
|
"relative",
|
|
328
328
|
"absolute",
|
|
@@ -331,39 +331,54 @@ function k() {
|
|
|
331
331
|
"unset",
|
|
332
332
|
"revert",
|
|
333
333
|
"revert-layer"
|
|
334
|
-
]), s =
|
|
335
|
-
s && !
|
|
336
|
-
for (const n of
|
|
337
|
-
const
|
|
338
|
-
|
|
334
|
+
]), s = r.getPropertyValue("position").trim().toLowerCase();
|
|
335
|
+
s && !o.has(s) && r.removeProperty("position");
|
|
336
|
+
for (const n of h) {
|
|
337
|
+
const i = r.getPropertyValue(n);
|
|
338
|
+
i && y.test(i) && r.removeProperty(n);
|
|
339
339
|
}
|
|
340
|
-
|
|
341
|
-
}),
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
if (
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
340
|
+
r.length === 0 && e.removeAttribute("style");
|
|
341
|
+
}), a.addHook("uponSanitizeAttribute", (e, r) => {
|
|
342
|
+
if (!w.has(r.attrName)) return;
|
|
343
|
+
const t = r.attrValue;
|
|
344
|
+
/^\s*\/\//.test(t) ? (r.attrValue = t.trimStart().replace(/^\/\//, "https://"), r.keepAttr = !0) : /^\s*\\/.test(t) && (r.keepAttr = !1);
|
|
345
|
+
}), a.addHook("afterSanitizeAttributes", (e) => {
|
|
346
|
+
if (!(e instanceof Element) || !e.hasAttribute("srcset")) return;
|
|
347
|
+
const t = (e.getAttribute("srcset") ?? "").split(","), o = (i) => i.trim().split(/\s+/)[0];
|
|
348
|
+
if (t.some((i) => /^\s*\\/.test(o(i)))) {
|
|
349
|
+
e.removeAttribute("srcset");
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
let s = !1;
|
|
353
|
+
const n = t.map((i) => {
|
|
354
|
+
const l = o(i);
|
|
355
|
+
if (!l.startsWith("//")) return i;
|
|
356
|
+
s = !0;
|
|
357
|
+
const d = i.indexOf(l);
|
|
358
|
+
return i.slice(0, d) + "https://" + l.slice(2) + i.slice(d + l.length);
|
|
359
|
+
});
|
|
360
|
+
s && e.setAttribute("srcset", n.join(","));
|
|
361
|
+
}), a.addHook("afterSanitizeAttributes", (e) => {
|
|
362
|
+
var o;
|
|
363
|
+
if (!(e instanceof Element) || e.tagName !== "A" && e.tagName !== "AREA" || ((o = e.getAttribute("target")) == null ? void 0 : o.toLowerCase()) !== "_blank") return;
|
|
364
|
+
const r = e.getAttribute("rel") ?? "", t = new Set(r.split(/\s+/).filter(Boolean));
|
|
365
|
+
t.add("noopener"), e.setAttribute("rel", [...t].join(" "));
|
|
366
|
+
}), a.addHook("afterSanitizeAttributes", (e) => {
|
|
367
|
+
if (!(e instanceof Element) || e.tagName !== "IFRAME" || !e.hasAttribute("sandbox")) return;
|
|
368
|
+
const t = (e.getAttribute("sandbox") ?? "").toLowerCase().split(/\s+/).filter(Boolean), o = t.filter((s) => k.has(s));
|
|
369
|
+
o.length !== t.length && e.setAttribute("sandbox", o.join(" "));
|
|
370
|
+
}), a);
|
|
356
371
|
}
|
|
357
|
-
function
|
|
372
|
+
function v(e, r) {
|
|
358
373
|
if (typeof window > "u")
|
|
359
374
|
throw new Error("sanitizeHtml requires a DOM environment (window is not defined)");
|
|
360
|
-
const
|
|
361
|
-
return
|
|
375
|
+
const t = r != null && r.allowFormAttributeNames ? { ...f, SANITIZE_DOM: !1 } : f;
|
|
376
|
+
return A().sanitize(e ?? "", t);
|
|
362
377
|
}
|
|
363
|
-
const
|
|
378
|
+
const p = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]), c = "http://platform-sanitize.invalid/", g = /^\s*\/\//, b = (
|
|
364
379
|
// oxlint-disable-next-line no-control-regex -- intentional security guard
|
|
365
380
|
/^[\u0000-\u0020\u007F-\u00A0\u2000-\u200F\u2028\u2029\u202F\u205F\u2060\u3000\uFEFF]*(?:javascript|data|vbscript|file):/i
|
|
366
|
-
),
|
|
381
|
+
), x = {
|
|
367
382
|
colon: ":",
|
|
368
383
|
// javascript:alert(1) → javascript:alert(1)
|
|
369
384
|
sol: "/",
|
|
@@ -376,49 +391,49 @@ const f = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]), l = "
|
|
|
376
391
|
`
|
|
377
392
|
// java
script:
|
|
378
393
|
};
|
|
379
|
-
function E(
|
|
380
|
-
return
|
|
381
|
-
const
|
|
382
|
-
if (!Number.isFinite(
|
|
394
|
+
function E(e) {
|
|
395
|
+
return e.replace(/&#(\d+);/g, (r, t) => {
|
|
396
|
+
const o = Number(t);
|
|
397
|
+
if (!Number.isFinite(o) || o < 0 || o > 1114111) return "";
|
|
383
398
|
try {
|
|
384
|
-
return String.fromCodePoint(
|
|
399
|
+
return String.fromCodePoint(o);
|
|
385
400
|
} catch {
|
|
386
401
|
return "";
|
|
387
402
|
}
|
|
388
|
-
}).replace(/&#x([\da-f]+);/gi, (
|
|
389
|
-
const
|
|
390
|
-
if (!Number.isFinite(
|
|
403
|
+
}).replace(/&#x([\da-f]+);/gi, (r, t) => {
|
|
404
|
+
const o = parseInt(t, 16);
|
|
405
|
+
if (!Number.isFinite(o) || o < 0 || o > 1114111) return "";
|
|
391
406
|
try {
|
|
392
|
-
return String.fromCodePoint(
|
|
407
|
+
return String.fromCodePoint(o);
|
|
393
408
|
} catch {
|
|
394
409
|
return "";
|
|
395
410
|
}
|
|
396
|
-
}).replace(/&([A-Za-z][A-Za-z0-9]*);/g, (
|
|
411
|
+
}).replace(/&([A-Za-z][A-Za-z0-9]*);/g, (r, t) => x[t] ?? r);
|
|
397
412
|
}
|
|
398
|
-
function
|
|
399
|
-
if (!
|
|
400
|
-
const
|
|
401
|
-
if (
|
|
402
|
-
if (/&[#A-Za-z]/.test(
|
|
403
|
-
const
|
|
404
|
-
if (
|
|
413
|
+
function R(e) {
|
|
414
|
+
if (!e || !e.trim()) return "about:blank";
|
|
415
|
+
const r = e.replace(/\\/g, "/");
|
|
416
|
+
if (g.test(r) || b.test(r)) return "about:blank";
|
|
417
|
+
if (/&[#A-Za-z]/.test(r)) {
|
|
418
|
+
const t = E(r);
|
|
419
|
+
if (g.test(t) || b.test(t))
|
|
405
420
|
return "about:blank";
|
|
406
421
|
try {
|
|
407
|
-
const
|
|
408
|
-
if (!
|
|
422
|
+
const o = new URL(t, c);
|
|
423
|
+
if (!o.href.startsWith(c) && !p.has(o.protocol))
|
|
409
424
|
return "about:blank";
|
|
410
425
|
} catch {
|
|
411
426
|
return "about:blank";
|
|
412
427
|
}
|
|
413
428
|
}
|
|
414
429
|
try {
|
|
415
|
-
const
|
|
416
|
-
return !
|
|
430
|
+
const t = new URL(r, c);
|
|
431
|
+
return !p.has(t.protocol) || (t.protocol === "http:" || t.protocol === "https:") && (t.username || t.password) ? "about:blank" : t.href.startsWith(c) ? e : r.replace(/[\x00-\x1F\u2028\u2029]/g, "").replace(/%250[9ad]/gi, "").replace(/%0[9ad]/gi, "");
|
|
417
432
|
} catch {
|
|
418
433
|
return "about:blank";
|
|
419
434
|
}
|
|
420
435
|
}
|
|
421
436
|
export {
|
|
422
|
-
|
|
423
|
-
|
|
437
|
+
v as sanitizeHtml,
|
|
438
|
+
R as sanitizeUrl
|
|
424
439
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitizeHtml.d.ts","sourceRoot":"","sources":["../src/sanitizeHtml.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sanitizeHtml.d.ts","sourceRoot":"","sources":["../src/sanitizeHtml.ts"],"names":[],"mappings":"AA6cA,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,OAAO,CAAC,EAAE;IAAE,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9C,MAAM,CASR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitizeUrl.d.ts","sourceRoot":"","sources":["../src/sanitizeUrl.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sanitizeUrl.d.ts","sourceRoot":"","sources":["../src/sanitizeUrl.ts"],"names":[],"mappings":"AAsFA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAwDlE"}
|