ferdium-app: Google Calendar fails to load user.js due to newly implemented CSP "require-trusted-types-for 'script'"

Preflight Checklist

  • I agree to follow the Code of Conduct that Ferdium Recipes adheres to.
  • I have searched the issue tracker for a bug report that matches the one I want to file, without success.

Ferdium Version

6.2.4

Recipe Name

Google Calendar

Recipe Version

2.3.2

Last Known working version of the recipe

No response

Steps to reproduce

Simply check the Service Developers Tools Console for the following error:

Uncaught (in promise) TypeError: Failed to set the 'innerHTML' property on 'Element': This document requires 'TrustedHTML' assignment. at v.loadUserFiles (VM133 recipe.js:1:4621) at v.loadRecipeModule (VM133 recipe.js:1:4526) at EventEmitter.<anonymous> (VM133 recipe.js:1:3337) at EventEmitter.emit (VM532 node:events:513:28) at Object.onMessage (VM639 renderer_init:2:9151)

Expected Behavior

Script should load fine and does load fine with other services that do not implement this specific CSP.

Actual Behavior

The user.js script fails to load.

Screenshots

The Service Developer Tools console shows the following error: afbeelding

Additional Information

Also the default Hello World script fails to load.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 4
  • Comments: 22 (2 by maintainers)

Commits related to this issue

Most upvoted comments

@Alexand3-R I see. Sounds a little ugly but we can use the static URL from the GitHub ferdium-recipes repo to apply more correctly the fix, as we maintain only files within the repo. Using https://raw.githubusercontent.com/ferdium/ferdium-recipes/main/recipes/googlecalendar/darkmode.css will work as a workaround for Google Calendar, as the link will always work. We can work in another issue for the final solution to prevent CSP errors across all Ferdium, but I see that the only recipe with troubles right now is Google Calendar. What do you think?

Using CSS files hosted on raw.githubusercontent.com does not work for some reason, however @MosEisley34 states that https://cdn.statically.io/gh/ferdium/ferdium-recipes/main/recipes/googlecalendar/darkmode.css does work, so that should be used instead.

However, also for the CSS, its not a workaround that is viable enough to be pushed to the googlecalendar recipe, as the options in the recipe settings to toggle it on and off and certain parameters, such as brightness, sepia and contrast will not work.

Would this likely cause dark mode to not work? Just noticed that starting today.

In https://github.com/ferdium/ferdium-recipes/pull/397, the directory got renamed from googlecalendar to google-calendar. Here is the updated webview.js for the mentioned workaround:

const _path = _interopRequireDefault(require('path'));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

module.exports = Ferdium => {
  // if the user is on googlecalendar landing page, go to the login page.
  if (
    location.hostname == 'workspace.google.com' &&
    location.href.includes('products/calendar/')
  ) {
    location.href =
      'https://accounts.google.com/AccountChooser?continue=https://calendar.google.com/u/0/';
  }
  Ferdium.injectCSS('https://cdn.statically.io/gh/ferdium/ferdium-recipes/main/recipes/google-calendar/calendar.css');
  Ferdium.injectJSUnsafe('https://cdn.statically.io/gh/ferdium/ferdium-recipes/main/recipes/google-calendar/webview-unsave.js');

  // Workaround for loading darkmode.css
  var cssId = 'cssDarkModeWorkaround';
  if (!document.getElementById(cssId))
  {
      var head  = document.getElementsByTagName('head')[0];
      var link  = document.createElement('link');
      link.id   = cssId;
      link.rel  = 'stylesheet';
      link.type = 'text/css';
      link.href = 'https://cdn.statically.io/gh/ferdium/ferdium-recipes/main/recipes/google-calendar/darkmode.css';
      link.media = 'all';
      head.appendChild(link);
  }
};

@lukassr and @Alexand3-R would you be able to make a joint PR about this CSP issue please?

@mikeseese thanks so much for this updated code. This worked for me 😃

@Alexand3-R @MosEisley34 ah thanks so much that worked great for me 💜

Hi, for some reason, the CSS’s stored on Github do not load. That was what I first tried. I was able to get it working by hosting the file on my own web server. Perhaps you can find another service to upload the darkmode.css.

@Alexand3-R hm, gave that a try but my dark mode didn’t come back 😦

Sorry this fix is only for loading external JavaScript files. However, here is the workaround that allows loading remote CSS files. For this to work, you would have to upload your “darkmode.css” file somewhere that allows direct access. The darkmode file can be found in your recipes folder of googlecalendar. Again, append this to webview.js.

// Workaround for loading darkmode.css
var cssId = 'cssDarkModeWorkaround';
if (!document.getElementById(cssId))
{
    var head  = document.getElementsByTagName('head')[0];
    var link  = document.createElement('link');
    link.id   = cssId;
    link.rel  = 'stylesheet';
    link.type = 'text/css';
    link.href = 'https://somedomain.com/path/to/darkmode.css';
    link.media = 'all';
    head.appendChild(link);
}

I managed to bring back the dark mode. In some lines where the innerHTML is edited, I wrapped the new content with the following function:

const escapeHTMLPolicy = trustedTypes.createPolicy('escapeHTML', {
  createHTML: string => string.replace(/</g, '&lt;'), // Escapes `<` characters to prevent the creation of new HTML elements

Ref 1, Ref 2

Specifically, I used the function in the following lines:

Dark mode in Google Calendar is back, but I’m having troubles disabling Dark Mode for some reason. Also, I didn’t tested to see if those changes affect other recipes, but my eyes are burning and I use GCalendar in my day-to-day.

Would this likely cause dark mode to not work? Just noticed that starting today.

If its implemented using JavaScript, then yes, likely. Possible fixes are:

1. Modify Ferdium code and rebuild to have it load the user.js file using a policy. Something like this:

const escapeHTMLPolicy = trustedTypes.createPolicy("myEscapePolicy", {
createScriptURL: (string) =>string.replace(/>/g, "<"),});
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = escapeHTMLPolicy.createScriptURL(ferdiUserScriptPath);

2. Find a way to fully disable CSP in Ferdium.

Debugger output of error: afbeelding

Afaik, regular calls like innerHTML are also stopped by this new CSP.