Skip to content

fix(scanner): reject non-registry package specs before fetch (MCP-2442 P0 ACE)#673

Closed
Dumbris wants to merge 1 commit into
mainfrom
fix/mcp-2442-scanner-fetch-spec-validation
Closed

fix(scanner): reject non-registry package specs before fetch (MCP-2442 P0 ACE)#673
Dumbris wants to merge 1 commit into
mainfrom
fix/mcp-2442-scanner-fetch-spec-validation

Conversation

@Dumbris

@Dumbris Dumbris commented Jun 15, 2026

Copy link
Copy Markdown
Member

Summary — CRITICAL/P0 arbitrary code execution on the scan path

From the Codex security audit (MCP-2442). resolveFromPackageFetch handed the server-configured package spec to npm pack / uv pip download / pip download unvalidated. For a uvx/pipx server configured with a local-path, git+/VCS, URL, or file: spec, the download still executes the package's build backend (setup.py / PEP 517 egg_info) even with --only-binary=:all: / --ignore-scripts — arbitrary code execution during a supposedly static scan.

--only-binary=:all: only protects bare registry-name specs (a wheel-less registry package falls back cleanly). It does not protect a non-registry spec, which is the whole bug.

Fix

New isBareRegistrySpec(spec, ecosystem) gates both ecosystems in resolveFromPackageFetch before any download:

  • Accept: bare PEP 503 (python) / npm registry name, optionally scoped (@scope/name) and version-pinned (==, >=, @1.2.3).
  • Reject: paths (./, ../, /abs, ~, \, ..), git+/hg+/svn+/bzr+, URLs (://), file:, PEP 508 direct references (name @ url), and shell metacharacters → caller falls back to tool_definitions_only (no fetch, no execution).
  • The safe registry path (wheel-only download / npm pack --ignore-scripts) is unchanged — no regression.

Tests (TDD)

  • TestIsBareRegistrySpec — accept/reject table for both ecosystems (incl. @scope/../escape, git+ssh, direct refs).
  • TestResolveFromPackageFetch_RejectsNonRegistrySpec — git+/local/URL specs short-circuit with a rejection before any download command runs.
  • TestResolveFromPackageFetch_LocalPathSpecDoesNotExecute — execution-marker proof: a local-path uvx spec whose setup.py would write a marker never executes (marker absent), independent of whether uv/pip is installed.

Verification

  • go build ./...
  • go test -race ./internal/security/scanner/ ✅ (new + existing fetch tests, registry path unchanged)
  • ./scripts/run-linter.sh0 issues ✅ · gofmt clean ✅

Branched from origin/main per the issue note (local tree was divergent).

Related #MCP-2442

@Dumbris

Dumbris commented Jun 15, 2026

Copy link
Copy Markdown
Member Author

Tracking / coordination note

  • QA dispatched → MCP-2447 (QATester, SHA-pinned 88f28a0b).
  • ⚠️ Could not update the source issue MCP-2442: it's held by an orphaned stale checkout (prior run 1ebd3be5, activeRun: null) — release/checkout/comment all 409 Issue run ownership conflict. The deliverable isn't lock-gated (this PR is the fix). MCP-2442 needs a CEO close / lock-clear once fix(scanner): reject non-registry package specs before fetch (MCP-2442 P0 ACE) #673 merges (same orphaned-lock pattern as MCP-2149, which the CEO cleared directly).

This is a P0 ACE fix — please prioritize review/merge.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 15, 2026

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: acbfbcc
Status:⚡️  Build in progress...

View logs

@codecov-commenter

codecov-commenter commented Jun 15, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 96.00000% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/security/scanner/package_fetch.go 96.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: fix/mcp-2442-scanner-fetch-spec-validation

Available Artifacts

  • archive-darwin-amd64 (28 MB)
  • archive-darwin-arm64 (25 MB)
  • archive-linux-amd64 (16 MB)
  • archive-linux-arm64 (14 MB)
  • archive-windows-amd64 (28 MB)
  • archive-windows-arm64 (25 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (21 MB)
  • installer-dmg-darwin-arm64 (19 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 27522692998 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

Codex audit (MCP-2442): resolveFromPackageFetch passed the server-configured
package spec to npm pack / uv pip download / pip download UNVALIDATED. For a
uvx/pipx server with a local-path, git+/VCS, URL, or file: spec, the download
STILL executes the package's build backend (setup.py / PEP 517 egg_info) even
with --only-binary=:all: / --ignore-scripts — arbitrary code execution during
a supposedly static scan.

Add isBareRegistrySpec(spec, ecosystem) and gate both ecosystems in
resolveFromPackageFetch: only a bare PEP 503 (python) / npm registry name
(+ optional version pin) is fetched. Paths, git+/hg+/svn+/bzr+, URLs (://),
file:, PEP 508 direct references (name @ url), and shell metacharacters are
refused → caller falls back to tool_definitions_only (no fetch, no execution).
The registry-name path (already wheel-only / --ignore-scripts) is unchanged.

TDD: isBareRegistrySpec accept/reject table; resolveFromPackageFetch rejection
for git+/local/URL specs; and an execution-marker test proving a local-path
uvx spec never runs its setup.py (validation short-circuits before any
download, independent of whether uv/pip is installed).

Related #MCP-2442

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@Dumbris Dumbris force-pushed the fix/mcp-2442-scanner-fetch-spec-validation branch from 88f28a0 to acbfbcc Compare June 15, 2026 06:04
@Dumbris

Dumbris commented Jun 15, 2026

Copy link
Copy Markdown
Member Author

Duplicate of #672 (canonical MCP-2442 fix, includes docs); closing to avoid conflicting package_fetch.go edits.

@Dumbris Dumbris closed this Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants