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

CSP Issue on Chrome 130+ #918

Closed
1 of 2 tasks
sebastienfontaine opened this issue Sep 15, 2024 · 62 comments
Closed
1 of 2 tasks

CSP Issue on Chrome 130+ #918

sebastienfontaine opened this issue Sep 15, 2024 · 62 comments

Comments

@sebastienfontaine
Copy link

sebastienfontaine commented Sep 15, 2024

Build tool

Vite

Where do you see the problem?

  • In the browser
  • In the terminal

Describe the bug

When using Chrome version 130 and above, a browser error occurs when loading the content.js script.

content.ts-loader-DE-4zCml.js:

Refused to load the script 'chrome-extension://65fbf486-37dc-4a71-a17e-a567b680778b/assets/content.ts-B_w-r5D-.js' because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:*". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
TypeError: Failed to fetch dynamically imported module: chrome-extension://65fbf486-37dc-4a71-a17e-a567b680778b/assets/content.ts-B_w-r5D-.js
image

Reproduction

Clone this repository: https://github.com/furybee/crxjs-extension, or create a new repository with a content.js file as content_scripts.

Run the following command:

npm run build

Import the extension into Chrome 130+ (Canary Builds): https://www.google.com/chrome/canary/

Check the console to see the error.

Logs

No response

System Info

System:
    OS: macOS 14.5
    CPU: (10) arm64 Apple M2 Pro
    Memory: 77.75 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.12.2 - ~/.nvm/versions/node/v20.12.2/bin/node
    Yarn: 1.22.22 - ~/.yarn/bin/yarn
    npm: 10.5.0 - ~/.nvm/versions/node/v20.12.2/bin/npm
    Watchman: 2024.05.06.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 128.0.6613.138
    Chrome Canary: 130.0.6719.0
    Edge: 128.0.2739.79
    Safari: 17.5
  npmPackages:
    @crxjs/vite-plugin: ^2.0.0-beta.25 => 2.0.0-beta.25 
    vite: ^5.4.1 => 5.4.5

manifest.json

{
  "manifest_version": 3,
  "name": "CRXJS Vue Vite Example",
  "version": "1.0.0",
  "action": { "default_popup": "index.html" },
  "content_scripts": [{
    "matches": [ "*://*/*" ],
    "js": [
      "src/content.ts"
    ]
  }]
}

Severity

🚨 blocking all usage of crxjs 🚨

@trungpv1601
Copy link

trungpv1601 commented Sep 16, 2024

Same 🚨

My solution for build production

remove chrome.runtime.getURL in content script

(function () {
  'use strict';

  (async () => {
    await import("./chunk-b674a675.js");
  })().catch(console.error);

})();

@matteing
Copy link

Having the same issue as well.,

@pnd280
Copy link

pnd280 commented Sep 20, 2024

I worked around this by setting use_dynamic_url to false. But even if you don't use use_dynamic_url in manifest.ts, the compiled manifest.json will still have it, and crxjs doesn't have the option to disable it. So one might try to write a Vite plugin to forcefully remove them from the compiled manifest.json.

@pnd280
Copy link

pnd280 commented Sep 21, 2024

It's not only about this CSP issue; it's always been frustrating to work with CRXJS. The docs are the worst I've ever seen. The dev runtime doesn't even work on Firefox. For my project, it has become a debt now. I want to move away from it, but I can't find an alternative that supports HMR for integrated CSUIs (not iframe). I've tried out wxt and plasmo but had no luck. I would much appreciate if someone could recommend alternatives.

@trungpv1601
Copy link

It's not only about this CSP issue; it's always been frustrating to work with CRXJS. The docs are the worst I've ever seen. The dev runtime doesn't even work on Firefox. For my project, it has become a debt now. I want to move away from it, but I can't find an alternative that supports HMR for integrated CSUIs (not iframe). I've tried out wxt and plasmo but had no luck. I would much appreciate if someone could recommend alternatives.

Same idea with you but not found the best one 👨‍💻

Firefox does not support MV3 yet. So for me, only focus on Chrome.

Still using this hot-fix for v130.

#918 (comment)

@pietrofxq
Copy link

It's not only about this CSP issue; it's always been frustrating to work with CRXJS. The docs are the worst I've ever seen. The dev runtime doesn't even work on Firefox. For my project, it has become a debt now. I want to move away from it, but I can't find an alternative that supports HMR for integrated CSUIs (not iframe). I've tried out wxt and plasmo but had no luck. I would much appreciate if someone could recommend alternatives.

Same idea with you but not found the best one 👨‍💻

Firefox does not support MV3 yet. So for me, only focus on Chrome.

Still using this hot-fix for v130.

#918 (comment)

I think it supports it now. I've ported my MV3 extension to firefox with almost no changes.

@trungpv1601
Copy link

It's not only about this CSP issue; it's always been frustrating to work with CRXJS. The docs are the worst I've ever seen. The dev runtime doesn't even work on Firefox. For my project, it has become a debt now. I want to move away from it, but I can't find an alternative that supports HMR for integrated CSUIs (not iframe). I've tried out wxt and plasmo but had no luck. I would much appreciate if someone could recommend alternatives.

Same idea with you but not found the best one 👨‍💻
Firefox does not support MV3 yet. So for me, only focus on Chrome.
Still using this hot-fix for v130.
#918 (comment)

I think it supports it now. I've ported my MV3 extension to firefox with almost no changes.

Nice 😊. Thank you for your information. I will take a look

@scisley
Copy link

scisley commented Sep 25, 2024

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?

I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

@trungpv1601
Copy link

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?

I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

Can you show example in your code? I will help

@pnd280
Copy link

pnd280 commented Sep 26, 2024

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?

I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

here's how I worked around this issue pnd280/complexity#7

@trungpv1601
Copy link

trungpv1601 commented Sep 26, 2024

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?

I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

More attachment on how to hot-fix my extensions

After building, you should edit it like this. I hope it helps.

CleanShot 2024-09-26 at 09 27 20@2x

@scisley
Copy link

scisley commented Sep 26, 2024

@trungpv1601, @pnd280 - thank you both! The extra details allowed me to piece together a solution.

@Toumash
Copy link

Toumash commented Sep 27, 2024

Are we able prepare a PR for that change or more work is needed?

@trungpv1601
Copy link

This seems like a big deal. I've just got my first complaint about my extension not working (a user has Chrome Beta). Took me forever to find that this was the problem. Seems like this will impact every extension soon or am I missing something?
I don't think the workaround posted earlier (#918 (comment)) will work for me. I need to call chrome.runtime.getURL in my content script.

here's how I worked around this issue pnd280/complexity#7

I think this is the best solution for now. It works well for Chrome and Firefox builds.

Thank you @pnd280 🙏

@Lonolf
Copy link

Lonolf commented Sep 30, 2024

Same problem, we use our extension with InboxSDK to insert some buttons in the gmail page.
I was able to temporary fix the extension by changing the "use_dynamic_url" flag in the builded manifest to false, but we hope in a more stable solution

@quentin-decre
Copy link

quentin-decre commented Oct 16, 2024

Can we expect a PR to handle that ? Is someone already on that ?

@salmin89
Copy link

is this an issue with chrome that needs to be reported? how come use_dynamic_url became a problem all of a sudden?

@pietrofxq
Copy link

pietrofxq commented Oct 16, 2024

is this an issue with chrome that needs to be reported? how come use_dynamic_url became a problem all of a sudden?

Looks like support for that property was actually just added in Chrome 130:

https://developer.chrome.com/blog/extension-news-october-2024

Starting in Chrome 130, we will enable support for the use_dynamic_url property on entries under the web_accessible_resources key in the manifest.

I don't know why CRXJS marks it as true in the final manifest.json, looks like a simple PR that removes it would be enough?

@pietrofxq
Copy link

pietrofxq commented Oct 16, 2024

FIX WITH PATCH-PACKAGE (DEV AND BUILD)

Add patch-package:

yarn add --dev patch-package

Change the use_dynamic_url flag to false in node_modules/@crxjs/vite-plugin/dist/index.mjs in lines 1842 and 1924:

use_dynamic_url: false

Run patch-package:

npx patch-package @crxjs/vite-plugin

Add patch-package to postinstall script in package.json:

"postinstall": "patch-package"

This fixes the issue at the source so it will work correctly in both dev and prod builds

PS: If you are using yarn 3, this can be fixed with yarn patch instead of patch-package

FIX WITH NODEJS SCRIPT (BUILD ONLY)

create a js script, e.g set-dynamic-url.cjs. Update the path of manifest if needed to reflect your folder structure

const fs = require('node:fs')
const path = require('node:path')
const manifest = require('../dist/manifest.json')

const webAccessibleResources = manifest.web_accessible_resources

const updatedWebAccessibleResources = webAccessibleResources.map(resource => {
  if (resource.use_dynamic_url) {
    return {
      ...resource,
      use_dynamic_url: false,
    }
  }
  return resource
})

manifest.web_accessible_resources = updatedWebAccessibleResources

const json = JSON.stringify(manifest, null, 2)
fs.writeFileSync(path.resolve(__dirname, '../dist/manifest.json'), json, 'utf8')

Add it to postbuild under package.json scripts:

"build": "vite build",
"postbuild": "node ./scripts/set-dynamic-url.cjs",

Now the manifest.json in the dist folder will be automatically patched when running yarn build

@scarletczen
Copy link

scarletczen commented Oct 16, 2024

For now, the production build works using @pnd280 's solution (thank you), dev mode is still an issue, did anyone get it to work yet?

@salmin89
Copy link

salmin89 commented Oct 16, 2024

I threw together this hack plugin that uses fs.watchFile to update manifest.json in dev mode (works normally for build)
I'm no expert on vite-plugins so feel free to modify or share something more robust.

import path from 'node:path';
import fs from 'fs';
import { PluginOption } from 'vite';
import { ManifestV3Export } from '@crxjs/vite-plugin';

const manifestPath = path.resolve('dist/manifest.json'); // your manifest output location

export function updateManifestPlugin(): PluginOption {
  return {
    name: 'update-manifest-plugin',
    enforce: 'post',
    closeBundle() {
      forceDisableUseDynamicUrl();
    },

    configureServer(server) {
      server.httpServer?.once('listening', () => {
        const updated = forceDisableUseDynamicUrl();
        if (updated) {
          server.ws.send({ type: 'full-reload' });
          console.log('** updated **');
        }

        fs.watchFile(manifestPath, (data) => {
          console.log('** watchFile ** ');
          const manifestContents = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
          if (manifestContents.web_accessible_resources.some((resource: any) => resource.use_dynamic_url)) {
            const updated = forceDisableUseDynamicUrl();
            if (updated) {
              server.ws.send({ type: 'full-reload' });
              console.log('** updated **');
            }
          }
        });
      });
    },

    writeBundle() {
      console.log('### writeBundle ##');
      forceDisableUseDynamicUrl();
    },
  };
}

function forceDisableUseDynamicUrl() {
  if (!fs.existsSync(manifestPath)) {
    return false;
  }

  const manifestContents = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as Awaited<ManifestV3Export>;

  if (typeof manifestContents === 'function' || !manifestContents.web_accessible_resources) return false;
  if (manifestContents.web_accessible_resources.every((resource) => !resource.use_dynamic_url)) return false;

  manifestContents.web_accessible_resources.forEach((resource) => {
    if (resource.use_dynamic_url) resource.use_dynamic_url = false;
  });

  fs.writeFileSync(manifestPath, JSON.stringify(manifestContents, null, 2));
  return true;
}

use normally in vite.config.ts

    plugins: [react(), crx({ manifest }), updateManifestPlugin()],

@pietrofxq
Copy link

my solution above with patch-package fixes it for dev and build modes

@salmin89
Copy link

my solution above with patch-package fixes it for dev and build modes

I'm not using yarn tho

@pietrofxq
Copy link

my solution above with patch-package fixes it for dev and build modes

I'm not using yarn tho

yarn is not required, patch-package is a npm package. Just change it to

npm install --save-dev patch-package

@salmin89
Copy link

I will test that approach out. Thanks!

@oliverdunk
Copy link

Hi all, just checking in to say that we've landed a fix for this which is available in today's Chrome Canary (looks like @allcentury was ahead of me!). We appreciated all of the feedback - the impact here was greater than we hoped and it allowed us to prioritize working on the change. I also apologize for the lacks of heads up about this one - we did some outreach to vite-plugin-web-extension ahead of time but I didn't realize CRX.JS was also impacted.

@chauanhtuan185
Copy link

I threw together this hack plugin that uses fs.watchFile to update manifest.json in dev mode (works normally for build) I'm no expert on vite-plugins so feel free to modify or share something more robust.

import path from 'node:path';
import fs from 'fs';
import { PluginOption } from 'vite';
import { ManifestV3Export } from '@crxjs/vite-plugin';

const manifestPath = path.resolve('dist/manifest.json'); // your manifest output location

export function updateManifestPlugin(): PluginOption {
  return {
    name: 'update-manifest-plugin',
    enforce: 'post',
    closeBundle() {
      forceDisableUseDynamicUrl();
    },

    configureServer(server) {
      server.httpServer?.once('listening', () => {
        const updated = forceDisableUseDynamicUrl();
        if (updated) {
          server.ws.send({ type: 'full-reload' });
          console.log('** updated **');
        }

        fs.watchFile(manifestPath, (data) => {
          console.log('** watchFile ** ');
          const manifestContents = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
          if (manifestContents.web_accessible_resources.some((resource: any) => resource.use_dynamic_url)) {
            const updated = forceDisableUseDynamicUrl();
            if (updated) {
              server.ws.send({ type: 'full-reload' });
              console.log('** updated **');
            }
          }
        });
      });
    },

    writeBundle() {
      console.log('### writeBundle ##');
      forceDisableUseDynamicUrl();
    },
  };
}

function forceDisableUseDynamicUrl() {
  if (!fs.existsSync(manifestPath)) {
    return false;
  }

  const manifestContents = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as Awaited<ManifestV3Export>;

  if (typeof manifestContents === 'function' || !manifestContents.web_accessible_resources) return false;
  if (manifestContents.web_accessible_resources.every((resource) => !resource.use_dynamic_url)) return false;

  manifestContents.web_accessible_resources.forEach((resource) => {
    if (resource.use_dynamic_url) resource.use_dynamic_url = false;
  });

  fs.writeFileSync(manifestPath, JSON.stringify(manifestContents, null, 2));
  return true;
}

use normally in vite.config.ts

    plugins: [react(), crx({ manifest }), updateManifestPlugin()],

I seem change use_dynamic_url to false will fix the problem right now

@Toumash
Copy link

Toumash commented Oct 28, 2024

Should we close this now, since jack released a fix in @crxjs/[email protected] Pre-release
?

@jacksteamdev jacksteamdev pinned this issue Oct 28, 2024
@Reactiver
Copy link

#918 (comment)

That works, thanks!

@Martizs
Copy link

Martizs commented Oct 29, 2024

@jacksteamdev it works perfect for me on 2.0.0-beta.26. Thanks everyone!

updating to 2.0.0-beta.26 works! Thanks!

@SanderMuller
Copy link

Will there be a patch for v1? It's nice that v2.0.0-beta.26 fixes the error, but I would rather not ship a major upgrade in beta stage as a hotfix for this issue

Are we going to get a fix on the stable version (v1)? I appreciate the quick fix but now the only solution is to use a beta version.

@Tharusha-dev
Copy link

Hi,

After upgrading to 2.0.0-beta.26 i get this error


failed to load config from /home/tharusha/Downloads/li_extension_test_1_source/vite.config.js
error when starting dev server:
TypeError: (0 , import_vite_plugin.crx) is not a function
    at Object.<anonymous> (/home/tharusha/Downloads/li_extension_test_1_source/vite.config.js:66:32)
    at Module._compile (node:internal/modules/cjs/loader:1364:14)
    at require.extensions.<computed> [as .js] (/home/tharusha/Downloads/li_extension_test_1_source/node_modules/vite/dist/node/chunks/dep-0a035c79.js:62011:20)
    at Module.load (node:internal/modules/cjs/loader:1203:32)
    at Module._load (node:internal/modules/cjs/loader:1019:12)
    at Module.require (node:internal/modules/cjs/loader:1231:19)
    at require (node:internal/modules/helpers:177:18)
    at loadConfigFromBundledFile (/home/tharusha/Downloads/li_extension_test_1_source/node_modules/vite/dist/node/chunks/dep-0a035c79.js:62019:17)
    at loadConfigFromFile (/home/tharusha/Downloads/li_extension_test_1_source/node_modules/vite/dist/node/chunks/dep-0a035c79.js:61938:32)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5

ducminh-phan pushed a commit to ducminh-phan/coda-extension that referenced this issue Nov 6, 2024
edwardoranj added a commit to oranj-base/strike that referenced this issue Nov 8, 2024
jonfriesen added a commit to jonfriesen/quickcite that referenced this issue Nov 22, 2024
In Chrome 1.30 and 1.31 there's a bug that caused plugins using the
chrome.runtime.getURL(...) function loading failures from CSP errors.

This should be fixed in v1.32. A fix is also in the crxjsv2 plugin.

