[Updated with new fix] Issues with privately hosted plugins in Chromium browsers

Recently local network access prompts and new behaviour was introduced in Chromium browsers. https://developer.chrome.com/blog/local-network-access

They require users to specify that they allow local network access for certain iframes. We have plugins that are not publicly accessible and this likely causes requests towards these plugins to fail and plugins to stop working. Will this be looked into?

There are of course work-arounds in the browser settings, but it’s a less than ideal experience to have it fail instead of prompt the user to allow / deny.

I think being able to add the property allow=“local-network-access” to the iframe would resolve the issue but I’m not quite sure.

Thank you in advance for taking this into consideration.

Hi @aaron.hugaert,

Thank you for this report! News to me (and probably all of us here). We can certainly look into it, but could you please help us understand your use case here?

I want to make sure I’m understanding the situation correctly… this isn’t for testing plugin dev (on localhost:5174 by default), right? The page says:

For the first milestone of Local Network Access, we consider a “local network request” to be any request from the public network to a local network or loopback destination.

Does that mean it only applies to situations where the plugin is:

  • Hosted publicly (on Vercel or Netlify or wherever, not on localhost or another local address)
  • But still uses clientside JS to communicate with servers on your LAN (e.g. 192.168.*, *.local)

So if both the plugin itself and the thing it’s trying to fetch from are on your LAN, it wouldn’t have this problem? It only happens if the public is hosted on a “public” address and it’s still trying to fetch from a local server?

Also, from that page:

Because the local network access permission is restricted to secure contexts, and it can be difficult to migrate local network devices to HTTPS, the permission-gated local network requests will now be exempted from mixed content checks if Chrome knows that the requests will be going to the local network before resolving the destination. Chrome knows a request is going to the local network if:

  • The request hostname is a private IP literal (e.g., 192.168.0.1).
  • The request hostname is a .local domain.
  • The fetch() call is annotated with the option targetAddressSpace: "local".

Do any of those work (especially the fetch() annotation)?

It took a little while until I could get back on this, sorry about that.

I don’t know how I looked over this but it seems to actually only affect our use of the Web Previews plugin: Web Previews - Plugins — DatoCMS.

I think the fact that it’s hosted publicaly but has to fetch through the local network / VPN causes problems, that presents itself as CORS issues. The fact that this is a problem now, and wasn’t before still seems to be related to those recent changes regarding local network access though.

For the time being our solution is hosting the plugin on our network.

Just to be clear… do you mean the plugin is hosted externally (e.g. on Vercel/Netlify/AWS), but the preview site is hosted locally on your LAN (a 192.168 address? or a local domain name?)? Or is it on localhost on your own computer during development?

It’s totally believable. In this case, I’m hoping the fetch() annotation with targetAddressSpace: "local" would work, but it would be helpful to know your precise setup so we can properly test it against your actual use case.

Thank you!

Hello!
My use case is simply testing Web Preview plugin against a localhost server - this gets blocked by the browser even though the setting for local network access is set to “Allowed”.

Access to fetch at ‘http://localhost:6301/api/preview-links’ from origin ‘https://plugins-cdn.datocms.com’ has been blocked by CORS policy:
Permission was denied for this request to access the unknown address space.

Appears to be due to the iFrame needing an attribute on it as well:

For now I am working around it using a tunnel via ngrok, but would rather not have to resort to this.

Thank you for the details, @emil.hernqvist and @aaron.hugaert!

I’ve been able to replicate it now and have reported it to devs. I’ll let you know once it’s fixed.

Interim update: I have a PR awaiting code review. You can try it on a private fork of the plugin if you’re in a rush: https://github.com/datocms/plugins/pull/127/changes

It uses targetAddressSpace annotation for the web preview plugin’s fetch call, as explained in the OP’s blog post or this better explainer: https://github.com/WICG/local-network-access/blob/main/explainer.md. It SEEMS to work in my tests, but please let me know if it doesn’t for you.

I wasn’t able to fix it with either CORS headers (Access-Control-Allow-Private-Network) or iframe annotations. It’s specifically on the fetch call from a less-local origin (where the plugin is hosted) to a more local one (your loopback localhost or 127.0.0.01), so I had to annotate it there.

