Trouble with CORS only in Shopify Theme Editor
Hey Barrel team 👋
Thank you for this plugin, its been great so far!
For some reason I am having major CORS issues only in the Shopify theme editor. This started today (worked fine last night), so idk if its a Shopify issue or what. However, everything works perfectly fine in my local/network preview. I didn't commit any new css/scripts to my /src folder as well.
I have this vite.config file:
import { defineConfig, defaultAllowedOrigins } from 'vite'
import tailwindcss from '@tailwindcss/vite'
import shopify from 'vite-plugin-shopify'
export default defineConfig({
plugins: [
tailwindcss(),
shopify({
themeRoot: 'app',
sourceCodeDir: 'src',
entrypointsDir: 'src/entrypoints',
snippetFile: 'vite-assets.liquid',
}),
],
server: {
cors: {
origin: [defaultAllowedOrigins, /\.myshopify\.com$/]
}
},
build: {
rollupOptions: {
output: {
entryFileNames: '[name].[hash].min.js',
chunkFileNames: '[name].[hash].min.js',
assetFileNames: '[name].[hash].min[extname]',
},
},
},
})
In the Shopify Theme Editor I see this error, and I cannot use the editor in any way:
Hi @rylanharper (:
Probably Shopify has updated the Content Security Policy (CSP) on .myshopify.com domains to include stricter rules that may be blocking insecure (http://localhost) asset requests within the theme editor.
Serving assets through a secure HTTPS tunnel (e.g. ngrok) resolves the issue, allowing Vite’s assets to load as expected.
// https://vitejs.dev/config/
export default defineConfig({
- plugins: [shopify(), tailwindcss()],
+ plugins: [
+ shopify({ tunnel: 'https://123abc.ngrok-free.app:5173' }),
+ tailwindcss()
+ ],
server: {
+ allowedHosts: ['123abc.ngrok-free.app'],
cors: {
origin: [defaultAllowedOrigins, /\.myshopify\.com$/]
@montalvomiguelo Hmm okay got it. Its very odd everything changed all of a sudden, even though it was working for me the past few weeks locally and in a theme editor setting.
Alright, so I went through the ngrok download and setup and have everything working!
However, I have to be honest.. This feels horrible DX wise for me lol. Not with the plugin itself, but just the general workflow of connecting to Shopify. Do I have manually add in a new ngrok subdomain to my vite.config every time I develop my theme since the subdomains are auto-generated? What do you recommend here? Like whats the approach at Barrel if you don't mind me asking 🤔
I'm coming over from working with Shopify in a headless environment so all this is pretty new.
@rylanharper I haven't found another solution yet; the issue started recently. Assets seem to load fine without the tunnel setup outside the theme editor
The same issue. I've tried everything, but to no avail. This happened after updating the google chrome version to version 142.0.7444.135.
Same here, as @slo86 says, the issue is related to the latest chrome update and note related to Shopify Content Security Policy (CSP). Some of my teammates had the issue and I did not, until I updated to latest chrome version.
ChatGPT suggests it might be related to Private Network Access (PNA) enforcement in recent Chrome/Edge versions. When the storefront runs on HTTPS (e.g. https://website.com) and requests assets from http://localhost:5173, the browser performs a PNA preflight. If the dev server doesn’t return the header:
Access-Control-Allow-Private-Network: true
How to fix it Type chrome://flags/#local-network-access-check into your Chrome address bar and press Enter. Find the "Local Network Access" flag and set its value to Disabled. Relaunch the browser when prompted
https://chromestatus.com/feature/5152728072060928
@slo86 genius! worked perfectly
@slo86 Thanks for that info, this resolves the issue!:)
@montalvomiguelo Maybe this fix can be added to the docs under Troubleshooting section within the docs? Or should I just close out the issue?
@rylanharper Could you please help me update the troubleshooting section of the documentation when you have a moment to close this issue? 🙏 🙏
@montalvomiguelo Sure! I should have some time this Sunday/Monday to submit a small PR to edit the docs:)
How to fix it Type chrome://flags/#local-network-access-check into your Chrome address bar and press Enter. Find the "Local Network Access" flag and set its value to Disabled. Relaunch the browser when prompted
https://chromestatus.com/feature/5152728072060928
This didn't work for me unfortunately
@lukecharle Fix your vite.config.js. Configure CORS for the dev server.
Docs (troubleshooting) - https://shopify-vite.barrelny.com/guide/troubleshooting.html
@lukecharle Fix your vite.config.js. Configure CORS for the dev server.
Docs (troubleshooting) - https://shopify-vite.barrelny.com/guide/troubleshooting.html
Yeah already have that in my config.
But after a bit of AI support, Cursor added the following under plugins and seems to be all working now! Hopefully this might be useful for others too.
{
name: 'add-private-network-header',
configureServer(server) {
server.middlewares.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Private-Network', 'true');
next();
});
}
}
@montalvomiguelo I'm using a slightly more simple approach. If you just pass tunnel: true, then Shopify's CLI will automatically generate and use a Cloudflare tunnel.
shopify({
themeRoot,
snippetFile: assetsSnippetFile,
versionNumbers: true,
tunnel: true,
}),
Then for the server I have the typical...
server: {
cors: {
origin: [
/^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/,
/^https?:\/\/[^/]+\.myshopify\.com$/,
],
},
},
When you start up the dev server Shopify will handle all the tunnel magic.
Would love a vite.config solution (none of the above have worked for me), though the Chrome settings update did. Will follow for updates!
@montalvomiguelo I'm using a slightly more simple approach. If you just pass tunnel: true, then Shopify's CLI will automatically generate and use a Cloudflare tunnel.
shopify({ themeRoot, snippetFile: assetsSnippetFile, versionNumbers: true, tunnel: true, }),Then for the server I have the typical...
server: { cors: { origin: [ /^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/, /^https?:\/\/[^/]+\.myshopify\.com$/, ], }, },When you start up the dev server Shopify will handle all the tunnel magic.
![]()
Error
GET TUNNEL_URL net::ERR_ABORTED 403 (Forbidden)
✅ Fix
Adding allowedHosts: true in the Vite server config resolved the 403 error:
server: {
+ allowedHosts: true,
cors: {
origin: [
/^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/,
/^https?:\/\/[^/]+\.myshopify\.com$/,
],
},
},
⚠️ According to the Vite documentation, setting
allowedHosts: trueallows any host, which is not recommended for public tunnels.I also tried a safer pattern-based configuration:
allowedHosts: [ /\.ngrok-free\.app$/, /\.trycloudflare\.com$/, /\.myshopify\.com$/, ]but it didn’t seem to work — "Could not start Cloudflare tunnel: max retries reached."
Full vite.config.mjs
import { defineConfig } from "vite";
import shopify from "vite-plugin-shopify";
export default defineConfig({
plugins: [
shopify({
themeRoot: [ROOT_PATH],
snippetFile: "react-snippet.liquid",
versionNumbers: true,
tunnel: true,
}),
],
server: {
allowedHosts: true,
cors: {
origin: [
/^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/,
/^https?:\/\/[^/]+\.myshopify\.com$/,
],
},
},
});
🧩 Dependencies
"vite": "^7.2.2"
"vite-plugin-shopify": "^4.0.2"
Everything builds and runs correctly with allowedHosts: true, but regex-based host filtering currently doesn’t work
Lol I am unsure what to add to the docs now 😵💫
Maybe I add in the Google Chrome "Local Network Access" fix and the Cloudflare tunnel config from @jonathanmoore?
I didn't have to modify anything with Chrome or add allowedHosts: true. Adding tunnel: true did the trick.
https://shopify.dev/docs/apps/build/cli-for-apps/networking-options#cloudflare-quick-tunnels
@INEEDAMONITOR are you sure you are on the latest version of the Shopify CLI?
Hmm, the tunnel approach and adding the store to allowed origins feels a little safer than turning off that update from Chrome?
Hi,
If Shopify can add allow="local-network-access" attribute on <iframe> that would fix the issue. (Source: CORS issue with Version 142 but not in Version 141 - Chrome Enterprise & Education Community )
@montalvomiguelo Agreed, the tunnel is safer than turning off Chrome's Local Network Access checks.. I reset my Chrome network settings and added @jonathanmoore's vite config, which is good, but needs the allowedHosts: true option like @INEEDAMONITOR mentioned (this is with the latest version of the CLI) for it to work fully.
I'm just wondering what a go-to config looks like for the documentation. If I can get a concrete example, I'll add a small PR to add this to the docs and close out this issue. What do you suggest @montalvomiguelo?
@rylanharper It seems like the allowedHosts config is not needed when using cloudflared. I did not need to set it up on my end either. @jonathanmoore's config feels like the simplest recommended tunnel solution?
When using ngrok, Vite displays a message saying that allowedHosts needs to be configured; that's why I added it when I shared my solution with ngrok above.
When setting up allowedHosts, Vite recommends using an explicit list of allowed hosts https://vite.dev/config/server-options#server-allowedhosts. Same for cors https://vite.dev/config/server-options#server-cors
~~Hmm maybe I'm just a noob, but is "cloudflared" the same as the Cloudlfare tunnel lol?~~ (I think that was a typo). I may be doing something wrong because the I get a CORS 403 error if the allowedHosts option is not set to true (although I see Vite says this is not recommended):
Failed to load resource: the server responded with a status of 403 ()
Yes, you are correct that its needed for ngrok, but I'm trying to avoid ngrok for better DX.
Edit: Maybe I should just post this topic on the Shopify dev forms and see what the Shopify team says? Seems like all this is due to recent Chrome updates, making a tunnel config necessary to bundle assets with vite. What @msev said is interesting and maybe I can bring that up in the post, but I dont know much about that iframe issue.
I'll post this again here as it seems to have been missed..add the following under plugins and it 'should' work:
{
name: 'add-private-network-header',
configureServer(server) {
server.middlewares.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Private-Network', 'true');
next();
});
}
}
hmm, that plugin approach does not seem to work on my end
Hey all, here is the thread on the Shopify Developer Community Forms on this issue. The Shopify team is aware of the issue and will (hopefully) post an update on this sometime soon. In the meantime, I guess the tunnel or Chrome settings adjustment is the best way forward.
I'll post this again here as it seems to have been missed..add the following under
pluginsand it 'should' work:{ name: 'add-private-network-header', configureServer(server) { server.middlewares.use((req, res, next) => { res.setHeader('Access-Control-Allow-Private-Network', 'true'); next(); }); } }
So this was working all fine for me, but now when I visit the preview url (stores domain), I'm getting:
...has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource
But it works fine in the customiser and on http://127.0.0.1:9292/
Honestly its just a new problem everyday 😂