Build1 distinct publisher2 min readPublished
Install hooks and .pth files execute before your first import, which puts the useful controls in resolver precedence and environment scope rather than in a test suite that passes either way.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Run `npm install` and any package in the tree can execute a postinstall hook during installation, before your application code runs [7]. Python has the same position available through a `.pth` file in `site-packages`, which the interpreter executes at startup, ahead of the first import [8]. The install line therefore grants execution inside a process that already inherits its environment, including `AWS_SECRET_ACCESS_KEY` and `GITHUB_TOKEN` [5], and nothing in the default flow reads the code first [6].
Resolution is the configurable half. npm and PyPI prefer the public version when its number is higher than the one in the internal private registry, so publishing `[email protected]` reaches any pipeline that depends on that name and has no registry lock [4].
The rate matters more than the totals. About 119,000 downloads across roughly 40 minutes is near 2,975 a minute [2], and an archive covering 434,000 pipeline runs works out to about 3.6 runs' worth of credentials per download [3]: one install line landing in a job that reruns, each run handing over a fresh set.
Two payload shapes are in play, the interception proxy that makes the real call and exfiltrates alongside it, and the facade that fabricates a response and never contacts the API at all [17]. The Paysafe packages skipped machines with fewer than two CPU cores or with VM-indicative usernames [15], which is a package fingerprinting the runner more carefully than the runner fingerprints the package. Obfuscation rotated per file, so no two of the 17 shared a hash [14].
Now transfer. Sonatype's Q1 2025 count was 17,954 malicious packages, 56% of them classified as data exfiltration [1], which is roughly 10,054 exfiltration packages in a single quarter [1], and the writeup puts Q2 volume growth at 188% year over year [3]. Those are counts of what was published, not of what your resolver will fetch. For that population to reach a given build, the resolver has to be allowed to reach it: floating version ranges, public-over-private precedence left at the default, lifecycle hooks enabled. A build that installs pinned hashes from an internal mirror with hooks disabled is still exposed to the maintainer-account compromise path, which is how the LiteLLM release shipped [9], but not to the confusion path.
One caution on the source. It reports counts, execution primitives and detection times, and credits Sonatype, Socket.dev, JFrog and THN, but it measures no control's effectiveness, and it dates the LiteLLM and Paysafe cases to 2026 while opening with 2025 telemetry. On what it does establish, the only gates sitting ahead of execution are which registry answers the resolve and what the environment holds when the hook fires.
Ranked by verification strength, evidence, and original report placement.
In Q1 2025 Sonatype tracked 17,954 malicious packages, with 56% classified as data exfiltration.
In Q2 2025, over 4,400 packages specifically targeted API tokens.
Total malicious package volume grew 188% year-over-year in Q2 2025.
npm and PyPI prefer the public version when its version number exceeds the internal private registry version; an attacker publishing [email protected] to npm reaches any pipeline depending on that name without a registry lock.
STRIPE_SECRET_KEY, AWS_SECRET_ACCESS_KEY and GITHUB_TOKEN live in environment variables the entire process inherits, accessible to the SDK before any application code runs.
The Solana FakeFix campaign, documented by JFrog, used postinstall lifecycle hooks as the execution primitive; the hooks ran during npm install or pip install, before any application code ran.
Distinct publishers with included, body-backed reporting in this cluster.
1 article · September 5, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
science
A backdoored litellm release turns every CI job that installed it into a credential incident1 distinct publisher
security
The 2,500-org compromise was a Trivy problem. LiteLLM was the closing act.1 distinct publisher
build
Every one of thirteen named 2025-26 incidents ran on a credential that still worked1 distinct publisher
security
A free Artifactory plugin can hold npm and PyPI versions until they age in public1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
One account, every number relayed
Two kinds of material sit side by side here and they do not deserve the same weight. The mechanics are checkable by anyone with an interpreter: .pth files in site-packages run at startup, install hooks run before imports, and both installers prefer the higher public version. The figures are not. Sonatype's counts, JFrog's Solana work and Socket.dev's Paysafe analysis are named but never linked, and the LiteLLM chain that gives this story its headline, from Trivy's CI credentials to the 40-minute quarantine and the 434,000 pipeline runs, carries no attribution at all.
Attackers get a tally, defenders get a blank
As a technique in service, this is well past demonstration: seventeen live packages across two registries, four Paysafe versions distributed inside six minutes, and roughly 119,000 pulls of a single poisoned LiteLLM release. The half our coverage never counts is defensive. Nothing in the piece measures how many teams pin a private registry, scope CI credentials to a single publish, or watch outbound destinations during an SDK call, so uptake of the fixes it recommends is unknown.
Mechanics hold, the verdict runs ahead of them
Modest overstatement, and it is concentrated in the conclusions rather than the technical body. Four versions shipping before a six-minute flag argues that reactive detection is imperfect at that latency; the piece reads it as reactive detection being not viable at all. Per-package hash rotation defeats signature blocklists specifically, which the text acknowledges and then generalises. On the other side, the story understates its own weakest point: the LiteLLM numbers doing the most rhetorical work are the ones with no source attached.
Counted by the firms selling the counting
Sonatype supplies the volume telemetry and Socket.dev the campaign detail, and both sell the scanning that findings of this shape justify buying. That does not make the numbers wrong, and Socket.dev's six-minute flag is a detail that cuts against its own product's sufficiency. What is missing is the other side of the table: no registry operator, no LiteLLM or Trivy maintainer, and no statement of whether the author has a stake in supply chain tooling.
Sure on the mechanism, shaky on the scale
Split confidence is the honest reading. The behaviour of postinstall hooks, .pth files, resolver precedence and response-only assertions can be confirmed without trusting the author at all, and that is most of what a reader would change practice on. Every quantity, from 17,954 packages to 119,000 downloads to 434,000 pipeline runs, comes through one post that names some sources and not others, and none of it has been corroborated elsewhere in our coverage.