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

Manifest V3 and Content-Security-Policy in GMail prevent loading extension script via addScript #798

Open
huksley opened this issue Oct 22, 2024 · 12 comments

Comments

@huksley
Copy link
Contributor

huksley commented Oct 22, 2024

Looks like new changes Gmail broke many functionality in gmail-js.

For example this.gmail.observe.before("send_message", () => handler()) stopped working.

I can see the following messages in the console:

gmail.js:688 Can't find composeRoot for [object Object]
gmail.js:688 api.dom.compose called with invalid element
@huksley
Copy link
Contributor Author

huksley commented Oct 22, 2024

The initial culprit that the approach similar to extensionInjector.js are no longer supported.

Gmail started sending Content-Security-Policy headers which disallows loading subsequent scripts. But the initial content script are injected okay.

Screenshot 2024-10-22 at 10 03 57



@huksley huksley changed the title Observe for send and scheduled send stopped working, recipient change does not working Manifest V3 and Content-Security-Policy in GMail prevent loading extension script Oct 22, 2024
@huksley
Copy link
Contributor Author

huksley commented Oct 22, 2024

So resolution is the following.
Gmail enabled CSP policy which prohibits loading real extension via extension injector.

I.e. this will not work anymore: https://github.com/josteink/gmailjs-node-boilerplate/blob/dda13306bb24083504185bc20db6cce55b4a71dd/src/extensionInjector.js#L3

Workaround: load extension script from service worker, i.e. using scripting capabilities.

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  chrome.scripting.executeScript({
    target: { tabId: sender.tab.id frameIds: [sender.frameId] },
    world: "MAIN",
    files: ["src/extension.js"]
  })
  .then(r => {
    logger.info("Injected script", r);
  })
  .catch(err => {
    logger.warn("Failed to inject script", err);
  });
  sendResponse(true);
})

And extension injector must send message to inject, i.e.

chrome.runtime.sendMessage({ action: "injectScript" }, res => {
    if (!res) {
      logger.warn("Failed to add script from service worker");
    }
  });

@huksley huksley changed the title Manifest V3 and Content-Security-Policy in GMail prevent loading extension script Manifest V3 and Content-Security-Policy in GMail prevent loading extension script via addScript Oct 22, 2024
@huksley
Copy link
Contributor Author

huksley commented Oct 22, 2024

gmail.js:688 Can't find composeRoot for [object Object]
gmail.js:688 api.dom.compose called with invalid element

These errors happen because if you load compiled script (gmail.js + my extension) directly via content script declared in manifest, it gets loaded in ISOLATED world without access to DOM, XHR, fetch.

Only loading script using chrome.scripting() now allows properly access gmail structures.

@huksley
Copy link
Contributor Author

huksley commented Oct 22, 2024

@josteink

@josteink
Copy link
Collaborator

That's very impressive digging @huksley. Thanks for the assistance!

If you could prepare a PR which updates the boilerplate with your findings, I would be extremely grateful! 😊

@MykhailoDev
Copy link

I faced same problem, but i use gmail-js with vite and csxjs vite plugine. this request have fix for this problem crxjs/chrome-extension-tools@f4eb4d4

main problem was in manifest.json and use_dynamic_url

may be this issue will usefull crxjs/chrome-extension-tools#918

@josteink
Copy link
Collaborator

josteink commented Oct 24, 2024

I've tested with three accounts:

  • regular gmail account
  • grandfathered free Google Apps account
  • paid Google Workplace account

I cannot reproduce CSP issues or loading issues at all in any of those configurations.

Can you provide some leads/insights into what accounts you guys have when you can reproduce this issue?

For reference, this is the CSP headers I'm currently getting:

script-src 'report-sample' 'nonce-Cs68NcA0-MAMhOrX7djC5w' 'unsafe-inline' 'strict-dynamic' https: http: 'unsafe-eval';object-src 'none';base-uri 'self';report-uri https://mail.google.com/mail/cspreport, require-trusted-types-for 'script';report-uri https://mail.google.com/mail/cspreport

@MykhailoDev
Copy link

I've tested with three accounts:

  • regular gmail account
  • grandfathered free Google Apps account
  • paid Google Workplace account

I cannot reproduce CSP issues or loading issues at all in any of those configurations.

Can you provide some leads/insights into what accounts you guys have when you can reproduce this issue?

For reference, this is the CSP headers I'm currently getting:

script-src 'report-sample' 'nonce-Cs68NcA0-MAMhOrX7djC5w' 'unsafe-inline' 'strict-dynamic' https: http: 'unsafe-eval';object-src 'none';base-uri 'self';report-uri https://mail.google.com/mail/cspreport, require-trusted-types-for 'script';report-uri https://mail.google.com/mail/cspreport

Any account in new Chrome 130

@huksley
Copy link
Contributor Author

huksley commented Oct 24, 2024

main problem was in manifest.json and use_dynamic_url

what a can of worms(((

I cannot reproduce CSP issues or loading issues at all in any of those configurations.

@josteink try setting use_dynamic_url: true
i.e.

"web_accessible_resources": [
    {
      "resources": ["src/*", "assets/*", "images/*"],
      "matches": ["*://*/*"],
      "use_dynamic_url": true
    }
]

I don't even know where I took this, I believe some official docs recommended it?!

@josteink
Copy link
Collaborator

josteink commented Oct 25, 2024

I've spent half the day trying:

  1. to replicate this issue (and failing!)
  2. and understand how my code is different from others (and failing again!)
  3. and reading up on the very minimal documentation for use_dynamic_url to understand how it applies to the extension (and failing yet again!)

For reference in my extension I have:

  • Manifest V3
  • web-assets bundled inside the extension (scripts, svgs, etc)
  • no remote assets on remote hosts, zero.
  • page-scripts injected from content-script using URLs generated from chrome.runtime.getURL(src); in content-script.
  • No use of use_dynamic_url in my manifest.

And everything works fine on my end!

So can someone tell me what I'm missing? Why would I want to enable use_dynamic_url, if I seemingly don't need it? What does it actually do? Or how does it affect gmailjs into a non-working state?

From the surface of things, to me it sounds like this might be more of a gmail+extension general issue, than gmailjs issue? Or am I wrong?

@huksley
Copy link
Contributor Author

huksley commented Oct 26, 2024

Well, AFAIK this problem happens if some one used use_dynamic_url: true
and only in specific version of the Chrome...

https://issues.chromium.org/issues/354748637

Btw, one thing I noticed, that the way I am loading the extension now, sometimes, if you open new tab and type mail.google.com, the extension does not load. if you reload a page it load successfully.

Some maybe this issue is not applicable to Gmail.js but this use of use_dynamic_url is everywhere.

@josteink
Copy link
Collaborator

Ok. So use_dynamic_urls is everywhere. But I still don't get what it does.

What scenarios does it enable that you wouldn't be able to do otherwise? 🤷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants