Research

Trust, But Verify: Our Supply-Chain Check Flagged a Package Today. We Did the Work. It Was Fine.

Trust, But Verify: Our Supply-Chain Check Flagged a Package Today. We Did the Work. It Was Fine.

A Dependabot pull request came in this morning to bump a development dependency from version 10.0.1 to 11.0.0. Routine. The kind of thing that gets merged on a glance.

Our pre-install membrane refused it. Verdict: review. Risk 45. The reason it gave was one line:

REVIVAL: silent 4y then published 18d ago (hijacked-maintainer shape)

That is a serious thing for a machine to say about somebody's work, so we went and checked it. This post is the whole decision, because a flag you cannot audit is worth nothing.

The pre-install membrane decision for one dependency on 2026-10-27. The heuristic returned verdict REVIEW at risk 45 with the signal REVIVAL: silent 4y then published 18d ago, hijacked-maintainer shape. Three manual checks followed: a matching release exists in the source repo as tag v11.0.0; the code was written by the repo owner under his own name; the commit date and the publish date both read 2026-10-09. Verdict: cleared, and still not installed, because the version already in use carries zero known vulnerabilities. The honest residual is that npm carries no provenance attestation for the release, so nothing cryptographically ties the published tarball to that repository.

What the signal actually detects

The package is node-notifier. It is a desktop notification library, about seventeen and a half million downloads a month, and it has existed for roughly fourteen years. We use it in local tooling to pop a notification when a long job finishes. It touches nothing that serves a customer.

The npm registry gives the publish history plainly. Version 10.0.1 went out on February 1, 2022. Then nothing. The next release, 11.0.0, landed on October 9, 2026 — four years and eight months of silence, broken by a major version bump.

That shape is worth stopping for. A long-dormant package with millions of weekly downloads is an attractive thing to take over, because the install base is already there and nobody is watching the repository. When a quiet package suddenly ships a major version, one of the explanations is that the account that publishes it is no longer controlled by the person who wrote it.

It is not the only explanation. It is not even the most likely one. But it is cheap to check and expensive to miss, which is the entire argument for having a gate.

The three checks

Does a matching release exist in the source repo? Yes. The repository carries a tag, v11.0.0, matching the version published to npm. An attacker who steals a publishing token does not usually bother tagging the victim's repository, because they do not have write access to it — the token publishes to the registry, not to GitHub.

Who wrote the code behind it? The most recent commit is authored by the repository owner, under his own name, on his own project. The account that published to npm matches the account that owns the repo.

Do the dates line up? The commit and the npm publish both land on October 9, 2026. A hijacked publish is typically orphaned in time — a tarball appears with no corresponding activity in the source tree.

Three for three. There are also tags in that repository for versions 10.1.0 and 10.2.0 that were never published to npm at all, which is the ordinary texture of a maintainer working in his own repo on his own schedule, and not something a thief produces.

Our read is that a maintainer came back to his project after a long break and shipped a major version. We are not calling this package compromised, and nothing in this post should be read that way. The heuristic fired on a shape. The shape had a boring explanation. That is the system working, not the system finding something.

Nobody else has noticed, in either direction

We went looking for anyone else who had written about this release. There is nothing — no advisory, no blog post, no forum thread.

More interesting: the release-tracking services have not caught up either. The public indexes we checked still list 10.0.1 as the newest version, eighteen days after 11.0.0 shipped. One of them still reports the repository's last push as June 2024.

So if you are relying on a release-monitoring dashboard to tell you when a dependency moves, there is a case here where it would have told you nothing for two and a half weeks. The registry knew immediately. The registry is the thing to watch.

We are still not installing it

Here is the part that matters, and it is not the part most people expect.

We cleared the package and we are still holding the upgrade. Not out of suspicion — out of arithmetic. The version we already run, 10.0.1, carries zero known vulnerabilities. The new version carries zero known vulnerabilities. A major version bump across a four-year gap, on a library that only makes our laptops go ping, buys us no security and hands us a pile of behavioral changes to absorb.

The reason to upgrade a dependency is that staying put costs something. Here it costs nothing. "It is probably fine" is not a reason to change code.

The honest residual

Everything above is circumstantial, and we should say so plainly.

npm carries no provenance attestation for this release. Provenance, where a publisher opts into it, cryptographically ties a published tarball to the exact repository and build that produced it. Without it, a matching tag and a matching date are strong evidence and not proof. A sufficiently careful attacker with both a publishing token and repository write access could produce everything we verified.

That is a gap in how the ecosystem works, not a mark against this maintainer or this project. The great majority of npm packages have no provenance either. We are naming it because the alternative is implying our three checks are stronger than they are.

This is the second time this month we have run into the same wall from a different direction. Trusted publishing and provenance would make this entire post a single command instead of an evening — and until adoption is broad, "we checked the repo and the dates matched" remains the best available answer rather than the right one.

Why publish a non-event

Because this is what the work actually looks like, most of the time.

Supply-chain security writing is full of the hits — the malicious package, the stolen token, the worm in the CI pipeline. The ordinary day is a gate stopping something that turns out to be innocent, and somebody spending twenty minutes proving it. If we only published the catches, we would be describing a different job than the one we do, and we would be quietly training ourselves to prefer alarming findings over accurate ones.

There is also a fairness point. A heuristic that says "hijacked-maintainer shape" about a real person's release has an obligation attached to it: go and check, and if it is clean, say so as loudly as you would have said the opposite.

Ninety-five percent confidence, and the five percent is named above: without provenance, we verified correspondence, not authenticity.

If this was worth your time — or if you came for something and did not find it — tell us in thirty seconds at analytics.dugganusa.com/nps.html. No cookies, no tracking, no third parties, and your address is hashed and never stored.


Every indicator in this post is in the feed. Free.

1.58M+ IOCs, STIX 2.1 / TAXII, 88% novel vs ThreatFox, exploited-CVE leads ahead of CISA. No credit card — a free API key in 30 seconds, and you can audit every claim above against the live endpoints.

Get your free key → analytics.dugganusa.com/stix/register