This is the third cross-registry state report, after April's 202-server sample and June's 2,233-project Trust Middle. Before writing it I went back over how those reports were put together, because the obvious headline, Blocked is up nearly fivefold, is the kind of number that is technically true and practically misleading. Most of this report is about why, and about what I've changed in how I report so it doesn't happen again.

Everything here is reproducible. The per-project dataset, the hand review of every security block, and the analysis script are published with this report (CC BY 4.0). The June baseline is the pinned June 9 snapshot on Hugging Face.

TL;DR

2,767Projects scored
13.9%Blocked
9Blocked for security
2Held up on review

What Blocked is made of

Blocked is a hard gate: if any of five disqualifiers fires, the project is Blocked regardless of its score. The trouble is that those five disqualifiers mean very different things for the person about to install:

No license — 344 (89.6%) Archived — 31 (8.1%) Security — 9 (2.3%)
No license (344): a legal risk to you, not a code risk
GitHub finds no license file in the repository. Without one, your right to use, modify, or ship the code is unclear. Some of these declare a license in package.json or pyproject.toml, but a manifest field isn't a substitute for a license file. That matters, especially inside a company, and it's why it blocks. But nothing about the code itself is dangerous. 272 of these 344 also have a single author with little adoption or no security tooling, so they're mostly small projects (the median has 2 stars).
Archived (31): nobody is patching it
The owner has marked the repository read-only. Whatever vulnerabilities it has today, it will have forever. This is a maintenance risk that grows with time.
Security (9): the scanner, an advisory, or CI found something
A blocking pattern in the code an agent actually runs, an unpatched critical vulnerability or malware advisory on the installable version, or a CI workflow that sends a token to an outside host. This is the category people picture when they hear “Blocked”, and it's 0.3% of the corpus. I review all nine below.

If you only read a tier, you can't tell these apart. Starting with this report, I will always report Blocked broken down by these three reasons, never as a single number.

Why the number jumped

Three algorithm changes landed between the June snapshot and today. Each project picks up new rules only when it is re-scored, so their effect shows up gradually in the weekly public snapshots:

DateChangeEffect on Blocked
Jun 9June snapshot (The Trust Middle)64 blocked (2.9%) under the rules of the day
Jun 11v3.3.0: no license and archived repositories become hard blocks (before, they only lowered the tier); malware advisories fire the critical-vulnerability gatePushes up, week by week, as projects are re-scored
Jun 11v3.3.1: the supply-chain gate narrowed to actual token exfiltrationNarrows one rule
Jul 6v3.4.0: safety scanner rebuilt around behavior instead of keywords (details)Clears most false safety blocks

Here is the Blocked share (%) in each weekly public snapshot. Counts are records, before the de-duplication described below:

The July 6 spike is the false-positive epidemic that the scanner rebuild cleared the following week. The climb after that is the license rule reaching more of the corpus as projects were re-scored, plus new projects entering it. The share peaked at 14.7% on August 3 and has eased slightly since.

Two ways to check that this is a rule change and not the ecosystem getting worse:

What I got wrong in June: The Trust Middle reported 2.9% Blocked. The number was right for the rules on June 9, but I didn't say that a rule change two days later would move it, or that most of those 64 blocks came from scanner rules I later found to be too broad (59 of the 63 still in the corpus have since cleared). The June report now carries a note pointing here.

Licensing hasn't moved

Of the 287 same-record projects with no license in June, 31 (10.8%) have added one in the 15 weeks since. The other 256 are still unlicensed. Across the whole corpus, 348 projects trip the no-license rule and all of them are Blocked: 344 for that alone, and four that are also archived. Another 25 npm-only packages declare no license but aren't blocked, because the npm-only scorer doesn't apply the rule.

This is the cheapest problem in the whole dataset to fix: one file. It's also the one that moves slowest. If you publish an MCP server or skill, adding a LICENSE is most of the distance out of Blocked. If you run a registry, requiring one at publish time would clear about nine in ten Blocked entries.

