@@ -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