chrome-extension-boilerplate-react: Uncaught Error: SecurityError: An insecure SockJS connection may not be initiated from a page loaded over HTTPS

I am having a similar issue to this. I am trying to inject a content script into a 3rd party website using https, and receiving the following error:

Uncaught Error: SecurityError: An insecure SockJS connection may not be initiated from a page loaded over HTTPS
    at new SockJS (fanduel.bundle.js:9519:13)
    at new SockJSClient (fanduel.bundle.js:7020:17)
    at initSocket (fanduel.bundle.js:14279:12)
    at ./node_modules/webpack-dev-server/client/index.js?protocol=ws%3A&hostname=localhost&port=3000&pathname=%2Fws&logging=info&overlay=true&reconnect=10&hot=true&live-reload=false (fanduel.bundle.js:7474:55)
    at options.factory (fanduel.bundle.js:17300:31)
    at __webpack_require__ (fanduel.bundle.js:16758:33)
    at fanduel.bundle.js:17875:11
    at fanduel.bundle.js:17880:12

My code is as follows manifest.json

{
    "manifest_version": 3,
    "background": { "service_worker": "background.bundle.js" },
    "action": {},
    "permissions": [
        "identity",
        "storage",
        "tabs",
        "activeTab",
        "scripting",
        "downloads"
    ],
    "host_permissions": ["<all_urls>"]
}

index.js (background script)

chrome.windows.create(
	{
		url: "https://www.fanduel.com/history",
		focused: false,
		state: "minimized",
	},
	async (hiddenWindow) => {
		const tab = hiddenWindow.tabs[0];

		const res = await chrome.scripting.executeScript({
			target: { tabId: tab.id },
			files: ["fanduel.bundle.js"],
		});
		console.log(res);
	}
);

fanduel.js (fanduel.bundle.js)

chrome.runtime.sendMessage({
    message: "from fanduel.js",
});
console.log("from fanduel.js");
window.onload = () => {
    chrome.runtime.sendMessage({
        message: "onload event from fanduel.js",
    });

    console.log("onload event from fanduel.js");
};

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 7
  • Comments: 35

Commits related to this issue

Most upvoted comments

A quick fix for this. In utils of project’s root folder, look for webserver.js. Change server.client.webSocketTransport to ws. Change server.webSocketServer to ws. So it will look like this: image

Restart dev server and the problem is gone 🎉🎉🎉

A quick fix for this. In utils of project’s root folder, look for webserver.js. Change server.client.webSocketTransport to ws. Change server.webSocketServer to ws. So it will look like this: image

Restart dev server and the problem is gone 🎉🎉🎉

After applying these changes, when you change anything, the dev server reload the page infinitely (infinity loop)

It did not work for me I am getting another error:

WebSocket connection to 'wss://github.com/ws' failed: 
WebSocketClient @ WebSocketClient.js:16
initWDSSocket @ WDSSocket.js:23
initSocket @ ErrorOverlayEntry.js:83
executeWithRetryAndTimeout @ retry.js:9
runWithRetry @ retry.js:17
setupOverlay @ ErrorOverlayEntry.js:82
runWithPatchedUrl @ patchUrl.js:29
./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js @ ErrorOverlayEntry.js:77
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
(anonymous) @ startup:7
(anonymous) @ startup:8
index.js:561 [webpack-dev-server] Event {isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
image

The only way to workaround this is to execute npm run build everytime you make a change and re-load the unpacked extension. Hope this helps solving @lxieyang

FYI, if you testing only against local webpages it’s enough to set chrome://flags/#allow-insecure-localhost

A quick fix for this. In utils of project’s root folder, look for webserver.js. Change server.client.webSocketTransport to ws. Change server.webSocketServer to ws. So it will look like this: image

Restart dev server and the problem is gone 🎉🎉🎉

Didn’t work, I got [webpack-dev-server] [object Event] error Stack Trace contentScript.bundle.js:8007 (logger) contentScript.bundle.js:8176 (anonymous function) contentScript.bundle.js:7626 (error) contentScript.bun

A quick fix for this. In utils of project’s root folder, look for webserver.js. Change server.client.webSocketTransport to ws. Change server.webSocketServer to ws. So it will look like this: image Restart dev server and the problem is gone 🎉🎉🎉

After applying these changes, when you change anything, the dev server reload the page infinitely (infinity loop)

Same. Would definitely recommend not using this boilerplate due to this reason.

Alright, I’ve been dealing with this issue for a few days and found a solution that worked out for me. The TLDR (with some explanatory comments) for the solution is:

Solution TLDR:

In webserver.js:

  • set hot: false
  • Make sure you are setting the hot entry points manually
  • manually add HotModuleReplacementPlugin to the plugin list
  • set client: false
  • set https: false (haven’t tested with true but I think it should work the same)

Example

# webserver.js
...

// Set hot entry points manually
for (let entryName in config.entry) {
  if (excludeEntriesToHotReload.indexOf(entryName) === -1) {
    // Enable HMR for all entries except those in the "notHMR" list
    // See "Manual entry points" in https://webpack.js.org/guides/hot-module-replacement/#enabling-hmr
    config.entry[entryName] = [
      'webpack/hot/dev-server.js',
      `webpack-dev-server/client/index.js?hot=true&hostname=localhost&port=${env.PORT}`,
    ].concat(config.entry[entryName]);
  }
}

// Add HotModuleReplacementPlugin to plugin list
config.plugins = [new webpack.HotModuleReplacementPlugin({})].concat(
  config.plugins || []
);
...

var server = new WebpackDevServer(
  {
    https: false,
    // We do not enable hot mode because we are defining above HMR only for some entries
    hot: false,
    liveReload: false,
    client: false,
    // From here and below the rest of the options don't need changing, just posted the most important ones here for clarity
    host: 'localhost',
    port: env.PORT,
    static: {
      directory: path.join(__dirname, '../build'),
    },
    devMiddleware: {
      publicPath: `http://localhost:${env.PORT}/`,
      writeToDisk: true,
    },
    ...
  }
)

Explanation

Let me preface my explanation by clarifying I am not an expert and this is what I’ve come to understand from reading documentation and debugging the issue for a few days.

As I understand it, the issueAn insecure SockJS connection may not be initiated from a page loaded over HTTPS comes from using sockjs as the webSocketServer option in the webserver.js file.

However, if you change webSocketServer to ws you will notice that the error is gone but now you will get an infinite refresh loop whenever you refresh a page or make a change to your code.

This stems from the fact that HMR is enabled for ALL entry points via hot:true in the dev server config. Which includes the modules that should not have HMR enabled, content script being the culprit in this case for the infinite reload. If you open the dev console on the webpage that is reloading you will notice that it is attempting to create a websocket connection to the site that you are on currently, this would usually throw an exception when using sockjs due to it being insecure and stop further code execution, preventing HMR from attempting to get updates (this is why when using sockjs you don’t have infinite reload loops), but now that we are using ws and no exception is thrown HMR will try to find updates which it will never get and prompt it to refresh the page in search for updates, causing an infinite loop.

To fix this we declare hot:false and instead define manual entry points for HMR following webpack’s documentation. And we also need to explicitly add the HotModuleReplacementPlugin that webpack would automatically add when hot:true.

Closing Notes & Improved implementation

If you want to implement an even better version of HMR + the ability to reload the extension automatically when content or background scripts change, you can use this fork which implements that later feature and apply the changes mentioned to achieve both

Nothing helped, so I ended up using this boilerplate instead: https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite

Make https: true, in webpackdevserver Initialtor in webserver.js file image

Faced the same issue, I applied:

A quick fix for this. In utils of project’s root folder, look for webserver.js. Change server.client.webSocketTransport to ws. Change server.webSocketServer to ws. So it will look like this: image

Restart dev server and the problem is gone 🎉🎉🎉

and then I also got:

It did not work for me I am getting another error:

WebSocket connection to 'wss://github.com/ws' failed: 
WebSocketClient @ WebSocketClient.js:16
initWDSSocket @ WDSSocket.js:23
initSocket @ ErrorOverlayEntry.js:83
executeWithRetryAndTimeout @ retry.js:9
runWithRetry @ retry.js:17
setupOverlay @ ErrorOverlayEntry.js:82
runWithPatchedUrl @ patchUrl.js:29
./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js @ ErrorOverlayEntry.js:77
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
(anonymous) @ startup:7
(anonymous) @ startup:8
index.js:561 [webpack-dev-server] Event {isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
image

Then, I applied several more suggestions:

Make https: true, in webpackdevserver Initialtor in webserver.js file image

FYI, if you testing only against local webpages it’s enough to set chrome://flags/#allow-insecure-localhost

For Developers still getting errors This Should Works publicPath: http://localhost to publicPath: wss://localhost

Try with wss://, which indicates you want a secure WebSocket connection.

And it worked 👍🏼

This bug will also cause the issue that content js is not working. After changed webserver.js, it works well.

For Developers still getting errors This Should Works publicPath: `http://localhost to publicPath: `wss://localhost

Try with wss://, which indicates you want a secure WebSocket connection.

If you have your WebSocket server running with your Web server, it will probably use the same security certificate and you do not need to do anything. If it does not work, please check your WebSocket server documentation about how to add certificates and enable wss://.

https: true,
  hot: true,
  liveReload: false,
  client: {
    webSocketTransport: 'sockjs',
  },
  webSocketServer: 'sockjs',
  host: 'localhost',
  port: env.PORT,
  static: {
    directory: path.join(__dirname, '../build'),
  },
  devMiddleware: {
    publicPath: `wss://localhost:${env.PORT}/`,
    writeToDisk: true,
  },
  ```