what-core 0.6.3 → 0.6.6
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/compiler.d.ts +1 -1
- package/dist/compiler.js +59 -15
- package/dist/compiler.js.map +3 -3
- package/dist/compiler.min.js +1 -1
- package/dist/compiler.min.js.map +4 -4
- package/dist/index.js +59 -15
- package/dist/index.js.map +3 -3
- package/dist/index.min.js +5 -5
- package/dist/index.min.js.map +4 -4
- package/dist/render.js +59 -15
- package/dist/render.js.map +3 -3
- package/dist/render.min.js +2 -2
- package/dist/render.min.js.map +4 -4
- package/dist/testing.js +54 -0
- package/dist/testing.js.map +3 -3
- package/dist/testing.min.js +1 -1
- package/dist/testing.min.js.map +4 -4
- package/jsx-runtime.d.ts +2 -2
- package/package.json +1 -1
- package/render.d.ts +1 -1
- package/src/dom.js +9 -0
- package/src/render.js +6 -20
- package/src/security.js +63 -0
- package/testing.d.ts +1 -1
package/compiler.d.ts
CHANGED
package/dist/compiler.js
CHANGED
|
@@ -412,6 +412,53 @@ function _setComponentRef(fn) {
|
|
|
412
412
|
_getCurrentComponentRef = fn;
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
+
// packages/core/src/security.js
|
|
416
|
+
var URL_ATTRS = /* @__PURE__ */ new Set([
|
|
417
|
+
"href",
|
|
418
|
+
"src",
|
|
419
|
+
"action",
|
|
420
|
+
"formaction",
|
|
421
|
+
"poster",
|
|
422
|
+
"cite",
|
|
423
|
+
"background",
|
|
424
|
+
"xlink:href"
|
|
425
|
+
]);
|
|
426
|
+
var URL_LIST_ATTRS = /* @__PURE__ */ new Set(["srcset"]);
|
|
427
|
+
function normalizeAttrName(name) {
|
|
428
|
+
return String(name).toLowerCase();
|
|
429
|
+
}
|
|
430
|
+
function normalizeUrlForProtocolCheck(url) {
|
|
431
|
+
return String(url).trim().replace(/[\s\x00-\x1f\x7f]/g, "").toLowerCase();
|
|
432
|
+
}
|
|
433
|
+
function isSafeUrlValue(value) {
|
|
434
|
+
if (typeof value !== "string") return true;
|
|
435
|
+
const normalized = normalizeUrlForProtocolCheck(value);
|
|
436
|
+
return !(normalized.startsWith("javascript:") || normalized.startsWith("data:") || normalized.startsWith("vbscript:"));
|
|
437
|
+
}
|
|
438
|
+
function isSafeSrcsetValue(value) {
|
|
439
|
+
if (typeof value !== "string") return true;
|
|
440
|
+
return value.split(",").every((candidate) => {
|
|
441
|
+
const url = candidate.trim().split(/\s+/, 1)[0] || "";
|
|
442
|
+
return url === "" || isSafeUrlValue(url);
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
function isUrlAttribute(name) {
|
|
446
|
+
return URL_ATTRS.has(normalizeAttrName(name));
|
|
447
|
+
}
|
|
448
|
+
function isUrlListAttribute(name) {
|
|
449
|
+
return URL_LIST_ATTRS.has(normalizeAttrName(name));
|
|
450
|
+
}
|
|
451
|
+
function isSafeUrlAttributeValue(name, value) {
|
|
452
|
+
if (isUrlListAttribute(name)) return isSafeSrcsetValue(value);
|
|
453
|
+
if (isUrlAttribute(name)) return isSafeUrlValue(value);
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
function getDomAttributeName(name) {
|
|
457
|
+
if (name === "className") return "class";
|
|
458
|
+
if (name === "htmlFor") return "for";
|
|
459
|
+
return normalizeAttrName(name) === "formaction" ? "formaction" : name;
|
|
460
|
+
}
|
|
461
|
+
|
|
415
462
|
// packages/core/src/dom.js
|
|
416
463
|
var SVG_ELEMENTS = /* @__PURE__ */ new Set([
|
|
417
464
|
"svg",
|
|
@@ -886,6 +933,13 @@ function applyProps(el, newProps, oldProps, isSvg) {
|
|
|
886
933
|
}
|
|
887
934
|
}
|
|
888
935
|
function setProp(el, key, value, isSvg) {
|
|
936
|
+
if (!isSafeUrlAttributeValue(key, value)) {
|
|
937
|
+
if (typeof console !== "undefined") {
|
|
938
|
+
console.warn(`[what] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
939
|
+
}
|
|
940
|
+
el.removeAttribute(getDomAttributeName(key));
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
889
943
|
if (typeof value === "function" && !(key.startsWith("on") && key.length > 2) && key !== "ref") {
|
|
890
944
|
if (!el._propEffects) el._propEffects = {};
|
|
891
945
|
if (el._propEffects[key]) {
|
|
@@ -998,15 +1052,6 @@ function _$createComponent(Component, props, children) {
|
|
|
998
1052
|
}
|
|
999
1053
|
return createDOM({ tag: Component, props: props || {}, children: children || [], key: null, _vnode: true });
|
|
1000
1054
|
}
|
|
1001
|
-
var URL_ATTRS = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "formAction"]);
|
|
1002
|
-
function isSafeUrl(url) {
|
|
1003
|
-
if (typeof url !== "string") return true;
|
|
1004
|
-
const normalized = url.trim().replace(/[\s\x00-\x1f]/g, "").toLowerCase();
|
|
1005
|
-
if (normalized.startsWith("javascript:")) return false;
|
|
1006
|
-
if (normalized.startsWith("data:")) return false;
|
|
1007
|
-
if (normalized.startsWith("vbscript:")) return false;
|
|
1008
|
-
return true;
|
|
1009
|
-
}
|
|
1010
1055
|
var TABLE_WRAPPERS = {
|
|
1011
1056
|
tr: { depth: 2, wrap: "<table><tbody>", unwrap: "</tbody></table>" },
|
|
1012
1057
|
td: { depth: 3, wrap: "<table><tbody><tr>", unwrap: "</tr></tbody></table>" },
|
|
@@ -1697,13 +1742,12 @@ function setProp2(el, key, value) {
|
|
|
1697
1742
|
return;
|
|
1698
1743
|
}
|
|
1699
1744
|
if (key === "key") return;
|
|
1700
|
-
if (
|
|
1701
|
-
if (
|
|
1702
|
-
|
|
1703
|
-
console.warn(`[what] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
1704
|
-
}
|
|
1705
|
-
return;
|
|
1745
|
+
if (!isSafeUrlAttributeValue(key, value)) {
|
|
1746
|
+
if (typeof console !== "undefined") {
|
|
1747
|
+
console.warn(`[what] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
1706
1748
|
}
|
|
1749
|
+
el.removeAttribute(getDomAttributeName(key));
|
|
1750
|
+
return;
|
|
1707
1751
|
}
|
|
1708
1752
|
if (key === "class" || key === "className") {
|
|
1709
1753
|
el.className = value || "";
|