Skip to content

Commit 0bbe5e4

Browse files
committed
Better injection
1 parent bf5c084 commit 0bbe5e4

2 files changed

Lines changed: 140 additions & 16 deletions

File tree

Public/utils/gm_core.js

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,29 @@
141141
injectScriptTag(src) {
142142
return new Promise((resolve, reject) => {
143143
const el = document.createElement("script");
144-
el.src = src;
144+
145+
// Handle Trusted Types enforcement for script URLs
146+
let trustedSrc = src;
147+
if (window.trustedTypes && window.trustedTypes.createPolicy) {
148+
try {
149+
if (!window.__ctTrustedScriptURLPolicy) {
150+
window.__ctTrustedScriptURLPolicy = window.trustedTypes.createPolicy(
151+
"codetweak",
152+
{
153+
createScriptURL: (input) => input,
154+
}
155+
);
156+
}
157+
trustedSrc = window.__ctTrustedScriptURLPolicy.createScriptURL(src);
158+
} catch (e) {
159+
console.error("Failed to create trusted script URL:", e);
160+
console.warn("Falling back to raw URL.");
161+
// If policy creation failed (likely already exists), fall back to raw URL.
162+
trustedSrc = src;
163+
}
164+
}
165+
166+
el.src = trustedSrc;
145167
el.async = false; // preserve execution order
146168
el.onload = resolve;
147169
el.onerror = () => reject(new Error(`Failed to load script ${src}`));
@@ -268,7 +290,51 @@
268290
async function executeUserScriptWithDependencies(userCode, scriptId, requireUrls, loader) {
269291
try {
270292
await loader.loadScripts(requireUrls);
271-
new Function(userCode)();
293+
const blob = new Blob([userCode], { type: "text/javascript" });
294+
const blobUrl = URL.createObjectURL(blob);
295+
296+
await new Promise((resolve, reject) => {
297+
const scriptEl = document.createElement("script");
298+
299+
// Handle Trusted Types enforcement for script URLs
300+
let trustedSrc = blobUrl;
301+
if (window.trustedTypes && window.trustedTypes.createPolicy) {
302+
try {
303+
if (!window.__ctTrustedScriptURLPolicy) {
304+
window.__ctTrustedScriptURLPolicy = window.trustedTypes.createPolicy(
305+
"codetweak",
306+
{
307+
createScriptURL: (input) => input,
308+
}
309+
);
310+
}
311+
trustedSrc = window.__ctTrustedScriptURLPolicy.createScriptURL(blobUrl);
312+
} catch (e) {
313+
console.error("Failed to create trusted script URL:", e);
314+
console.warn("Falling back to raw URL.");
315+
// If policy creation failed (likely already exists), fall back to raw URL.
316+
trustedSrc = blobUrl;
317+
}
318+
}
319+
320+
scriptEl.src = trustedSrc;
321+
scriptEl.async = false; // maintain order
322+
scriptEl.onload = () => {
323+
URL.revokeObjectURL(blobUrl);
324+
resolve();
325+
};
326+
scriptEl.onerror = (event) => {
327+
URL.revokeObjectURL(blobUrl);
328+
reject(
329+
new Error(
330+
`Failed to execute user script ${scriptId}: ${event?.message || "unknown error"}`
331+
)
332+
);
333+
};
334+
(document.head || document.documentElement || document.body).appendChild(
335+
scriptEl
336+
);
337+
});
272338
} catch (err) {
273339
console.error(`CodeTweak: Error executing user script ${scriptId}:`, err);
274340
}

Public/utils/inject.js

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -405,21 +405,36 @@ class ExternalScriptLoader {
405405
}
406406
}
407407

408-
injectScriptTag(src) {
408+
async injectScriptTag(url) {
409409
return new Promise((resolve, reject) => {
410-
const scriptEl = document.createElement("script");
411-
scriptEl.src = src;
412-
scriptEl.async = false; // Preserve execution order
413-
scriptEl.onload = resolve;
414-
scriptEl.onerror = () =>
415-
reject(new Error(`Failed to load required script: ${src}`));
410+
const script = document.createElement("script");
416411

417-
const target = document.head || document.documentElement;
418-
if (target) {
419-
target.appendChild(scriptEl);
420-
} else {
421-
reject(new Error("No valid target element found for script injection"));
412+
// Trusted Types compliance
413+
let trustedSrc = url;
414+
if (window.trustedTypes && window.trustedTypes.createPolicy) {
415+
try {
416+
if (!window.__ctTrustedScriptURLPolicy) {
417+
window.__ctTrustedScriptURLPolicy = window.trustedTypes.createPolicy(
418+
"codetweak",
419+
{
420+
createScriptURL: (input) => input,
421+
}
422+
);
423+
}
424+
trustedSrc = window.__ctTrustedScriptURLPolicy.createScriptURL(url);
425+
} catch (_e) {
426+
console.error("Failed to create trusted script URL:", _e);
427+
console.warn("Falling back to raw URL.");
428+
// ignore, fall back to raw URL
429+
trustedSrc = url;
430+
}
422431
}
432+
433+
script.src = trustedSrc;
434+
script.async = false; // Preserve execution order
435+
script.onload = resolve;
436+
script.onerror = () => reject(new Error(`Failed to load external script: ${url}`));
437+
(document.head || document.documentElement).appendChild(script);
423438
});
424439
}
425440
}
@@ -553,8 +568,51 @@ async function executeUserScriptWithDependencies(
553568
// Load external dependencies first
554569
await scriptLoader.loadScripts(requiredUrls);
555570

556-
// Execute user script
557-
new Function(userCode)();
571+
// Execute user script using a CSP-compliant blob URL instead of Function()
572+
const blob = new Blob([userCode], { type: "text/javascript" });
573+
const blobUrl = URL.createObjectURL(blob);
574+
575+
await new Promise((resolve, reject) => {
576+
const scriptEl = document.createElement("script");
577+
578+
// Trusted Types compliance for blob URL
579+
let trustedSrc = blobUrl;
580+
if (window.trustedTypes && window.trustedTypes.createPolicy) {
581+
try {
582+
if (!window.__ctTrustedScriptURLPolicy) {
583+
window.__ctTrustedScriptURLPolicy = window.trustedTypes.createPolicy(
584+
"codetweak",
585+
{
586+
createScriptURL: (input) => input,
587+
}
588+
);
589+
}
590+
trustedSrc = window.__ctTrustedScriptURLPolicy.createScriptURL(blobUrl);
591+
} catch (_e) {
592+
console.error("Failed to create trusted script URL:", _e);
593+
console.warn("Falling back to raw URL.");
594+
trustedSrc = blobUrl;
595+
}
596+
}
597+
598+
scriptEl.src = trustedSrc;
599+
scriptEl.async = false; // Preserve execution order
600+
scriptEl.onload = () => {
601+
URL.revokeObjectURL(blobUrl);
602+
resolve();
603+
};
604+
scriptEl.onerror = (event) => {
605+
URL.revokeObjectURL(blobUrl);
606+
reject(
607+
new Error(
608+
`Failed to execute user script ${scriptId}: ${event?.message || "unknown error"}`
609+
)
610+
);
611+
};
612+
(document.head || document.documentElement || document.body).appendChild(
613+
scriptEl
614+
);
615+
});
558616
} catch (error) {
559617
console.error(`CodeTweak: Error executing user script ${scriptId}:`, error);
560618
}

0 commit comments

Comments
 (0)