The nine security blocks, checked by hand

A security block is a strong claim about someone's project, so before counting any of them I looked at the exact file, advisory, or workflow that triggered each one. The full review is in the published review file.

ProjectWhat firedVerdict
diegosouzapw/omnirouteCritical RCE advisory (GHSA-hf57-cqmx-p4gr). GitHub's reviewed range includes the npm latest; the maintainer's advisory and code show a fix in 3.8.49Range dispute
lobehub/lobehubCritical SSRF advisory (GHSA-xmwj-c75x-6346). Fixed upstream, but the fix was never published to npmHolds (npm)
packrift/packrift-mcpMCP resources and start guides hand the agent curl … | bash one-liners from the publisher's domainHolds
browserbase/mcp-server-browserbaseMalware advisory on the npm package; OSV's range matches every version, GitHub's covers only 2.1.1Range dispute
alibaba/nacosCI sends GITHUB_TOKEN with curl, but to api.github.comFalse positive
caura-ai/caura-memclawHTML comments in SKILL.md that are maintainer notesFalse positive
nvidia/nemoclawAn SPDX copyright comment in a SKILL.md; installer usage text for humans; a build scriptFalse positive
decolua/9routerInstall commands for other CLIs, displayed as text in the app's UIFalse positive
koala73/worldmonitorA defensive instruction that quotes “ignore previous instructions” as an example of what to disregardFalse positive

What holds. LobeHub's npm package: its latest version, last published in February, is inside the range of a critical SSRF advisory. LobeHub's current releases carry the fix, but it never reached npm, so anyone installing from npm gets the affected version. And packrift-mcp, a commerce server with no sign of bad intent: its MCP resources and start guides hand your agent a shell one-liner that downloads a script from the publisher's domain and pipes it to bash. The script checks a confirmation variable itself, so whatever that URL serves on the day your agent runs it is what executes. That's exactly the risk the rule exists for. The difference from NemoClaw's installer, which I count as a false positive, is the audience: NemoClaw's one-liner is usage text for a human; packrift's is delivered to an agent.

What doesn't. Five of the nine are my scanner being wrong, and they fall into four patterns: an HTML comment in an agent-facing file with nothing instruction-like in it; defensive text that quotes an attack string in order to tell the agent to ignore it; install commands shown to a human in a UI rather than executed; and a GitHub token sent to GitHub's own API. The July rebuild cleared 107 false safety blocks, but these four patterns got through it. Fixing them is next on my list, and until that ships, those five score pages still show Blocked. I'd rather tell you that than quietly drop them from the count.

The range disputes. Two blocks rest on advisories whose sources disagree about which versions are affected. OmniRoute's critical RCE advisory, as reviewed by GitHub and mirrored in OSV, covers every version up to the current npm release (3.8.50). The maintainer's own advisory for the same ID says it was fixed in 3.8.49, and the code agrees: 3.8.49 made the vulnerable endpoint loopback-only. The block follows the reviewed range until the records agree, but I don't count it as a finding that holds. Browserbase's MCP package had one malicious version, 2.1.1, in November 2025. OSV's malware record flags every version of the package; GitHub's advisory covers only 2.1.1. The current release (3.0.0, March 2026) is outside GitHub's range, and the project is archived, so it stays Blocked on that basis. Going forward, I check an advisory's range against the other sources before I call a current version affected.

Net: 2 of 2,767 projects are Blocked for a security reason that holds up. That doesn't mean everything else is safe. It means the Blocked tier is mostly a legal and maintenance signal, and the security question lives mostly in the scores. The next section is about the parts of that question the scores can't answer yet.

What the scores couldn't see this quarter

Vulnerabilities outside npm

The vulnerability signal checks the installable version against OSV.dev, CISA's Known Exploited Vulnerabilities catalog, and EPSS. But it finds the installable version by reading the project's npm package. If there isn't one, there's no lookup:

Primary languageProjectsWith a vulnerability lookup
TypeScript750479 (64%)
Python72826 (3.6%)
JavaScript233113 (48%)
Go1478 (5.4%)
Rust9814 (14%)
All projects2,767775 (28%)

MCP Atlassian shows what that means. CVE-2026-73498, disclosed in July, is an arbitrary file read in its confluence_upload_attachment tool. GitHub now lists 30 advisories against the package, 2 of them critical and 25 published on September 22. The maintainers shipped every fix before the advisory went public, and the current release, 0.23.1, is affected by none of them. So for someone installing today, the score's silence costs nothing. But it is silence, not a finding: its score, Established, 5.9, has no vulnerability signal at all, so it would read exactly the same if the current release were affected. For a project with 30 advisories in a year, that history is itself worth knowing, and the score can't see it.

My methodology page used to list PyPA and Go advisories among the sources for this signal. OSV does include them, but my engine only queried npm packages, so that was an overstatement. I've corrected the page. Adding PyPI and Go lookups is the most valuable coverage fix available, and it's queued.

Deadbugz: an attack a pre-install score can't see

In August, Pillar Security documented Deadbugz: 23 pull requests to unrelated AI and developer-tool projects, most of them adding a remote MCP server called productivity-suite to a project's configuration (four pointed at a hidden local script instead). It offers text formatting and summarization. After exactly three tool calls, its tool listings and prompts change into instructions to collect SSH keys, AWS credentials, shell history, and Kubernetes config, and to hide that from the user. None had been merged when Pillar reviewed them; four were still open.

No pre-install score would have caught it, mine included, and not because the code was hidden: Pillar found the server's source public, with the trigger in it. The problem is where the attack enters. Each pull request added an endpoint URL or a file path to a project's configuration, not an installable package, so nothing in the change prompts a pre-install lookup. Anyone who connects to the server to try it gets harmless answers for the first three calls, and the hostile behavior starts only after it's trusted. The general lesson: what a remote endpoint returns tomorrow is outside anything you can check today.

What does help:

The rest of the picture

The June report's main finding was the “trust middle”: two-thirds of projects packed into the 5–7 band and nothing above 9. With the caveat that three algorithm changes sit between the two snapshots, here's how the distribution looks now:

How I report now

These changes apply to this report and every one after it:

  1. Blocked is always broken down by reason: legal (no license), maintenance (archived), security.
  2. Every security block is checked by hand before it's counted, and the review is published.
  3. Projects, not records. Renamed and moved repositories can leave several records pointing at one project. I de-duplicate by GitHub repository ID: 2,863 records become 2,767 projects.
  4. Rule changes are separated from ecosystem change. Any comparison over time names the algorithm versions in between and gives a same-rules estimate.
  5. Inputs are pinned. Baselines are content-addressed snapshots, and each report ships its dataset, review file, and analysis script.
  6. Coverage is stated. When a signal only covers part of the corpus, like vulnerability data at 28%, I say so next to the finding.
  7. Advisory ranges are cross-checked across OSV, GitHub's reviewed advisory, and the maintainer's own advisory before a current version is called affected.
What this data doesn't tell you: These are project-level, pre-install scores. They don't observe a server's runtime behavior, so they can't see an attack like Deadbugz once it's running, and a project that scores 8 can still misbehave when an agent calls it. The corpus is what my crawler has found across the MCP Registry, npm, ClawHub, Smithery, and GitHub search: large, but not every MCP server that exists. Tiers are as of the scoring run behind the public feed generated September 24, 2026 at 13:09 UTC (algorithm 3.4.0); individual scores change daily.

Data and reproduction

Sources

Check a server before you install it

Paste any GitHub repo, npm package, or registry URL. The score page shows the reason behind any block.

Open Scanner