more like untrustedtypes

This commit is contained in:
velzie 2024-07-14 19:51:28 -04:00
parent 92651ed66b
commit 6eb9b6f12c
No known key found for this signature in database
GPG key ID: 048413F95F0DDE1F
5 changed files with 48 additions and 45 deletions

View file

@ -51,11 +51,6 @@ for (const attr of attrs) {
if (/nonce|integrity|csp/.test(attr)) { if (/nonce|integrity|csp/.test(attr)) {
return; return;
} else if (/src|href|data|action|formaction/.test(attr)) { } else if (/src|href|data|action|formaction/.test(attr)) {
// @ts-expect-error
if (value instanceof TrustedScriptURL) {
return;
}
value = encodeUrl(value); value = encodeUrl(value);
} else if (attr === "srcdoc") { } else if (attr === "srcdoc") {
value = rewriteHtml(value); value = rewriteHtml(value);
@ -115,17 +110,12 @@ const innerHTML = Object.getOwnPropertyDescriptor(
Object.defineProperty(Element.prototype, "innerHTML", { Object.defineProperty(Element.prototype, "innerHTML", {
set(value) { set(value) {
// @ts-expect-error
if ( if (
this instanceof HTMLScriptElement && this instanceof HTMLScriptElement
!(value instanceof TrustedScript)
) { ) {
value = rewriteJs(value); value = rewriteJs(value);
} else if (this instanceof HTMLStyleElement) { } else if (this instanceof HTMLStyleElement) {
value = rewriteCss(value); value = rewriteCss(value);
// @ts-expect-error
} else if (!(value instanceof TrustedHTML)) {
value = rewriteHtml(value);
} }
return innerHTML.set.call(this, value); return innerHTML.set.call(this, value);

View file

@ -1,32 +1,40 @@
import { rewriteHtml, rewriteJs, encodeUrl } from "./shared"; // import { rewriteHtml, rewriteJs, encodeUrl } from "./shared";
// @ts-expect-error // trustedTypes.createPolicy = new Proxy(trustedTypes.createPolicy, {
trustedTypes.createPolicy = new Proxy(trustedTypes.createPolicy, { // apply(target, thisArg, argArray) {
apply(target, thisArg, argArray) { // if (argArray[1].createHTML) {
if (argArray[1].createHTML) { // argArray[1].createHTML = new Proxy(argArray[1].createHTML, {
argArray[1].createHTML = new Proxy(argArray[1].createHTML, { // apply(target1, thisArg1, argArray1) {
apply(target1, thisArg1, argArray1) { // return rewriteHtml(target1(...argArray1));
return rewriteHtml(target1(...argArray1)); // },
}, // });
}); // }
} //
// if (argArray[1].createScript) {
// argArray[1].createScript = new Proxy(argArray[1].createScript, {
// apply(target1, thisArg1, argArray1) {
// return rewriteJs(target1(...argArray1));
// },
// });
// }
//
// if (argArray[1].createScriptURL) {
// argArray[1].createScriptURL = new Proxy(argArray[1].createScriptURL, {
// apply(target1, thisArg1, argArray1) {
// return encodeUrl(target1(...argArray1));
// },
// });
// }
//
// return Reflect.apply(target, thisArg, argArray);
// },
// });
if (argArray[1].createScript) { //@ts-nocheck
argArray[1].createScript = new Proxy(argArray[1].createScript, { delete window.TrustedHTML;
apply(target1, thisArg1, argArray1) { delete window.TrustedScript;
return rewriteJs(target1(...argArray1)); delete window.TrustedScriptURL;
}, delete window.TrustedTypePolicy;
}); delete window.TrustedTypePolicyFactory;
} delete window.trustedTypes;
if (argArray[1].createScriptURL) {
argArray[1].createScriptURL = new Proxy(argArray[1].createScriptURL, {
apply(target1, thisArg1, argArray1) {
return encodeUrl(target1(...argArray1));
},
});
}
return Reflect.apply(target, thisArg, argArray);
},
});

View file

@ -37,7 +37,7 @@ function traverseParsedHtml(node, origin?: URL) {
} }
/* url attributes */ /* url attributes */
for (const urlAttr of ["src", "href", "data", "action", "formaction"]) { for (const urlAttr of ["src", "href", "action", "formaction"]) {
if (hasAttrib(node, urlAttr) && !isScramjetFile(node.attribs[urlAttr])) { if (hasAttrib(node, urlAttr) && !isScramjetFile(node.attribs[urlAttr])) {
const value = node.attribs[urlAttr]; const value = node.attribs[urlAttr];
node.attribs[`data-${urlAttr}`] = value; node.attribs[`data-${urlAttr}`] = value;
@ -67,8 +67,12 @@ function traverseParsedHtml(node, origin?: URL) {
node.attribs.type node.attribs.type
) && ) &&
node.children[0] !== undefined node.children[0] !== undefined
) ) {
node.children[0].data = rewriteJs(node.children[0].data, origin); let js = node.children[0].data
const htmlcomment = /<!--[\s\S]*?-->/g;
js = js.replace(htmlcomment, "");
node.children[0].data = rewriteJs(js, origin);
}
if (node.name === "meta" && hasAttrib(node, "http-equiv")) { if (node.name === "meta" && hasAttrib(node, "http-equiv")) {
if (node.attribs["http-equiv"] === "content-security-policy") { if (node.attribs["http-equiv"] === "content-security-policy") {
node = {}; node = {};

View file

@ -17,8 +17,6 @@ import * as ESTree from "estree";
// parent // parent
export function rewriteJs(js: string, origin?: URL) { export function rewriteJs(js: string, origin?: URL) {
const htmlcomment = /<!--[\s\S]*?-->/g;
js = js.replace(htmlcomment, "");
try { try {
const ast = parseModule(js, { const ast = parseModule(js, {
module: true, module: true,

View file

@ -27,6 +27,9 @@ export function encodeUrl(url: string | URL, origin?: URL) {
); );
} }
// is this the correct behavior?
if (!url) url = origin.href;
if (url.startsWith("javascript:")) { if (url.startsWith("javascript:")) {
return "javascript:" + rewriteJs(url.slice("javascript:".length)); return "javascript:" + rewriteJs(url.slice("javascript:".length));
} else if (/^(#|mailto|about|data)/.test(url)) { } else if (/^(#|mailto|about|data)/.test(url)) {