Skip to content

Proposal: Preflight + Public TLS as Permission Prompt Exemption for Local Network Access #96

@ChrisEdgington

Description

@ChrisEdgington

Summary

The LNA permission prompt is sound for the common case: unauthenticated HTTP requests to raw IPs where the browser cannot verify the target's identity or intent.

However, when a local network target serves a publicly-trusted TLS certificate and explicitly opts in via a CORS preflight, every security property the permission prompt provides is already established cryptographically — and more reliably than a user clicking "Allow." I propose exempting these requests from the prompt.

Use Case

I built ProxyBox Zero, a hardware device that acts as an HTTPS reverse proxy between cloud web applications and local network peripherals (printers, scales, barcode scanners). Our customers are small manufacturers, warehouses, and agricultural operations — no IT departments, no enterprise-managed devices.

How it works:

  1. ProxyBox gets a local IP (e.g., 192.168.1.50)
  2. DNS points {device-id}.pbxz.io192.168.1.50 via Cloudflare
  3. Caddy uses the DNS-01 ACME challenge to obtain a publicly-trusted, CT-logged Let's Encrypt certificate
  4. Cloud ERPs make fetch() calls to the device over browser-trusted HTTPS

The firmware is fully updatable — we can implement any preflight or handshake protocol the spec requires. Enterprise policies (LocalNetworkAccessAllowedForUrls) are not viable for our market; our users don't know what Chrome policies are.

The Core Argument

The LNA explainer states:

"Even if the local device has opted in to connections from a top level site, we believe there is value in user awareness and control over this exchange."

This was written about the original PNA preflight, where "opted in" meant an unauthenticated HTTP server at some IP returned a header — a weak signal. User awareness meaningfully adds security there.

But when the target serves a publicly-trusted certificate with CT logging, responds to a preflight with Access-Control-Allow-Private-Network: true, and communicates over HTTPS end-to-end, the prompt is confirming what's already been established cryptographically.

What attack does the permission prompt prevent that the TLS handshake + preflight does not?

Threat How TLS + preflight addresses it
CSRF against local devices Target explicitly opts in via preflight; attacker cannot forge opt-in without controlling the device
Drive-by exploitation of vulnerable services Vulnerable devices don't serve publicly-trusted certs or respond to preflights; they remain protected by the prompt
Network fingerprinting / scanning Attacker must guess a valid hostname with a matching publicly-trusted cert on a local IP — see timing discussion below
User unawareness The user physically installed the device and configured their ERP to use it

Why Previous Preflight Concerns Don't Apply

"Legacy devices can't implement preflights"

This proposal doesn't change anything for legacy devices. They continue through the permission prompt. This is a strictly additive path for devices that can meet the security bar.

"Timing attacks could determine valid IP addresses"

The original PNA preflight was sent to arbitrary IPs over HTTP, enabling topology discovery via timing (crbug.com/40051437, WICG/private-network-access#41). Under this proposal, the target must complete a TLS handshake with a publicly-trusted certificate matching the requested hostname. An attacker scanning local IPs sees:

  • No TLS listener → connection refused (no new information vs. any closed port)
  • Wrong/self-signed cert → handshake fails (no preflight sent)
  • Valid cert, wrong hostname → verification fails (no preflight sent)

Reaching the preflight stage requires knowing a valid hostname that resolves locally and is served by a device with a matching public cert. At that point, the attacker already knows more than preflight timing would reveal.

"User awareness has value even with device opt-in"

The spec authors compare LNA to iOS/Android local network permissions. But those OS-level permissions are per-application, persistent, and one-time — they aren't reset by OS updates or profile changes. The browser permission prompt's persistence is implementation-defined and in practice fragile (browser updates, profile resets, switching browsers all re-trigger it). A TLS+preflight exemption would actually be closer to the OS model: durable authorization established by a strong signal.

Proposal

Exempt local network requests from the permission prompt when all conditions are met:

  1. HTTPS end-to-end (no mixed content)
  2. Target serves a certificate from a publicly-trusted CA (in the browser's root store)
  3. Target responds to CORS preflight with Access-Control-Allow-Private-Network: true
  4. Standard CORS requirements satisfied

If any condition isn't met, fall back to the current permission prompt.

if (isLocalNetworkRequest(request)) {
  if (connection.isHTTPS &&
      connection.certificate.isPubliclyTrusted &&
      preflightResponse.has("Access-Control-Allow-Private-Network: true") &&
      corsRequirementsMet(preflightResponse)) {
    return null; // Allow — security properties already satisfied
  } else {
    // Existing permission prompt flow
  }
}

This changes nothing for unauthenticated requests, legacy devices, or the spec's core security model. Users can still block local network access via Permissions Policy and browser settings.

Questions for Discussion

  1. Are there attack scenarios where a valid publicly-trusted cert + preflight opt-in should still be blocked?
  2. Should the browser surface exempted connections in a settings panel (e.g., "Connected local devices") for transparency without friction?
  3. Would Private-Network-Access-ID / Private-Network-Access-Name headers be useful for that UI?

Related Issues & Specs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions