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: