v147 · Security · Local Network Access
Compatibility Lab
Probes service worker availability, classifies page origin context, and shows which WindowClient.navigate() target URLs are blocked in Chrome 147. Provides the postMessage-based alternative for service workers that need to signal navigation to private network resources.
API probes
WindowClient.navigate() LNA enforcement matrix
| SW registration origin | navigate() target | Chrome 147 result |
|---|---|---|
| Public (https://example.com) | http://192.168.1.1/admin | BLOCKED — LNA restriction |
| Public (https://example.com) | http://localhost:3000 | BLOCKED — LNA restriction |
| Public (https://example.com) | https://example.com/other | ALLOWED — same origin |
| Public (https://example.com) | https://api.example.com/ | ALLOWED — public to public |
| Private (http://192.168.x.x) | http://192.168.1.1/admin | ALLOWED — same tier |
| Localhost (http://localhost) | http://localhost:3000 | ALLOWED — loopback to loopback |
Live context probe
Service worker + LNA context check
Click "Run probe" to inspect service worker and LNA context…
postMessage alternative pattern
/* WindowClient.navigate() LNA restriction — Chrome 147 */
/* In Chrome 147+, a public-origin SW cannot navigate a window
client to a private network URL.
Instead of navigate(), send a message to the client and let
the page handle the navigation itself (from its own origin). */
/* service-worker.js */
self.addEventListener('message', async (event) => {
if (event.data.type !== 'nav-to-private') return;
const clients = await self.clients.matchAll({ type: 'window' });
for (const client of clients) {
/* BLOCKED in Chrome 147 from a public SW: */
// await client.navigate('http://192.168.1.1/admin');
/* SAFE alternative: postMessage back to the page */
client.postMessage({
type: 'navigate',
url: event.data.url
});
}
});
/* page.js — handle the navigation message */
navigator.serviceWorker.addEventListener('message', (e) => {
if (e.data.type === 'navigate') {
window.location.href = e.data.url;
}
});
/* Classify a URL target for LNA purposes */
function isPrivateNetworkTarget(url) {
try {
const { hostname } = new URL(url);
if (hostname === 'localhost' || hostname === '127.0.0.1') return true;
if (/^192\.168\./.test(hostname)) return true;
if (/^10\./.test(hostname)) return true;
if (/^172\.(1[6-9]|2\d|3[01])\./.test(hostname)) return true;
return false;
} catch { return false; }
}
references
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