How the Dependency Scanner Works

Last reviewed . Describes the scanner at /scanner and the lockfile check in the get started flow.

In one sentence: the scanner reads the exact package versions in your lockfile and reports which of them fall inside the affected range of a published security advisory. It does not assess whether your app is secure.

Supported files

FileSupportedNotes
package-lock.jsonYeslockfileVersion 1, 2, and 3. An older npm-shrinkwrap.json uses the same format and is accepted, though npm 12 no longer reads that file; rename it to package-lock.json.
yarn.lockYesYarn Classic (v1) and Yarn Berry lockfiles.
package.jsonNoIt lists version ranges such as ^0.74.0, not the versions that were installed, so it cannot be matched against advisories.
pnpm-lock.yaml, bun.lock, bun.lockbNonpm install --package-lock-only creates a package-lock.json, though its resolved versions can differ from what pnpm or Bun installed.
Podfile.lock, Gradle lockfilesNoNative iOS and Android dependencies are outside this scanner.

An unsupported or malformed file is rejected on the upload step with the reason and what to upload instead. It is never scanned.

How matching works

  1. Read installed versions. Every package entry with an exact version is collected, including transitive dependencies. npm aliases are resolved to the real package name. The same version installed at several paths is checked once.
  2. Skip what is not on the npm registry. Packages installed from git, local folders, links, or workspaces have no registry advisories. They are counted and shown as not checked.
  3. Look up advisories. Names and versions go to our Cloudflare Worker, which posts them to the npm registry's bulk advisory endpoint, the same endpoint npm audit uses. Each returned advisory includes an affected version range, and each installed version is tested against it. A range we cannot evaluate is treated as affected, so a parsing gap can over-report but never hide a match.
  4. Fall back to OSV.dev. If the npm lookup fails after one retry, your browser queries OSV.dev directly in batches of at most 1,000 packages, follows OSV's pagination, and fetches each advisory's details for its title and severity.
  5. Merge duplicates. An advisory that appears several times for one package, for example once per affected range, is shown once with every affected version.

Scan states

StateWhenWhat you see
UnsupportedThe file is not a supported lockfile, or has no registry packages.An error on the upload step. No scan runs and no email is requested.
CompleteEvery registry package version was checked.The report, after you enter a work email.
PartialSome lookups failed after retries.The report, marked incomplete, with how many package versions were checked. Matches cover checked packages only.
FailedNo package version could be checked.A failure message with a retry. No counts, no report, and no email request.

A partial or failed scan is never shown as a clean result, and the scan summary we receive with your email carries the same status.

What severity means

Severity (critical, high, medium, low) is the rating published with each advisory. GitHub assigns severity for advisories in the GitHub Advisory Database using CVSS. If OSV.dev details cannot be retrieved, the scanner shows the severity as unknown instead of guessing.

Severity describes the vulnerability in general, not the risk to your app. The CVSS user guide says it directly in a section titled "CVSS Measures Severity, not Risk." Three separate questions decide what to fix first:

What a result does not tell you

Differences from npm audit

The primary lookup uses the same bulk advisory endpoint as npm audit, so the advisories that match should agree. The scanner differs in presentation and scope: it lists each advisory once per package rather than per install path, and it does not compute fixes, mark dependent packages as vulnerable, or filter development dependencies. For Yarn projects, yarn audit (Classic) and yarn npm audit (Berry) are the local equivalents.

What is sent and stored

StepDataSent to
UploadNothing. The file is read in your browser and never uploaded.No one
ScanPackage names and versions, and the detected React Native versionOur Cloudflare Worker, which sends the names and versions to the npm registry
Scan, if the npm lookup failsPackage names and versionsOSV.dev, directly from your browser
Opening the reportYour email, the scan status and counts, lockfile format, React Native version, and the page addressOur Worker, which notifies our team

We never store your lockfile or your full package list. When scan storage is enabled on our Worker, a scan that matched advisories is kept with its matched advisories, counts, and basic request details (country, browser user agent, referring page) for up to 90 days. Leads, meaning your email with the scan summary, are kept for up to 24 months. The scanner page may also send anonymous usage events, such as a scan's status, to our analytics and ad measurement tools. See the privacy policy.

How the scanner is tested

The parser and report logic run against lockfiles generated from one synthetic project by npm 6 (lockfileVersion 1), npm 11 (lockfileVersions 2 and 3), Yarn 1.22, and Yarn 4.9, plus hand-written edge cases for aliases, git and workspace packages, and unsupported files. Advisory responses recorded from the npm registry and OSV.dev are replayed through the real Worker code. The tests also simulate a failed primary lookup, a failed fallback, a partial batch failure, pagination, missing severity details, and timeouts, and check that none of them can produce a clean result. They run on every site build. The sample report is generated by the same code from a synthetic lockfile.

Sources

Run the Scanner →