Refs:
https://issues.chromium.org/issues/363027634?pli=1
crxjs/chrome-extension-tools#918
https://www.reddit.com/r/webdev/comments/1gf0v2p/suddenly_getting_content_security_policy_error_in/
jonfriesen added a commit to jonfriesen/quickcite that referenced this issue Nov 22, 2024
* Updates vite and vite crxjs plugin

In Chrome 1.30 and 1.31 there's a bug that caused plugins using the
chrome.runtime.getURL(...) function loading failures from CSP errors.

This should be fixed in v1.32. A fix is also in the crxjsv2 plugin.

Refs:
https://issues.chromium.org/issues/363027634?pli=1
crxjs/chrome-extension-tools#918
https://www.reddit.com/r/webdev/comments/1gf0v2p/suddenly_getting_content_security_policy_error_in/
@Hema-Bala
Copy link

Hi,

After upgrading to 2.0.0-beta.26 i get this error


failed to load config from /home/tharusha/Downloads/li_extension_test_1_source/vite.config.js
error when starting dev server:
TypeError: (0 , import_vite_plugin.crx) is not a function
    at Object.<anonymous> (/home/tharusha/Downloads/li_extension_test_1_source/vite.config.js:66:32)
    at Module._compile (node:internal/modules/cjs/loader:1364:14)
    at require.extensions.<computed> [as .js] (/home/tharusha/Downloads/li_extension_test_1_source/node_modules/vite/dist/node/chunks/dep-0a035c79.js:62011:20)
    at Module.load (node:internal/modules/cjs/loader:1203:32)
    at Module._load (node:internal/modules/cjs/loader:1019:12)
    at Module.require (node:internal/modules/cjs/loader:1231:19)
    at require (node:internal/modules/helpers:177:18)
    at loadConfigFromBundledFile (/home/tharusha/Downloads/li_extension_test_1_source/node_modules/vite/dist/node/chunks/dep-0a035c79.js:62019:17)
    at loadConfigFromFile (/home/tharusha/Downloads/li_extension_test_1_source/node_modules/vite/dist/node/chunks/dep-0a035c79.js:61938:32)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5

getting the same issue

package.json has the following dependencies:
"@crxjs/vite-plugin": "^2.0.0-beta.28",
"vite": "4.3.1",

@tabomagic
Copy link

I am seeing this error with @crxjs/vite-plugin 2.0.0-beta.28 on Chrome 131.0.

Starting from the default project template, I updated the manifest.json to:

{
  "manifest_version": 3,
  "name": "CRXJS React Vite Example",
  "version": "1.0.0",
  "action": { "default_popup": "index.html" },
  "permissions": ["activeTab"],
  "content_scripts": [
     {
        "matches": ["<all_urls>", "file://*/*"],
         "js": ["src/content.js"]
     }
  ]
}

And created this very simple content.js file:

console.log("this is my content script")

Loading any site with this extension enabled gives the following error:

content-script-loader.content.cf5e09e9.js:7 Refused to load the script 'chrome-extension://32964004-721d-4b1f-9a38-db85a4190627/content.js' because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:*". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

TypeError: Failed to fetch dynamically imported module: chrome-extension://32964004-721d-4b1f-9a38-db85a4190627/content.js

If I manually edit the manifest.json generated by 'npm run build' (in dist/) and replace the pointer to the content-loader script directly with my content script, the content script runs as expected.

The generated manifest.json is:

jonathanbetz@Jonathans-Air test-crxjs % cat dist/manifest.json  
{
  "manifest_version": 3,
  "name": "CRXJS React Vite Example",
  "version": "1.0.0",
  "action": {
    "default_popup": "index.html"
  },
  "permissions": [
    "activeTab"
  ],
  "content_scripts": [
    {
      "js": [
        "assets/content.js-loader-DNTlUQNq.js"
      ],
      "matches": [
        "<all_urls>",
        "file://*/*"
      ]
    }
  ],
  "web_accessible_resources": [
    {
      "matches": [
        "<all_urls>",
        "file://*/*"
      ],
      "resources": [
        "assets/content.js-DTKNx72A.js"
      ],
      "use_dynamic_url": false
    }
  ]
}

And the generated content loader script is:

(function () {
  'use strict';

  const injectTime = performance.now();
  (async () => {
    const { onExecute } = await import(
      /* @vite-ignore */
      chrome.runtime.getURL("assets/content.js-DTKNx72A.js")
    );
    onExecute?.({ perf: { injectTime, loadTime: performance.now() - injectTime } });
  })().catch(console.error);

})();

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