Skip to main content
← All rules

mcp-scan rule

Unverified package source

unverified-sourcehigh

What mcp-scan saw

This is the final else branch of the registry scanner's chain. The package is invoked through npx or npm, is not in the malicious list, is not in OFFICIAL_SERVERS, is not in TRUSTED_COMMUNITY_SERVERS, and does not start with @modelcontextprotocol/. Unscoped names report HIGH; names starting with @ report MEDIUM.

Why it fires

Unscoped npm names are first-come and permanently transferable, so an unscoped name carries no publisher identity at all. A scope at least binds the package to an npm account, which is why the same finding drops a level when one is present. This is an inventory signal, not a detection: it says the scanner has no basis to vouch for the publisher.

When this is a false positive

  • Every legitimate third-party MCP server that is not on the two hardcoded allowlists reports here. That is most of the ecosystem, so a large count of these is expected rather than alarming.
  • The allowlists carry a LAST_UPDATED date, so a package that has since been adopted into the official org still reports until the list is refreshed.
  • Your own internal package, published to a private registry, is unscoped or scoped to your org and cannot be on either list.
  • The finding fires on the resolved package name, which is the first argument not starting with a dash. A wrapper CLI whose first positional argument is not the package will be graded against the wrong string.

How to fix it

  1. Open the package on npmjs.com and check the publisher, the linked repository, and the publish history.
  2. Pin the version in your args rather than letting npx resolve latest, so the code cannot change under you after you have reviewed it.
  3. For packages you have reviewed and intend to keep, add them to allowedPackages in .mcp-scan.json. That filters out every finding below CRITICAL for that package, which is broader than suppressing this rule alone.
  4. To suppress just this rule, add 'unverified-source' to suppressRules in .mcp-scan.json.
  5. Prefer a scoped package over an unscoped one when both exist, since the scope is what ties the name to an account.