@@ -218,6 +218,104 @@ class GMAPIRegistry {
218218 window . GM_addStyle = addStyle ;
219219 window . GM . addStyle = addStyle ;
220220 }
221+
222+ // Always provide Trusted Types helpers for user scripts
223+ this . setupTrustedTypesHelpers ( ) ;
224+ }
225+
226+ setupTrustedTypesHelpers ( ) {
227+ // Create a comprehensive Trusted Types policy for user scripts
228+ if ( window . trustedTypes && window . trustedTypes . createPolicy ) {
229+ try {
230+ if ( ! window . __ctUserScriptPolicy ) {
231+ window . __ctUserScriptPolicy = window . trustedTypes . createPolicy ( "codetweak-userscript" , {
232+ createHTML : ( input ) => {
233+ // Basic sanitization - remove script tags and dangerous attributes
234+ if ( typeof input !== 'string' ) return '' ;
235+ return input
236+ . replace ( / < s c r i p t \b [ ^ < ] * (?: (? ! < \/ s c r i p t > ) < [ ^ < ] * ) * < \/ s c r i p t > / gi, '' )
237+ . replace ( / o n \w + \s * = \s * [ " ' ] [ ^ " ' ] * [ " ' ] / gi, '' )
238+ . replace ( / j a v a s c r i p t : / gi, '' ) ;
239+ } ,
240+ createScript : ( input ) => input ,
241+ createScriptURL : ( input ) => input ,
242+ } ) ;
243+ }
244+
245+ // Provide helper functions for user scripts
246+ window . GM_setInnerHTML = ( element , html ) => {
247+ if ( ! element || typeof html !== 'string' ) return false ;
248+ try {
249+ const trustedHTML = window . __ctUserScriptPolicy . createHTML ( html ) ;
250+ element . innerHTML = trustedHTML ;
251+ return true ;
252+ } catch ( error ) {
253+ console . warn ( 'CodeTweak: Failed to set innerHTML with Trusted Types:' , error ) ;
254+ // Fallback for non-Trusted Types environments
255+ try {
256+ element . innerHTML = html ;
257+ return true ;
258+ } catch ( fallbackError ) {
259+ console . error ( 'CodeTweak: innerHTML fallback also failed:' , fallbackError ) ;
260+ return false ;
261+ }
262+ }
263+ } ;
264+
265+ window . GM_createHTML = ( html ) => {
266+ try {
267+ return window . __ctUserScriptPolicy . createHTML ( html ) ;
268+ } catch ( error ) {
269+ console . warn ( 'CodeTweak: Failed to create TrustedHTML:' , error ) ;
270+ return html ; // Fallback
271+ }
272+ } ;
273+
274+ // Make these available in GM namespace too
275+ window . GM = window . GM || { } ;
276+ window . GM . setInnerHTML = window . GM_setInnerHTML ;
277+ window . GM . createHTML = window . GM_createHTML ;
278+
279+ } catch ( error ) {
280+ console . warn ( 'CodeTweak: Failed to create Trusted Types policy:' , error ) ;
281+
282+ // Provide fallback functions that work without Trusted Types
283+ window . GM_setInnerHTML = ( element , html ) => {
284+ if ( ! element || typeof html !== 'string' ) return false ;
285+ try {
286+ element . innerHTML = html ;
287+ return true ;
288+ } catch ( error ) {
289+ console . error ( 'CodeTweak: innerHTML assignment failed:' , error ) ;
290+ return false ;
291+ }
292+ } ;
293+
294+ window . GM_createHTML = ( html ) => html ;
295+
296+ window . GM = window . GM || { } ;
297+ window . GM . setInnerHTML = window . GM_setInnerHTML ;
298+ window . GM . createHTML = window . GM_createHTML ;
299+ }
300+ } else {
301+ // No Trusted Types support - provide basic fallbacks
302+ window . GM_setInnerHTML = ( element , html ) => {
303+ if ( ! element || typeof html !== 'string' ) return false ;
304+ try {
305+ element . innerHTML = html ;
306+ return true ;
307+ } catch ( error ) {
308+ console . error ( 'CodeTweak: innerHTML assignment failed:' , error ) ;
309+ return false ;
310+ }
311+ } ;
312+
313+ window . GM_createHTML = ( html ) => html ;
314+
315+ window . GM = window . GM || { } ;
316+ window . GM . setInnerHTML = window . GM_setInnerHTML ;
317+ window . GM . createHTML = window . GM_createHTML ;
318+ }
221319 }
222320
223321 registerResourceAPIs ( enabledApis ) {
@@ -303,7 +401,26 @@ class GMAPIRegistry {
303401 if ( typeof css !== "string" ) return null ;
304402
305403 const style = document . createElement ( "style" ) ;
306- style . textContent = css ;
404+
405+ // Handle Trusted Types for textContent
406+ let trustedCSS = css ;
407+ if ( window . trustedTypes && window . trustedTypes . createPolicy ) {
408+ try {
409+ if ( ! window . __ctTrustedHTMLPolicy ) {
410+ window . __ctTrustedHTMLPolicy = window . trustedTypes . createPolicy ( "codetweak-html" , {
411+ createHTML : ( input ) => input ,
412+ createScript : ( input ) => input ,
413+ createScriptURL : ( input ) => input ,
414+ } ) ;
415+ }
416+ // For CSS, we can use textContent directly, but let's be safe
417+ trustedCSS = css ; // textContent doesn't require TrustedHTML
418+ } catch ( e ) {
419+ console . warn ( "CodeTweak: Failed to create trusted types policy for CSS:" , e ) ;
420+ }
421+ }
422+
423+ style . textContent = trustedCSS ;
307424
308425 const target = document . head || document . documentElement || document . body ;
309426 if ( target ) {
@@ -599,55 +716,30 @@ async function executeUserScriptWithDependencies(
599716 // Load external dependencies first
600717 await scriptLoader . loadScripts ( requiredUrls ) ;
601718
602- // Execute user script using a CSP-compliant blob URL instead of Function()
603- const blob = new Blob ( [ userCode ] , { type : "text/javascript" } ) ;
604- const blobUrl = URL . createObjectURL ( blob ) ;
605-
606- await new Promise ( ( resolve , reject ) => {
607- const scriptEl = document . createElement ( "script" ) ;
608-
609- // Trusted Types compliance for blob URL
610- let trustedSrc = blobUrl ;
611- if ( window . trustedTypes && window . trustedTypes . createPolicy ) {
719+ // Execute user script directly without blob URLs to avoid CSP violations
720+ // Use Function constructor with proper error handling
721+ try {
722+ // Create a wrapper function that provides better error context
723+ const wrappedCode = `
612724 try {
613- if ( ! window . __ctTrustedScriptURLPolicy ) {
614- window . __ctTrustedScriptURLPolicy =
615- window . trustedTypes . createPolicy ( "codetweak" , {
616- createScriptURL : ( input ) => input ,
617- } ) ;
618- }
619- trustedSrc =
620- window . __ctTrustedScriptURLPolicy . createScriptURL ( blobUrl ) ;
621- } catch ( _e ) {
622- console . error ( "Failed to create trusted script URL:" , _e ) ;
623- console . warn ( "Falling back to raw URL." ) ;
624- // ignore, fall back to raw URL
625- trustedSrc = blobUrl ;
725+ ${ userCode }
726+ } catch (error) {
727+ console.error('CodeTweak: User script execution error in ${ scriptId } :', error);
728+ throw error;
626729 }
627- }
628-
629- scriptEl . src = trustedSrc ;
630- scriptEl . async = false ; // Preserve execution order
631- scriptEl . onload = ( ) => {
632- URL . revokeObjectURL ( blobUrl ) ;
633- resolve ( ) ;
634- } ;
635- scriptEl . onerror = ( event ) => {
636- URL . revokeObjectURL ( blobUrl ) ;
637- reject (
638- new Error (
639- `Failed to execute user script ${ scriptId } : ${
640- event ?. message || "unknown error"
641- } `
642- )
643- ) ;
644- } ;
645- ( document . head || document . documentElement || document . body ) . appendChild (
646- scriptEl
647- ) ;
648- } ) ;
730+ ` ;
731+
732+ // Execute directly using Function constructor (CSP-compliant)
733+ const userFunction = new Function ( wrappedCode ) ;
734+ userFunction ( ) ;
735+
736+ console . log ( `CodeTweak: Successfully executed script ${ scriptId } ` ) ;
737+ } catch ( error ) {
738+ console . error ( `CodeTweak: Error executing user script ${ scriptId } :` , error ) ;
739+ throw error ;
740+ }
649741 } catch ( error ) {
650- console . error ( `CodeTweak: Error executing user script ${ scriptId } :` , error ) ;
742+ console . error ( `CodeTweak: Error in executeUserScriptWithDependencies for ${ scriptId } :` , error ) ;
651743 }
652744}
653745
0 commit comments