npm Patch Desk

Socket Vulnerability Research Engineer, independent prototype
Built by Edward Tay for a job application. Not affiliated with, endorsed by, or operated by Socket. Advisories come live from OSV, download counts from the npm API, EPSS from FIRST. The backport and its verification are my own work.

Which patches are worth building this week

A patch target is one package release line with at least one advisory and no fixed release in that line. Its users can only move by a breaking upgrade, or by a patch. The queue ranks targets by weekly downloads still on vulnerable versions of that line, severity, EPSS and how many advisories one patch would close.

TargetScoreWeekly downloads on lineLatest in lineAdvisoriesWorst open advisory

minimatch GHSA-g3hv-75wg-m249: the range is wider than the bug

Published 30 October 2026 (CVE-2026-118764). A crafted glob makes firstPhasePreProcess() keep doubling its pattern list, then secondPhasePreProcess() compares every pair. The only fixed release is 11.0.1.

LineWeekly downloadsAdvisory saysPublished code says

Reachability

  • The bug runs only at optimizationLevel 2 or higher. minimatch's own default is 1.
  • glob 9, 10 and 11 construct minimatch with optimizationLevel: 2 and depend on minimatch ^8, ^9 and ^10. Any app that passes a user-supplied pattern to glob() on those versions reaches the bug.
  • Direct minimatch callers at the default level do not reach it.

Backport, verified on every version people install

Socket patches exact versions, so one advisory fans out. Every 7.x to 10.x version with at least 10,000 weekly downloads was patched and gated:

VersionWeekly downloadsExploit, originalExploit, patchedUpstream testsDifferential and fuzz

Exploit: 14 repeats of **/../a/b at optimizationLevel 2, in a child process with a 20-second limit. Upstream tests: the four cases from test/preprocess-limits.ts in fix commit 77a0f5c, ported. Differential: 14 ordinary patterns x 15 paths x levels 0 to 2. Fuzz: 1,000 seeded random patterns x 20 paths x 3 levels, compared with the unpatched build. CJS and ESM builds both patched; each record's afterHash matches the build that passed.

The patch (9.0.9, CommonJS build; ESM is the same three edits)

Patch records, in the shape of Socket's patch API

One record per exact version: the PURL and each changed file's SHA-256 before and after. The upstream version number is kept, as Socket's hosted npm patches do; the tarball integrity changes instead.

PURLFilebeforeHashafterHash

What I would file

  • A range correction to the GitHub advisory: introduced 7.0.0, with the evidence above, so 3.x to 6.x users stop getting a false alert.
  • A note to glob's maintainer that glob 9 to 11 inherit the bug through optimizationLevel: 2.
  • Patch records for 7.4.9, 8.0.7, 9.0.9 and 10.2.6 first, then for every other version on those lines with real downloads: about 500 million weekly downloads have no in-line fix.

Run the backport in your browser

Both lanes download minimatch 9.0.9 from the npm CDN. The right lane applies the same three edits as the patch script to the module source, then loads it. Each lane runs in its own worker with a 30-second limit.

minimatch 9.0.9 as published
-
minimatch 9.0.9 with the backport
-

Lockfile triage

Paste a package-lock.json (v1 to v3), yarn.lock or pnpm-lock.yaml. Every dependency is checked against OSV in one batch call. Each finding gets one of three actions: upgrade inside the same line, a breaking upgrade, or a patch because no fixed release exists.

DependencyAdvisorySeverityAction

Method

  • Data. OSV /v1/query per package and /v1/querybatch for lockfiles; npm /versions/<pkg>/last-week for downloads per exact version; the registry's abbreviated metadata for the version list; FIRST EPSS. All read from your browser. A snapshot from 4 November 2026 loads first so the page works offline.
  • Range maths. OSV SEMVER events (introduced, fixed, last_affected) evaluated with a semver comparator that orders prereleases correctly. Release lines follow semver: the major, or the minor for 0.x.
  • Backport demand. For each advisory and line, the weekly downloads of affected versions in a line with no fixed release. Score = (log10 downloads minus 3) x severity weight x (1 + 4 x EPSS), plus up to 100% for more advisories one patch would close.
  • Corrections. Where the published code shows the advisory range is too wide, the correction is applied and marked, with the evidence.
  • Socket coverage. A small Pages Function proxies Socket's public patch API (it sends no CORS headers) so the queue detail can show which advisories already have a free Socket patch, and for which versions.
  • Patch QA. Every backport runs four gates: the exploit gets fast, upstream's tests for the fix pass, a differential run on ordinary inputs and a seeded fuzz run (60,000 checks) both show no behaviour change. The scripts are in the repository with the diffs.
  • Tests. node tests/run.mjs covers the semver comparator, range evaluation, demand, corrections, lockfile parsing and the in-browser patch transform.
Edward Tay, 2026. Independent prototype for a job application.