@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 CHANGED
@@ -1,5 +1,5 @@
1
- import c from "dompurify";
2
- const p = /* @__PURE__ */ new Set([
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
- ]), m = /* @__PURE__ */ new Set([
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
- ]), u = /^\s*(\/\/|\\)/, w = [
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
- ], h = /url\s*\(\s*['"]?(?:[a-z][a-z0-9+\-.]*:|\/\/)/i, y = /* @__PURE__ */ new Set([
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
- ]), d = {
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 i = null;
316
- function k() {
317
- return i || (i = typeof c == "function" ? c(window) : c, i.addHook("afterSanitizeAttributes", (t) => {
318
- if (!(t instanceof Element) || !t.hasAttribute("style")) return;
319
- const e = t.style, o = [];
320
- for (let n = 0; n < e.length; n++) {
321
- const a = e.item(n);
322
- p.has(a) || o.push(a);
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 o) e.removeProperty(n);
325
- const r = /* @__PURE__ */ new Set([
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 = e.getPropertyValue("position").trim().toLowerCase();
335
- s && !r.has(s) && e.removeProperty("position");
336
- for (const n of w) {
337
- const a = e.getPropertyValue(n);
338
- a && h.test(a) && e.removeProperty(n);
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
- e.length === 0 && t.removeAttribute("style");
341
- }), i.addHook("uponSanitizeAttribute", (t, e) => {
342
- m.has(e.attrName) && u.test(e.attrValue) && (e.keepAttr = !1);
343
- }), i.addHook("afterSanitizeAttributes", (t) => {
344
- if (!(t instanceof Element) || !t.hasAttribute("srcset")) return;
345
- (t.getAttribute("srcset") ?? "").split(",").map((r) => r.trim().split(/\s+/)[0]).some((r) => u.test(r)) && t.removeAttribute("srcset");
346
- }), i.addHook("afterSanitizeAttributes", (t) => {
347
- var r;
348
- if (!(t instanceof Element) || t.tagName !== "A" && t.tagName !== "AREA" || ((r = t.getAttribute("target")) == null ? void 0 : r.toLowerCase()) !== "_blank") return;
349
- const e = t.getAttribute("rel") ?? "", o = new Set(e.split(/\s+/).filter(Boolean));
350
- o.add("noopener"), t.setAttribute("rel", [...o].join(" "));
351
- }), i.addHook("afterSanitizeAttributes", (t) => {
352
- if (!(t instanceof Element) || t.tagName !== "IFRAME" || !t.hasAttribute("sandbox")) return;
353
- const o = (t.getAttribute("sandbox") ?? "").toLowerCase().split(/\s+/).filter(Boolean), r = o.filter((s) => y.has(s));
354
- r.length !== o.length && t.setAttribute("sandbox", r.join(" "));
355
- }), i);
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 R(t, e) {
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 o = e != null && e.allowFormAttributeNames ? { ...d, SANITIZE_DOM: !1 } : d;
361
- return k().sanitize(t ?? "", o);
375
+ const t = r != null && r.allowFormAttributeNames ? { ...f, SANITIZE_DOM: !1 } : f;
376
+ return A().sanitize(e ?? "", t);
362
377
  }
363
- const f = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]), l = "http://platform-sanitize.invalid/", b = /^\s*\/\//, g = (
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
- ), A = {
381
+ ), x = {
367
382
  colon: ":",
368
383
  // javascript&colon;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&NewLine;script:
378
393
  };
379
- function E(t) {
380
- return t.replace(/&#(\d+);/g, (e, o) => {
381
- const r = Number(o);
382
- if (!Number.isFinite(r) || r < 0 || r > 1114111) return "";
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(r);
399
+ return String.fromCodePoint(o);
385
400
  } catch {
386
401
  return "";
387
402
  }
388
- }).replace(/&#x([\da-f]+);/gi, (e, o) => {
389
- const r = parseInt(o, 16);
390
- if (!Number.isFinite(r) || r < 0 || r > 1114111) return "";
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(r);
407
+ return String.fromCodePoint(o);
393
408
  } catch {
394
409
  return "";
395
410
  }
396
- }).replace(/&([A-Za-z][A-Za-z0-9]*);/g, (e, o) => A[o] ?? e);
411
+ }).replace(/&([A-Za-z][A-Za-z0-9]*);/g, (r, t) => x[t] ?? r);
397
412
  }
398
- function S(t) {
399
- if (!t || !t.trim()) return "about:blank";
400
- const e = t.replace(/\\/g, "/");
401
- if (b.test(e) || g.test(e)) return "about:blank";
402
- if (/&[#A-Za-z]/.test(e)) {
403
- const o = E(e);
404
- if (b.test(o) || g.test(o))
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 r = new URL(o, l);
408
- if (!r.href.startsWith(l) && !f.has(r.protocol))
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 o = new URL(e, l);
416
- return !f.has(o.protocol) || (o.protocol === "http:" || o.protocol === "https:") && (o.username || o.password) ? "about:blank" : o.href.startsWith(l) ? t : e.replace(/[\x00-\x1F\u2028\u2029]/g, "").replace(/%250[9ad]/gi, "").replace(/%0[9ad]/gi, "");
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
- R as sanitizeHtml,
423
- S as sanitizeUrl
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":"AAybA,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
+ {"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":"AAoFA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAwDlE"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/platform-sanitize",
3
- "version": "0.3.14",
3
+ "version": "0.3.15",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",