DEV Community

Štefan Bohumel
Štefan Bohumel

Posted on Edited on Originally published at repoxray.pages.dev

RepoXray – Zero-upload supply-chain, slopsquatting, and MCP secret scanner

Hi, I built RepoXray (https://github.com/Ra9mirez11/repoxray) to audit repositories before running npm install or attaching AI coding agents.

Why I built it:

  1. AI slopsquatting: LLMs regularly hallucinate plausible package names. If a package returns 404 on npm today, an attacker can register it tomorrow. RepoXray checks live registry existence, package age (<21 days), OSV.dev advisories (resolving exact package-lock.json versions), and risky postinstall shell/network hooks.
  2. MCP & .env exposure: Many repos now include .mcp.json or claude_desktop_config.json with plaintext tokens or unpinned npx -y remote execution, plus .env files readable by coding agents without .aiignore.
  3. Privacy & footprint: The web scanner runs 100% in browser RAM via File System Access / Drag-and-Drop APIs (0 bytes uploaded to any server). The CLI (npx rxray .) is a 19 KB bundle with 0 runtime dependencies.

It also calculates active LLM context bloat and compiles tailored .aiignore + AGENTS.md guardrails and a remediation prompt. Would appreciate technical feedback on false positives or missing detection rules.

Top comments (7)

Collapse
 
x1y1co profile image
X1Y1 •

Nice scope. Three rules from running a similar check over 10,659 public MCP configs this weekend, in case they help:

  1. npm security placeholders. A version like 0.0.1-security means npm removed a malicious package under that name. Configs still call mcp-server-fetch, -git, -notion, -postgres and -redis through npx; all five had malware advisories this year (MAL-2026-5476 and others). Worth flagging separately from a normal 404 or a vuln.
  2. Wrong registry. The official fetch, git, sqlite and time servers are Python packages for uvx. The npm-style guesses (.../server-fetch under the official scope) were the most common missing names we saw.
  3. Scope owner, not just existence. A 404 under a scope the vendor does not own is a different risk from a 404 under one it does. Anthropic publishes as @anthropic-ai, while @anthropic belongs to someone else, and configs still reference @anthropic/... names.

One parser note: some configs write command as an array instead of a string, which crashed our first pass.

Collapse
 
ramirez911 profile image
Štefan Bohumel •

Gold-tier field data—thank you for sharing the takeaways from that 10,659-config scan.

Just shipped all four in rxray@0.2.0 (and live on repoxray.pages.dev), with credit to you in the changelog:

  1. SC-NPM-SECURITY-TOMBSTONE: Explicitly flags 0.0.1-security / *-security / "security holding package" tombstones (mcp-server-fetch, -git, etc.) as Critical malware-takedown artifacts rather than letting HTTP 200 pass or lumping them into generic vulns.
  2. SC-MCP-WRONG-REGISTRY: Flags npm references (@modelcontextprotocol/server-* and unscoped mcp-server-*) for the Python-only uvx reference servers (fetch, git, sqlite, time, sentry) and points directly to uvx mcp-server-<name>.
  3. SC-SCOPE-IMPERSONATION-RISK vs SC-HALLUCINATED-VENDOR-PKG: Separates 404s inside verified vendor-owned org scopes from open/unverified 404s, and explicitly flags lookalike non-vendor scopes like @anthropic/* (vs @anthropic-ai/*) and @mcp/* (vs @modelcontextprotocol/*).
  4. Hardened the MCP config parser (mcpParser.ts) to normalize command as both string and string array (["npx", "-y", ...]) and feed extracted MCP npx/bunx/uvx packages straight into the live registry check.

If you spot any other edge cases from your dataset, I'd love to add them.

Collapse
 
x1y1co profile image
X1Y1 •

Quick turnaround, thanks for the credit. Two more from the same data. Git installs: npx github:owner/repo or uvx --from git+https://... with no commit SHA are unpinned too, and a registry check skips them because there is no registry entry. And keys sitting in the env block of the config itself, which is where most of the likely-real tokens we found were. Do you flag env values today, or only files like .env?

Thread Thread
 
ramirez911 profile image
Štefan Bohumel •

On the env block question: yes, we already inspect structured "env": { ... } entries inside MCP configs via SEC-MCP-PLAINTEXT-ENV (allowing dynamic references like ${VAR}, ${env:VAR}, and op://... while redacting literal values). Prompted by your question, I just tightened that pass in rxray@0.3.2 to also catch Docker-style -e KEY=VAL args, cover mcp_config.json / cline_mcp_settings.json / roo_mcp_settings.json / .zed/settings.json, add prefixes for Notion (ntn_), Linear (lin_api_), Tavily (tvly-), Firecrawl (fc-), Perplexity (pplx-), Figma (figd_), and GitLab (glpat-), and filter out non-secret config keys (NODE_ENV, paths, MAX_TOKENS, public base URLs).

Also shipped SC-MCP-UNPINNED-GIT (and SC-UNPINNED-GIT-SPEC for manifests) in 0.3.2:

  • Catches npx github:owner/repo, bare npx owner/repo shorthand, npx git+https://..., and uvx --from git+https://... unless pinned to a full 40/64-hex commit SHA (#<sha> for npm/npx, @<sha> for uvx/pip) — flagging both floating HEAD and mutable branch/tag refs like @main.
  • Prevents Git specifiers from falling through into the npm/PyPI registry lookup (which previously risked false 404s on github:owner/repo or truncating git+https://... at +).

Appreciate you sharing these — updated your credit note in the changelog and web UI as well.

Thread Thread
 
x1y1co profile image
X1Y1 •

That was quick. Ours only checks one pasted config at a time, so a repo-wide scan running the same rules covers what we don't. If we find more patterns on the next rescan, we will post them here.

Thread Thread
 
ramirez911 profile image
Štefan Bohumel •

Makes total sense — single-config inspection and repo-wide/pre-commit scanning complement each other nicely.

Whenever your next rescan surfaces new patterns, drop them here or on GitHub (I added a dedicated Detection Rule issue template at github.com/Ra9mirez11/repoxray/iss...). Also, if you have a public URL or write-up for your single-config checker/research, let me know and I will link it directly from your @X1Y1 contributor card on RepoXray.

Thread Thread
 
x1y1co profile image
X1Y1 •

Thanks. The checker is at x1y1.co/mcp-config-check and the write-up with the numbers is x1y1.co/journal/public-mcp-configs-checked/. I'll use the issue template when the next rescan turns up something new.