PNA: A Short Life, A Long Shadow
The rise and fall of PNA, and what LNA means for browser security’s future.
Introduction
Have you seen these HTTP headers before?
Access-Control-Request-Method: GET
Access-Control-Request-Private-Network: true
Or perhaps this pesky alert?
If you’re a Chrome user who upgraded to Chrome 142 in the last three months, you may have encountered this alert. These two elements represent two different approaches to solving the same critical security problem—but in very different ways.
The Problem: Browsers as a Trust Boundary
For years, we’ve treated browsers primarily as rendering engines. But browsers are also enforcement points between:
- Public internet origins
- Local/private network resources
- Loopback interfaces
- User devices
The browser is a trust boundary — and historically, it didn’t act like one.
This trust boundary has been exploited for a very long time through various attack vectors, such as:
Port Scanning
Before Private Network Access (PNA), a malicious “public” website could:
- Probe RFC-1918 Networks
- Detect open ports
- Fingerprint routers, NAS devices, local services
Why? Because it’s an excellent way to fingerprint users in a stateless manner.
SOHO Pharming
An age-old technique where a public website would interact with private resources in a nefarious manner.
For example, a malicious site could hijack your router’s DNS settings:
fetch("https://router.local/setDNS?server=1.2.3.4")
A more recent example of this is CVE-2025-49596, which affected MCP Inspector :
fetch("http://localhost:6277/sse?command=cat&args=%2Fetc%2Fhosts")
Private Network Access (PNA): The First Solution
Browsers decided to address this problem through a mechanism called Private Network Access (PNA), initially known as CORS-RFC1918.
The goal:
Prevent public websites from silently accessing private network resources.
Core idea:
- Classify address spaces (public, private, local)
- Require explicit permission when crossing boundaries
Understanding Pre-flight Requests
To understand PNA, we first need to understand pre-flight requests. Consider this analogy:
You live in an apartment building, and a stranger walks up to the bellman asking to visit Mr. XYZ on floor N. The bellman is going to call you and ask for your permission: “Can I send this stranger up? Are you expecting them?” Depending on your response, the bellman will either allow or deny that stranger access.
Sound familiar? This is similar to how CORS works.
How PNA Works
PNA introduced new CORS behavior:
Access-Control-Request-Private-Network: true
When a public site attempts to access a private IP:
- Browser issues a preflight.
- Target must explicitly allow it.
- Otherwise, request fails.
A deeper dive into PNA can be found here: https://wiki.notveg.ninja/blog/pna/.
State of PNA
As of September 2025, PNA had been rolled out for over four years, and yet…
The Great Shift: PNA to LNA
In September 2025, Chrome made a dramatic decision: deprecate PNA entirely and replace it with Local Network Access (LNA). This wasn’t just a rename. It represented a fundamental philosophical shift in how browsers protect private networks.
PNA Model (Service-Side Protection):
- The private resource protects itself
- Must explicitly allow access via HTTP headers
- Security burden on server administrators
- Similar to CORS—declarative permission model
LNA Model (User-Side Protection):
- The user decides for each connection
- Browser prompts for permission
- Security burden shifted to end users
- No server-side configuration required
Local Network Access (LNA)
When LNA supported browsers detect an attempt to access a private network, they now display a simple prompt:
Unfortunately, the prompt provides no additional context about which internal resource triggered the request. To address this limitation, I developed a Chrome extension called LNAlyzer. . Details on how this extension works are available in my blog post: {LNAlyzer-UNDER-CONSTRUCTION}
Under the hood, these browsers use a function such as URLLoaderThrottle (in Chrome and Chromium). When a public origin tries to access a private IP:
- Request starts.
- IP resolves.
- LocalNetworkAccessCheck triggers.
- Request is deferred.
- IPC message sent to browser process.
- User sees permission prompt.
- User clicks Allow or Block.
- Request resumes or fails.
What We’ve Learned
Why PNA Struggled
- It Broke Existing Workflows
- Browsers historically allowed public websites to interact with services on localhost, routers, IOT dashboards and internal enterprise tools.
- Developers and vendors built systems assuming this behavior.
- PNA suddenly enforced a strict boundary in an ecosystem that had normalized crossing it.
- Compatibility suffered.
- Private Devices Can’t Easily Adapt
- PNA requires servers on private networks to send explicit opt-in headers for access.
- Many such devices have embedded firmware and are rarely updated.
- Browser Fragmentation
- For most of its existence, PNA was Chrome-only.
- Web developers couldn’t rely on it for cross-browser compatibility.
- No incentive to implement it if only Chrome users benefited.
- Developer Adoption Barriers
- Developers weren’t aware of PNA requirements.
- Didn’t understand how to implement them correctly.
- Chose to ignore them (no enforcement in other browsers)
- Lack of Centralized Configuration
- Enterprises often operate tools that span both public and internal network boundaries.
- Early PNA enforcement provided no practical way for organizations to centrally configure browser behavior across managed fleets.
- Security controls lived at the browser level, but enterprise policy needed to live at the admin level.
- LNA partially addressed this — at least in Chrome — by allowing administrators to define behavior via enterprise policy
Challenges for LNA
- Prompt Fatigue
- Browsers already ask users to approve: Camera, Microphone, Location and Notifications.
- Adding “Allow this site to access your local network?” becomes just another dialog.
- Non-technical users may find these prompts confusing and approve access without understanding the security implications.
- Architectural Friction
- LNA pauses network requests mid-flight to wait for user approval. This works reasonably well for
fetch(). - However, it becomes complicated for WebSockets (tight handshake timing), Service Workers (no visible UI), Shared Workers, and certain navigation flows.
- The browser network stack wasn’t originally built for interactive boundary checks.
- LNA had to retrofit permission logic into complex plumbing.
- LNA pauses network requests mid-flight to wait for user approval. This works reasonably well for
Browser Adoption Status
(As of February 2026)
| Browser | PNA Support | LNA Support | LNA Version | Current Status (Feb 2025) |
|---|---|---|---|---|
| Chrome/Chromium | ✅ (2021-2025) | ✅ | Chrome 142+ (Sept 2025) | Full LNA enforcement |
| Microsoft Edge | ❌ | ✅ | Edge 142+ (2025) | Full LNA enforcement |
| Firefox | ❌ | 🔄 Trials | Firefox Nightly | In development |
| Safari | ❌ | ❌ | N/A | Partial / Different model |