v147 · shipped · security · service workers
Local Network Access restrictions on Service Worker WindowClient.navigate()
Chrome 147 extends Local Network Access (LNA) enforcement to navigations initiated by service workers via WindowClient.navigate(). When the WindowClient is a subframe, any attempt to navigate it to a local/private IP address now triggers the same LNA checks as other restricted request types.
windowClient.navigate(url) where url resolves to a local or private address (loopback, RFC 1918, link-local) may now be blocked in Chrome 147 when the WindowClient is a subframe served from a public origin. Main-frame navigations are not affected.
at a glance
| Shipped in | Chrome 147 (desktop, Android) |
|---|---|
| Status | Enabled by default |
| Affected API | WindowClient.navigate() from service workers |
| Spec | WICG Local Network Access spec |
| ChromeStatus | 5172375182245888 — Local Network Access restrictions on Service Worker WindowClient.navigate() |
Status and scope divergence, both sides reported rather than resolved (fetched 2026-10-06): this page records
the feature as shipped in Chrome 147 with the Local Network Access check enabled by default, while the ChromeStatus
record for feature 5172375182245888 still reads status “Proposed” with
is_released false, and that record also lists Firefox as Shipped/Shipping pointing at a Mozilla
support article, where this page’s support table says Firefox has no position. A scope limit is carried with
it: the WICG Local Network Access specification this page cites never names WindowClient.navigate()
— its restricted-request surface is fetch-type requests — so this is Chromium enforcement reusing the
spec’s model rather than a spec-defined surface.
why it exists
Chrome's Local Network Access protections prevent public websites from silently reaching devices on the user's private network. Earlier work applied LNA checks to fetch() requests initiated from service workers. However, service workers can also trigger subframe navigations via WindowClient.navigate() — and that path was not covered. A compromised or malicious service worker from a public origin could navigate an embedded subframe to a local admin interface or device URL without the user's knowledge. Chrome 147 closes this hole by applying the same initiator-based LNA logic to WindowClient.navigate() calls.
Only subframe WindowClient navigations are affected. Chrome does not currently enforce LNA restrictions on main-frame navigations.
what changes
When a service worker calls windowClient.navigate(url):
- If the
WindowClientis a main frame: no change, no LNA check is applied. - If the
WindowClientis a subframe and the target URL resolves to a local/private address:- Chrome uses the
WindowClient(i.e. the subframe's origin) as the navigation initiator. - If the initiator is a public origin, the LNA permission check is triggered.
- If the user has not granted permission, or the context is not secure, the navigation is blocked.
- Chrome uses the
// A service worker navigating a subframe WindowClient to a local-network address.
// Chrome 147 uses the subframe's origin as the navigation initiator, so this
// call triggers the Local Network Access permission check and may be blocked.
self.addEventListener("message", async (event) => {
const client = await self.clients.get(event.source.id);
if (client?.frameType === "nested") {
await client.navigate("http://192.168.1.1:8080/status");
}
});
Affected address ranges
| Address range | Examples |
|---|---|
| Loopback | 127.0.0.1, localhost, ::1 |
| Private (RFC 1918) | 10.x.x.x, 172.16–31.x.x, 192.168.x.x |
| Link-local | 169.254.x.x, fe80::/10 |
browser support
| Browser | Support |
|---|---|
| Chrome 147+ (desktop, Android) | Enabled by default |
| Firefox | No position |
| Safari | No position |