This PR seems like it makes it work in both Chrome and Firefox (which doesn’t have the same issue to begin with, since they haven’t followed Google’s unilateral local access stuff). Safari still seems broken for now, but I’m not sure if that’s the same issue. Will await further reports on that.

@here This should be fixed now in version 1.0.28 of the Web Previews plugin. You can update from the sidebar in the plugin settings.

Please let me know if it works,or if you’re encountering any other localhost issues outside of this plugin.

Thanks for the deep dive and fix!

When building our own locally hosted plugins we have noted this issue as well though - is there a fix we as plugin authors need to implement for our plugins to be able to run through localhost?
It feels more in line with OP’s issue, and not clear to me how to get around this, as the plugin itself doesn’t render the iFrame in e.g. the plugin settings pane or field configuration.

It depends on where the error is happening. In the case of the Web Previews plugin, it was during a fetch() call. In that case, the fetch targetAddressSpace: 'loopback' annotation mentioned by the OP (or see https://github.com/WICG/local-network-access/blob/main/explainer.md) is what you’ll need to add to your own fetch call. An example of that annotation is in my PR.

If it’s another type of localhost issue (not necessarily in a fetch), then yes, there might be iframe annotations or other types of fixes we need to make… but could you please provide an example for me to test that against? Either your actual local plugin (you can email it to us at support@datocms.com) or a sanitized MVP that you can post here.

Sorry, not trying to ignore the other possible localhost failure modes, I just haven’t been able to replicate them yet! If you have an example of something that’s broken, that will help us troubleshoot and provide a fix :folded_hands:

@everyone Important update! We have a better fix in place now.

I owe all of you, and especially @aaron.hugaert an apology (and special thanks to Daan on Slack!). My previous fix was either insufficient, or completely wrong (I’m not entirely sure… the draft specs keep changing, apparently, or I might’ve just screwed up my testing procedure previously :sweat_smile:).

What we actually needed WAS in fact an iframe annotation in the parent frame (the CMS admin UI), the local-network-access that Aaron correctly identified at first (or rather, that param has now been separated into two, local-network and loopback-network; see https://docs.google.com/document/d/1QQkqehw8umtAgz5z0um7THx-aoU251p705FbIQjDuGs/edit?tab=t.0#heading=h.ao7p7jjargti)

We’ve now added that annotation correctly (I hope!), and as a result, Chrome users should get an explicit permission prompt if a plugin tries to load a localhost or *.local page. Once they approve the prompt, it should load:

So this fixes it at the technical level. From a UX perspective, plugin authors may wish to update their plugins to warn the user about why that permission is requested because Chrome doesn’t do a good job on its own and makes it sound pretty scary.

Thankfully, that warning should not pop up unless the user explicitly tries to load a local resource (i.e., adding the annotation in and of itself does not seem to trigger the permission popup; the plugin must actually attempt to actually load a local file first).

Sorry again for my mistake, and I hope that helps. I should note that this is all a bit confusing to me because the drafts keep changing, and Chrome is moving fast on this without any of the other browsers keeping up, and if they change it again, it may break again. Please let us know if you do notice any other issues related to this!

PS This whole situation was really confusing to me because a lot of the info I found was unclear and/or outdated. Here are the technical details that helped me (current and correct, as far as I can tell, as of March 2026), in case anyone else is investigating simiilar situations:

Technical analysis of Chrome iframe local network access issues

Chrome 142 introduced mandatory permission prompts for Local Network Access (LNA), which broke the Web Previews plugin for customers pointing it at localhost for local development previews.

Our initial fix a few months ago added targetAddressSpace to fetch requests, but that turned out to be a red herring — the root cause is that our plugins run inside an iframe. Chrome’s LNA policy requires iframes to explicitly declare local network access via an allow attribute on the iframe element itself. Without that allowlist annotation, the browser blocks the request before targetAddressSpace even matters.

The fix requires adding the appropriate permissions policy (e.g. local-network-access or its updated alias) to the iframe’s allow attribute, per the Microsoft/Chromium documentation on LNA from iframes.

See also:

2 Likes