Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mermaid versions after v9.2.2 cannot be injected into Firefox addons #5378

Open
simov opened this issue Mar 12, 2024 · 10 comments · May be fixed by #5408
Open

Mermaid versions after v9.2.2 cannot be injected into Firefox addons #5378

simov opened this issue Mar 12, 2024 · 10 comments · May be fixed by #5408
Labels
Contributor needed Status: Approved Is ready to be worked on Type: Bug / Error Something isn't working or is incorrect

Comments

@simov
Copy link

simov commented Mar 12, 2024

Description

I have a browser extension that injects mermaid.min.js as a content script:

chrome.scripting.executeScript({
  target: {tabId: id},
  files: [
    'mermaid.min.js'
  ],
  injectImmediately: true
})

In Chromium based browsers the above code injects the latest mermaid.min.js build without any issues. However, in Firefox after v9.2.2 it is no longer possible to inject the mermaid.min.js build using the exact same code.

Initially I was thinking that it is a temporary issue, so that's why I did not report it immediately, but at this point I have users asking me why am I not updating the Mermaid version in the Firefox version of the extension (same code base as the Chromium one), and I cannot figure out what changed after v9.2.2 that might be causing this.

According to the release docs for v9.3.0 https://github.com/mermaid-js/mermaid/releases/tag/v9.3.0 the build become:

25% Smaller

So I'm wondering if it is something related to that.

Note that this is happening ever since Dec 15th 2022 when v9.3.0 got released, so through out all this time all versions of Firefox consistently fail to inject the library after v9.3.0, but they can inject v9.2.2 just fine. I have tested every Mermaid build ever since.

Steps to reproduce

A simple Firefox addon can be created to reproduce this issue:

manifest.json

{
  "manifest_version": 3,
  "name"            : "Inject Mermaid > v9.2.2 Bug",
  "version"         : "1",
  "description"     : "All Mermaid versions from v9.3.0 onwards cannot be injected",

  "background" : {
    "scripts": [
      "background.js"
    ]
  },

  "permissions": [
    "scripting"
  ],

  "host_permissions": [
    "file:///*",
    "*://*/"
  ],

  "browser_specific_settings": {
    "gecko": {
      "id": "ff-mermaid-inject@foo.bar",
      "strict_min_version": "110.0"
    }
  }
}

background.js

console.log('background')

chrome.tabs.onUpdated.addListener((id, info, tab) => {

  if (info.status === 'loading' && info.url) {

    console.log('inject')

    chrome.scripting.executeScript({
      target: {tabId: id},
      files: [
        'mermaid.min.js',
        'content.js'
      ],
      injectImmediately: true
    }, (err) => {
      if (err) {
        console.log(err)
      }
    })
  }
})

content.js

console.log('content')
console.log(mermaid)

mermaid.min.js

See below

  1. Navigate to about:debugging#/runtime/this-firefox
    Screenshot from 2024-03-12 11-35-01

  2. Click on the Load Temporary Add-on... button

  3. Find the folder containing the 3 files from above and double click on the manifest.json file

  4. Make sure the Access the data for all websites switch is turned on for your temporary extension in about:addons
    Screenshot from 2024-03-12 11-54-41

  5. Navigate to any webpage

When using Mermaid v9.2.2 https://cdnjs.cloudflare.com/ajax/libs/mermaid/9.2.2/mermaid.min.js as the source of mearmaid.min.js the injecting works and therefore you will see the following output in the console log of the page you are looking at:
Screenshot from 2024-03-12 11-34-13

Meaning both the mermaid.min.js and the content.js got injected and you can see the mermaid object being printed out in the console.

Now,

  1. Replace the contents of mermaid.min.js with the contents of https://cdnjs.cloudflare.com/ajax/libs/mermaid/9.3.0/mermaid.min.js
  2. Navigate back to about:debugging#/runtime/this-firefox and click on the Reload button for your temporary addon
  3. Click on the Inspect button to view the console log for the background page
  4. Switch back to the site that you were looking at before and refresh the page

Now in the console log for the background page of the extension you can see the following:
Screenshot from 2024-03-12 11-32-41

So apparently on line 23 in mermaid.min.js now a call to Function() is being blocked by the CSP and therefore the inject fails as a whole. The inject is failing from v9.3.0 onward because of a Content Security Policy set for browser addons in Firefox. Note that the whole purpose of injecting mermaid.min.js instead of adding it as a script tag into the page is to circumvent another set of CSP issues, but in the content page context afterwards, so there is really no other way for me to use Mermaid other than injecting it in the background page.

I have examined the offending line 23 in both v9.2.2 and v9.3.0, but I cannot spot any significant difference between the two.

Screenshots

No response

Code Sample

No response

Setup

  • Mermaid version: v9.2.2 works, any version beyond v9.3.0 does not work
  • Browser and Version: any version of Firefox after Dec 15th 2022

Suggested Solutions

No response

Additional Context

No response

@simov simov added Status: Triage Needs to be verified, categorized, etc Type: Bug / Error Something isn't working or is incorrect labels Mar 12, 2024
@simov
Copy link
Author

simov commented Mar 12, 2024

As it turns out the problem can be resolved by replacing all occurrences of Function("return this") with (() => globalThis). Not sure how is it working in v9.2.2 if that version contains Function("return this") too, but it does not trigger the CSP error when injecting the library in Firefox.

@sidharthv96
Copy link
Member

sidharthv96 commented Mar 13, 2024

Can you check if https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.0.0-alpha.6/mermaid.min.js works?
We changed the bundler to esbuild in v11. Although that also contains Function("return this")

@simov
Copy link
Author

simov commented Mar 13, 2024

No it doesn't work, still the same issue in 11.0.0-alpha.6

@sidharthv96 sidharthv96 added Contributor needed Status: Approved Is ready to be worked on and removed Status: Triage Needs to be verified, categorized, etc labels Mar 13, 2024
@simov
Copy link
Author

simov commented Mar 13, 2024

As far as I understand the Function constructor is considered unsafe and for that reason it is blocked by the CSP (Content Security Policy), even though they say that using the Function constructor with a fixed string is generally safe as it cannot offer remote code execution, and of course Function("return this") is completely harmless too, but the rule is to not allow the Function constructor in general.

One guy showed me a WebPack plugin that he built to do just that - replace Function("return this") with (() => globalThis) so apparently other people are having issues with their builds too.

I don't know how and if changing this is going to affect backward compatibility for example.

@sidharthv96
Copy link
Member

Rollup was updated to v3 in 9.3.0, we also switched to using an esm version of lodash as well.
Can you try using webpack with that plugin to bundle mermaid and generate your content.js file, instead of injecting mermaid separately?

@sidharthv96
Copy link
Member

@remcohaszing @aloisklink @nirname @Yokozuna59 @Yash-Singh1 does anyone of you folks have any insights?

@simov
Copy link
Author

simov commented Mar 13, 2024

Rollup was updated to v3 in 9.3.0, we also switched to using an esm version of lodash as well. Can you try using webpack with that plugin to bundle mermaid and generate your content.js file, instead of injecting mermaid separately?

No, in fact I'm not building Mermaid myself, but following what this guy did I am simply going to replace all occurrences of Function("return this") with (() => globalThis) in the official mermaid.min.js build provided by you, which is part of my packaging script.

That works, however I am going to have some issues with the review process of my extension afterwards because I am modifying the official build, and that is being compared by the reviewer. So hopefully that's going to pass the validation, but of course it would be best if we have that fixed in the official build if there is no other downside related to it.

@Yash-Singh1
Copy link
Member

Yash-Singh1 commented Mar 13, 2024

@remcohaszing @aloisklink @nirname @Yokozuna59 @Yash-Singh1 does anyone of you folks have any insights?

This seems to be coming from the lodash-es _root.js: https://unpkg.com/browse/lodash-es@4.17.21/_root.js

https://github.com/lodash/lodash/blob/51ed7e7707047aae23433bebaf461064787b006a/_root.js#L7

I think it would make sense to patch lodash-es to use one of the polyfills here:

https://mathiasbynens.be/notes/globalthis#robust-polyfill

...or we could just replace it with window because Mermaid.js runs only in the browser.

@sidharthv96
Copy link
Member

@simov does #5383 mean that this issue was solved?

@simov
Copy link
Author

simov commented Mar 20, 2024

@sidharthv96, no these are two separate issues. Firefox cannot inject any version of Mermaid after v9.3.0 (this issue), any Chromium based browser (the rest of them) cannot inject Mermaid after v10.9.0 (#5383).

What I will do for the upcoming release of my extension is:

  • update Mermaid only to v10.8.0 - works in all Chromium browsers
  • apply a patch while packaging it for Firefox to replace the two occurrences of Function("return this") in the build with (() => globalThis)

This will make it work in all browsers for the time being, but of course if the official build does not get fixed I will have to think about something else next time I have to do a release.

@Yash-Singh1 Yash-Singh1 linked a pull request Mar 23, 2024 that will close this issue
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Contributor needed Status: Approved Is ready to be worked on Type: Bug / Error Something isn't working or is incorrect
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants