Sign In

lna-readiness

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lna-readiness

Static CI scanner that finds requests Chrome 142 Local Network Access will silently break — before they ship. CLI + ESLint plugin + GitHub Action.

latest
Source
npmnpm
Version
0.1.0
Version published
Maintainers
1
Created
Source

lna-readiness

Find the requests Chrome 142 will silently break — before your users do.

$ npx lna-readiness src

src/print.ts
  12:3  error  fetch() to a local address (http://localhost:9100/print) will be gated by
               Chrome 142 LNA and fail silently if the user denies the prompt.
               lna/fetch-private-target
               fix: fetch("http://localhost:9100/print", { targetAddressSpace: "local" })

1 error, 0 warnings across 214 files

What changed

Chrome 142 shipped the Local Network Access permission to the stable channel in late 2025. Any request from a web page to a more-private address space now goes behind a one-time prompt:

  • localhost, 127.0.0.0/8, ::1, 0.0.0.0
  • private IPv4: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
  • carrier-grade NAT 100.64.0.0/10 (Tailscale and friends)
  • link-local 169.254.0.0/16, IPv6 fe80::/10
  • IPv6 ULA fc00::/7
  • *.local and *.localhost (mDNS)

If the user denies or dismisses the prompt, the request fails silently — no console error you can catch reliably, no rejected promise you'd expect. The LocalNetworkAccessRestrictionsTemporaryOptOut enterprise escape hatch is removed after M152, so the gate hardens through 2026.

This breaks a specific, real set of apps: POS and label-printer bridges (the QZ Tray pattern), Office/Figma/Photoshop add-ins talking to a desktop companion over localhost, IoT and router config UIs served from 192.168.x.x, camera snapshot <img> tags, and iframe embeds that reach a private-IP backend.

The fix exists in docs — a targetAddressSpace hint on fetch, an allow="local-network-access" attribute on iframes, a delegated permission from the top frame. What's been missing is a way to find which requests in a codebase need it without shipping to production and waiting for the bug reports. That's this tool.

Install

npm i -D lna-readiness
# or run it once, no install:
npx lna-readiness

CLI

lna-readiness                      # scan the source tree from the current dir
lna-readiness src app pages        # scan specific dirs/globs
lna-readiness --json               # machine-readable, for tooling
lna-readiness --markdown           # a table for PR comments / CI summaries
lna-readiness --fail-on-warning    # warnings fail the build too
lna-readiness --max-warnings 5     # allow up to 5 warnings

Exit code is 1 when there are errors (or warnings over your threshold), 0 otherwise — drop it into any CI step.

What it flags

RuleWhat it catches
lna/fetch-private-targetfetch() to a private/local host with no targetAddressSpace hint
lna/xhr-private-targetXMLHttpRequest.open() to a private/local host
lna/axios-private-targetaxios.*() to a private/local host
lna/websocket-private-targetnew WebSocket() to a private/local host
lna/eventsource-private-targetnew EventSource() to a private/local host
lna/iframe-missing-allow<iframe> at a private/local URL missing allow="local-network-access"
lna/{img,script,source,...}-private-srcsub-resource loaded from a private/local host

It scans .js/.jsx/.ts/.tsx/.mjs/.cjs, .vue, .svelte, and .html. Requests with a URL it can't resolve statically (a variable, a template with an interpolated host) are left alone — no guessing, so no noise.

ESLint plugin

Same rules, live in your editor and existing lint run (flat config):

// eslint.config.js
import lna from 'lna-readiness/eslint-plugin';

export default [
  {
    plugins: { lna },
    rules: { 'lna/no-unguarded-local-network-request': 'error' },
  },
];

GitHub Action

# .github/workflows/lna.yml
name: LNA Readiness
on: [pull_request]
jobs:
  lna:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: fernforge/lna-readiness@v1
        with:
          # paths: 'src'            # optional, defaults to the whole repo
          # fail-on-warning: true   # optional
          # max-warnings: 0         # optional

The action writes a Markdown table to the job summary and exposes errors / warnings outputs.

Programmatic

import { scan, isPrivateNetworkUrl, targetSpaceOf } from 'lna-readiness';

const { findings } = scan(process.cwd());

isPrivateNetworkUrl('http://192.168.1.20/label'); // true
targetSpaceOf('ws://printer.local:8181/');        // 'local'
targetSpaceOf('https://api.stripe.com');          // 'public'

What this does not do

It's static analysis. It catches requests whose target is a literal string in your source. It can't see a host that's only known at runtime (from config, an env var, or user input) — for those, test with the prompt denied and handle the failure explicitly. It also doesn't check that you actually hold the granted permission; a passing scan means "these calls carry the right hints/attributes," not "these calls will succeed."

Background

  • Chrome: Local Network Access and the Private Network Access → LNA transition
  • WICG spec: Local Network Access

License

MIT

Keywords

chrome

FAQs

Package last updated on 01 Jul 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts