MCPSearch

Supply chain29 September 20268 min read

MCP Supply Chain Security: What Registries Forget

Why we keep the receipts

A package that backdoored an AI agent's email was pulled from npm. The backdoor is gone, the evidence is gone, and anyone asking what actually shipped is out of luck. That gap is the entire reason this archive exists.

In September 2025 a package called postmark-mcp appeared on npm. It was a near-exact copy of a legitimate MCP server for the Postmark email service, with one line added. That line blind-copied every message the agent sent to an address the author controlled. Security researchers reported it as the first confirmed malicious MCP server found in the wild.

Then it was removed. Here is what npm's registry returns for that package name today:

$ curl -s https://registry.npmjs.org/postmark-mcp

  "versions": {}
  "time": { "unpublished": { ... } }
Retrieved 29 September 2026. No versions. No tarballs. No code.

That is the correct thing for a registry to do. Leaving a live backdoor installable would be worse. But notice what it costs: the package is not just uninstallable, it is unexaminable. Every question a defender asks afterwards now has no primary source to answer it.

All of those are answerable from the bytes. None of them are answerable once the bytes are withdrawn. You are left with secondary reporting and your own lockfile.

This is not a bug in npm. It is what a registry is.

A package registry is a distribution system. Its job is to serve the current, correct, installable version of a thing. Every registry that does this well overwrites yesterday to do it, because yesterday is not what it is for.

So a registry answers exactly one question: what is published right now? It is not built to answer what was published in August, and it is not built to answer what changed between then and now. Those are historical questions, and no registry keeps history you can query, because keeping it is not the job.

For ordinary software this is mostly tolerable. For MCP servers it is not, for a specific structural reason: an MCP server is a thing an AI agent is handed credentials and told to act with. The postmark-mcp case is a neat illustration. The added line did not exploit a memory bug or escape a sandbox. It used the server's ordinary, sanctioned ability to send email, and added a recipient. The agent did exactly what it was built to do, on behalf of someone else.

When that is the shape of the risk, "what code did this thing contain on the day I gave it my API key" stops being an academic question.

What we do instead

MCPSearch asks the registries and catalogues the same questions every day, writes down the answers, and never overwrites them. Where an artifact can be retrieved, its bytes are stored and addressed by the SHA-256 of those bytes, so a stored object cannot disagree with its own address.

The record, as of 29 September 2026

Collection began
8 August 2026
Daily snapshots
51
Servers observed
71,595
Versions recorded
402,077
Artifacts archived
533,110
Bytes held
5.60 TB
Sources observed daily
Official MCP Registry, GitHub, Docker, Smithery, Cline, npm, PyPI

Every one of those figures is a count of things actually observed, not an estimate. You can check any of them in the portal.

The part we have to say out loud

We could not have caught postmark-mcp. That incident was September 2025. This archive started collecting on 8 August 2026, eleven months later. There was no record then, and we cannot make one now.

That is not a caveat we are burying at the bottom. It is the single most important property of a historical record: it cannot be back-filled. Every day the collection does not run is a day that is gone permanently, which is why the daily crawl is the one job in this system that everything else is allowed to be sacrificed for.

It is also why "we started" is the whole of the pitch. If the next postmark-mcp ships tomorrow, the questions at the top of this page will have answers that are dated, hashed and checkable, because today's bytes were written down today.

A worked example of how we can get this wrong

While writing this post we searched our own index for the incident and found a live record for activecampaign/postmark-mcp: five versions recorded, five artifacts archived, first observed 17 August 2026. The obvious sentence to write was "we have the malicious package archived."

That sentence would have been false. The malicious package was published by an unrelated npm account impersonating Postmark. ActiveCampaign owns Postmark, so the record we hold is the legitimate repository, the party that was impersonated. Publishing that claim would have connected a real company to a backdoor it was the target of.

We are telling you this because it is the failure mode of every security blog that sits on top of a large dataset. A string matches, the dates look close, and a plausible sentence writes itself. So there is a rule here, and it is a checklist item rather than a principle: no record from this archive is named alongside a security incident until the identity is confirmed against the primary disclosure: publisher account, package name and registry, not a matching string.

What this archive does not do. It records observations. It does not assess whether software is safe, and a difference between two observations is a fact about bytes, not a conclusion about intent. Where this blog reports an incident, the finding belongs to the researchers who disclosed it and is linked to their work. Where it reports an observation, the observation is ours and you can verify it in the portal. The two are never blended.

Wider context, and what we will not repeat

The postmark-mcp case is not isolated. Researchers have reported a substantial wave of MCP-related vulnerability disclosures through 2026, and formal guidance has started to appear, including a security design document published via the US Department of Defense and a Cloud Security Alliance research note. Authzed maintains a running timeline of publicly reported MCP incidents, which is a good place to start if this is new to you.

We deliberately have not quoted the headline percentages circulating about how many MCP servers contain a given flaw. We went looking for the primary source behind one widely repeated pair of figures and could not confirm them in the paper they were attributed to. Numbers on this site come with somewhere to check them, or they do not appear.

What comes next

This blog will run weekly, in two strands. One is the record itself: what appeared, what changed, what stopped being listed, drawn straight from the daily observations. The other is what is happening in MCP security more broadly, with the archive brought to bear where it genuinely has something to add, and an explicit note where it does not.

If you want to look at the data behind any of this, the portal is open and needs no account. If you want to know exactly how the observations are made and what they cannot tell you, that is on the methodology page, including the limitations.

Next: The record: week ending 28 September · All posts