Five Open PRs. drizzle-kit Still Ships @esbuild-kit/esm-loader.

The package you depend on can be healthy. What it pulls in might not be.

drizzle-kit has 8.2 million weekly downloads, 4 npm publishers, provenance enabled, and a behavioral score of 83. Looked at on its own, it’s fine.

npm install drizzle-kit also pulls in @esbuild-kit/esm-loader. That package’s GitHub repo is archived. Its last npm publish was 17 September 2023—981 days ago at the time of writing. It has one npm publisher. It gets 7.5 million weekly downloads through Drizzle and a few other consumers.


The numbers, side by side

Both packages scored through Commit’s behavioral audit:

Package Score Publishers Downloads/wk Days since publish Risk
drizzle-kit 83 4 8.2M 69
@esbuild-kit/esm-loader 65 1 7.5M 981 HIGH + WARN

drizzle-kit’s own metrics look healthy. The transitive dep does not. @esbuild-kit/esm-loader trips two risk flags: sole npm publisher with >1M weekly downloads, and no release in 12+ months. The repo is archived. The sole maintainer moved their work to tsx over two years ago.


The community already knows

This isn’t a surprise to anyone reading Drizzle’s issue tracker. At least five open pull requests propose dropping or replacing @esbuild-kit/esm-loader:

  • PR #3498 — opened 6 November 2024. Move @esbuild-kit/esm-loader to devDependencies.
  • PR #4250 — opened 10 March 2025. Remove @esbuild-kit/esm-loader.
  • PR #4430Replace with tsx.
  • PR #4819Replace @esbuild-kit/esm-loader with tsx.
  • PR #5689 — opened 27 April 2026. Drop deprecated @esbuild-kit/esm-loader dependency.

Plus a tracked security issue, #5481, opened 13 March 2026 with 15 thumbs-up reactions and 6 comments. All five PRs are open. The oldest has been open for 18 months. The issue has been open for 73 days.

This isn’t a swipe at Drizzle. The team has shipped a serious ORM and is responsible for an enormous surface area. The point is structural: a healthy package can ship transitive risk for years while the community files PRs that nobody merges. The risk lives one npm install below the surface where most people stop looking.


Why this pattern keeps recurring

The interesting thing about @esbuild-kit/esm-loader isn’t that one person published it. Plenty of small dependencies have one maintainer and do fine. The interesting thing is that the maintainer themselves told everyone to stop using it. The repo is archived. The replacement (tsx, by the same author) is right there.

That makes this a quieter version of the event-stream pattern: a package whose maintainer’s engagement has expired, still being shipped to millions of machines every week. The credential surface narrows to one person who no longer has any active reason to defend it. If that credential is compromised tomorrow, every drizzle-kit install pulling a fresh tree, plus every other downstream consumer of @esbuild-kit/esm-loader, ships whatever the attacker pushes.

Drizzle’s own score doesn’t tell you this. Neither does npm audit, because there’s no CVE: nothing is broken yet. The behavioral signals—archived repo, single publisher, no release in 981 days—catch the risk before there’s a vulnerability to scan for.


What this means for your stack

If drizzle-kit is in your devDependencies, you’re shipping @esbuild-kit/esm-loader into your CI and local dev environments. It runs every time you generate or push migrations. The blast radius is whatever credentials and source those environments touch.

The fix on Drizzle’s side is straightforward—tsx is a drop-in replacement, written by the same author, actively maintained, score 86. Five PRs are already written. Until one merges, the working answer for users is to pin drizzle-kit behind a vetted lockfile and watch for changes, or vendor the relevant CLI steps.


Find this in your own dependencies

The full transitive tree, scored:

npx proof-of-commitment --file package-lock.json

Or for one package and its direct dependencies via the web audit. The output flags packages with archived repos, single publishers, and stale release cadence—the three signals that combined into the example above.

None of this requires waiting for a CVE. Behavioral signals are available the moment the conditions are true. Right now, @esbuild-kit/esm-loader is on day 981.