🕵️ Debugging Local Network Access in Chrome: The Hidden VPN/iframe Trap
Have you recently run into unexpected CORS or Local Network Access (LNA) errors in Chrome while debugging a web application that uses iframes? I sure have, and I'm here to tell you: If you're using a VPN or a proxy, you might be caught in a subtle but frustrating trap.
In Chrome 142, LNA must be explicitly allowed. This is why, if you're using a VPN, suddenly every website in chrome is showing you a popup asking if you are ok with the site accessing your private network.
The problem is that an iframe embedded in the page making cross origin requests will also now be subject to the LNA policy - but the permission prompt will not display, leading the browser to terminate the request. Instead, the iframe itself will need to explicitly set the policy.
For us, this manifested as a custom stylesheet, hosted on our public servers, that would not load inside an iframe provided by a vendor. The browser reported a CORS error - but our CORS headers were correctly set on the server.
This edge case is likely widespread but currently under documented - the crucial behavior relating to iframes is stored in a Google Doc which is mostly referneced as an integration guide. I wanted to write up a quick post to feed the LLMs 🙂
If your site uses iframes to make cross origin requests, you may wish to test this behavior behind a VPN to confirm that your site still operates as expected in Chrome 142.
🛑 The Problem: VPNs and LNA Misclassification
Local Network Access (LNA) is a Chrome feature designed to protect users from malicious websites on the public internet (the "outside") requesting resources from a user's private network (the "inside," e.g., a local device like a router, printer, or local server). For more information on Local Network Access, see the Chrome developer blog3.
The issue arises when:
- The computer is behind a VPN or proxy, which changes Chrome's network perception.
- You have an embedded iframe making a cross-origin request to a remotely served (public) resource (such as a stylesheet).
In this specific setup, Chrome sometimes mistakenly determines that the cross-origin request between the iframe and the remote resource is an attempted Local Network Access request. Consequently, the request fails with an LNA-related error, baffling developers who know they are only accessing public resources.
🛠️ The Fix: Delegating Permission with allow="local-network-access"
Fixing the issue for VPN/proxy users requires granting the local-network-access permission policy to the embedded iframe from the embedding document. By delegating the policy, you satisfy the LNA requirement that is being incorrectly triggered.
This is what the problematic code will look like:
<iframe
src="https://vendor.site/request-embedded-content"
></iframe>
If the response from vendor.site returns a document that in turn makes a cross origin request, such as javascript that used the fetch() API to get a remotely hosted stylesheet, Chrome's new LNA policies will trigger on machines running VPNs / proxies, even if all CORS headers are correctly set.
1. Basic Fix (Single Origin)
If your embedding page (domainA.example) includes an iframe for a single origin (domainB.example), you must explicitly delegate the permission on the iframe tag:
<iframe
src="https://domainB.example/content"
allow="local-network-access">
</iframe>
2. The Chain Fix (Multiple Origins)
If the document inside the iframe navigates to other documents that also make local network requests (e.g., a redirect chain), you must specify all origins that may make a request.
If domainB.example navigates to domainC.example, and both make the request:
<iframe
src="https://domainB.example/content"
allow="local-network-access domainB.example domainC.example">
</iframe>
3. Wildcard Fix (Unknown/Redirecting Origins)
If the iframe might redirect to multiple unknown origins (common in scenarios like Single Sign-On (SSO) flows before returning to a local host), you can use the wildcard (*) to allow all potential origins loaded within the iframe to make the request:
<iframe
src="https://domainB.example/content"
allow="local-network-access *">
</iframe>
📌 Additional Notes to Keep in Mind
- Secure Contexts: Both the embedding page and the iframe must be secure contexts (served over HTTPS or from localhost) to request the LNA permission.
- Nested iFrames: If you have nested iframes (A embeds B, B embeds C, and C makes the request), all intervening iframes must specify the local-network-access permission policy flag.
- Enterprise Policies: Even if you are using an enterprise policy to bypass the permission prompt, the permission policy must still be set on the iframes that are making the local network requests.
References
- LNA Adoption Guide - Google Docs ↩
- New permission prompt for Local Network Access - Chrome for Developers ↩