Skip to content

fix(security): source-less in-process TPA description scanner (MCP-2082)#636

Merged
Dumbris merged 1 commit into
mainfrom
mcp-2082-tpa-descriptions
Jun 12, 2026
Merged

fix(security): source-less in-process TPA description scanner (MCP-2082)#636
Dumbris merged 1 commit into
mainfrom
mcp-2082-tpa-descriptions

Conversation

@Dumbris

@Dumbris Dumbris commented Jun 12, 2026

Copy link
Copy Markdown
Member

Problem (MCP-2082)

A connected remote server (e.g. com.googleapis.sqladmin/mcp over http) hits Scan Now and gets:

  • "No Source Available — Could not resolve source files for scanning."
  • "all scanners failed", Risk Score 0/100

This is wrong for a remote server: there is no source/Docker, but the connected server's tool descriptions/schemas are available and should still get a Tool-Poisoning-Attack (TPA) scan.

Root cause

Every bundled scanner is Docker-image based and requires a mountable /scan/source. On a host without those images pulled, all of them prefail (Docker image … not available locally), the engine has no source-less scanner, so it reports all scanners failed (engine.go) and the UI shows the dead-end.

Fix

Add a built-in, Docker-less scanner tpa-descriptions that runs in-process for any connected server:

  • ScannerPlugin.InProcess flag — such scanners seed as installed (always on) and skip the Docker image-availability gate in resolveScanners.
  • Engine.runSingleScanner branches to runInProcessScanner, which reads the already-exported tools.json and runs description/schema heuristics — hidden instructions, prompt-injection phrasing, data-exfiltration hints — plus embedded-secret detection via the existing security.Detector.
  • The description scan is a Pass-1 concern; Pass-2 (supply chain audit) skips it.

Result: a remote server with no source now produces a real description-based TPA scan + risk score that completes, instead of all scanners failed / No Source Available.

Tests (TDD, all green)

  • inprocess_test.go — hidden instructions detected, clean tools → no findings, documented example AWS key ignored, exfiltration phrasing detected.
  • engine_test.goend-to-end: a remote-style scan (no Docker, only tools.json) completes with findings and non-zero risk (not "all failed"); in-process scanner always resolves and never prefails.
  • registry_test.go — in-process scanner is installed by default with no image.

Verification

  • go build ./... (personal + -tags server) ✅
  • go vet ./internal/security/...
  • go test ./internal/security/... -race
  • go test ./internal/storage/
  • ./scripts/run-linter.sh → 0 issues ✅

Docs

  • docs/features/security-scanner-plugins.md updated (registry now 8 scanners; new always-on in-process entry documented).

Notes

  • Backend-only. The UI already renders a completed scan; because the scan now completes (and source_method stays url/tool_definitions_only for connected servers), the "No Source Available" dead-end no longer applies. No frontend change in scope.

Related MCP-2082

Remote http/sse servers have no source files or Docker container, so every
bundled (Docker-image) scanner prefails on image availability and the engine
reports "all scanners failed" / "No Source Available" with Risk 0 — even though
the connected server's tool descriptions/schemas are available and should still
get a Tool-Poisoning-Attack scan.

Add a built-in, Docker-less scanner `tpa-descriptions` that runs in-process for
any connected server:

- ScannerPlugin gains an InProcess flag; such scanners seed as "installed"
  (always on) and skip the Docker image-availability gate.
- The engine branches to runInProcessScanner, which reads the exported
  tools.json and runs description/schema heuristics (hidden instructions,
  prompt-injection phrasing, data-exfiltration hints) plus embedded-secret
  detection via the existing security.Detector.
- The description scan is a Pass-1 concern; Pass-2 (supply chain audit) skips it.

Result: a remote server with no source still produces a real description-based
TPA scan + risk score that COMPLETES, instead of the dead-end.

Related MCP-2082
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: ca2e98f
Status: ✅  Deploy successful!
Preview URL: https://d9110c83.mcpproxy-docs.pages.dev
Branch Preview URL: https://mcp-2082-tpa-descriptions.mcpproxy-docs.pages.dev

View logs

}

toolsPath := filepath.Join(req.SourceDir, "tools.json")
data, err := os.ReadFile(toolsPath)
@codecov-commenter

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 85.89744% with 11 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/security/scanner/inprocess.go 84.28% 6 Missing and 5 partials ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: mcp-2082-tpa-descriptions

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 (24 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 27398917668 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@Dumbris Dumbris merged commit 40742f2 into main Jun 12, 2026
45 of 46 checks passed
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.

3 participants