what-core 0.6.5 → 0.6.7
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/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/hooks.d.ts +25 -0
- package/package.json +3 -1
- package/src/dom.js +9 -0
- package/src/render.js +6 -20
- package/src/security.js +63 -0
package/dist/render.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",
|
|
@@ -889,6 +936,13 @@ function applyProps(el, newProps, oldProps, isSvg) {
|
|
|
889
936
|
}
|
|
890
937
|
}
|
|
891
938
|
function setProp(el, key, value, isSvg) {
|
|
939
|
+
if (!isSafeUrlAttributeValue(key, value)) {
|
|
940
|
+
if (typeof console !== "undefined") {
|
|
941
|
+
console.warn(`[what] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
942
|
+
}
|
|
943
|
+
el.removeAttribute(getDomAttributeName(key));
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
892
946
|
if (typeof value === "function" && !(key.startsWith("on") && key.length > 2) && key !== "ref") {
|
|
893
947
|
if (!el._propEffects) el._propEffects = {};
|
|
894
948
|
if (el._propEffects[key]) {
|
|
@@ -1180,15 +1234,6 @@ function _$createComponent(Component, props, children) {
|
|
|
1180
1234
|
}
|
|
1181
1235
|
return createDOM({ tag: Component, props: props || {}, children: children || [], key: null, _vnode: true });
|
|
1182
1236
|
}
|
|
1183
|
-
var URL_ATTRS = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "formAction"]);
|
|
1184
|
-
function isSafeUrl(url) {
|
|
1185
|
-
if (typeof url !== "string") return true;
|
|
1186
|
-
const normalized = url.trim().replace(/[\s\x00-\x1f]/g, "").toLowerCase();
|
|
1187
|
-
if (normalized.startsWith("javascript:")) return false;
|
|
1188
|
-
if (normalized.startsWith("data:")) return false;
|
|
1189
|
-
if (normalized.startsWith("vbscript:")) return false;
|
|
1190
|
-
return true;
|
|
1191
|
-
}
|
|
1192
1237
|
var TABLE_WRAPPERS = {
|
|
1193
1238
|
tr: { depth: 2, wrap: "<table><tbody>", unwrap: "</tbody></table>" },
|
|
1194
1239
|
td: { depth: 3, wrap: "<table><tbody><tr>", unwrap: "</tr></tbody></table>" },
|
|
@@ -1879,13 +1924,12 @@ function setProp2(el, key, value) {
|
|
|
1879
1924
|
return;
|
|
1880
1925
|
}
|
|
1881
1926
|
if (key === "key") return;
|
|
1882
|
-
if (
|
|
1883
|
-
if (
|
|
1884
|
-
|
|
1885
|
-
console.warn(`[what] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
1886
|
-
}
|
|
1887
|
-
return;
|
|
1927
|
+
if (!isSafeUrlAttributeValue(key, value)) {
|
|
1928
|
+
if (typeof console !== "undefined") {
|
|
1929
|
+
console.warn(`[what] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
1888
1930
|
}
|
|
1931
|
+
el.removeAttribute(getDomAttributeName(key));
|
|
1932
|
+
return;
|
|
1889
1933
|
}
|
|
1890
1934
|
if (key === "class" || key === "className") {
|
|
1891
1935
|
el.className = value || "";
|