Open
Conversation
Implement pluggable security scanner system for analyzing quarantined MCP servers before approval. Docker-based scanners run in isolated containers, produce SARIF reports, and integrate with the existing quarantine workflow. ## Changes - Scanner plugin architecture: types, registry (4 bundled scanners), Docker runner, SARIF 2.1.0 parser, parallel scan engine - Storage: 4 new BBolt buckets (scanners, jobs, reports, baselines) - Security service: install/configure scanners, scan/approve/reject workflow, integrity verification, risk scoring - REST API: 13 endpoints for scanner management, scan operations, approval flow, and security overview - CLI: mcpproxy security command group with 12 subcommands - Web UI: Security dashboard with scanner marketplace, scan trigger, findings viewer, approve/reject actions - SSE events: scan lifecycle and integrity alert events - Documentation: feature guide, spec, plan, autonomous summary ## Testing - 500+ tests passing across scanner, storage, httpapi, config packages - Race detector clean on all new code - Frontend type-checks clean and builds successfully Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deploying mcpproxy-docs with
|
| Latest commit: |
42941be
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://1743abee.mcpproxy-docs.pages.dev |
| Branch Preview URL: | https://feat-039-security-scanner-pl.mcpproxy-docs.pages.dev |
📦 Build ArtifactsWorkflow Run: View Run Available Artifacts
How to DownloadOption 1: GitHub Web UI (easiest)
Option 2: GitHub CLI gh run download 23996310827 --repo smart-mcp-proxy/mcpproxy-go
|
Critical fixes discovered during E2E testing: - Wire scanner.Service as SecurityController in server setup - Register security routes unconditionally (nil-guard in handlers) - Use background context for scan goroutines (prevent request context cancellation) - Sync registry from storage on startup (scanner state survives restart) - Add source_dir parameter to scan API and service - Fix Semgrep: mount source at /src (Docker image requirement), enable network - Disable read-only for scanner containers (they need cache writes) - Fix Trivy image name: aquasecurity/trivy (not aquasec/trivy) - Add GetSecurityOverview alias on Service for interface compliance Verified E2E: - Semgrep scan found subprocess shell=True (HIGH) and eval() (MEDIUM) - Full approve/reject/report CLI workflow tested against running server Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… scanning Users no longer need to provide --source-dir. When scanning, MCPProxy automatically: 1. Finds the running Docker container for the server (mcpproxy-<name>-*) 2. Extracts app source files via docker cp + docker diff analysis 3. Mounts extracted source for scanner containers 4. Cleans up temp files after scan completes Fallback chain: Docker container -> working_dir -> command args -> error. HTTP/SSE servers resolve to URL for mcp_connection scanners. Verified E2E: mcpproxy security scan perplexity works with zero config. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scanner API keys configured via the API or CLI are now stored in the
OS keyring (macOS Keychain / Linux Secret Service / Windows Credential
Manager) using the existing mcpproxy secrets system.
- ConfigureScanner stores values via keyring, keeps ${keyring:...} refs
- Engine resolves keyring references at scan time before passing to containers
- Secrets visible in `mcpproxy secrets list` alongside server secrets
- Fallback to direct storage if keyring is unavailable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Web UI expected APIResponse format {success: true, data: ...} but
security handlers were writing raw data. Changed all handlers to use
writeSuccess() which wraps via contracts.NewSuccessResponse().
Updated all 23 httpapi security tests to parse the wrapped format.
Rebuilt frontend dist for embedded Web UI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bugs found and fixed during E2E testing with real scanners:
1. CLI commands failed to parse wrapped API responses ({success, data})
- Added unwrapAPIResponse() helper to extract data from envelope
- Applied to all 8 json.Unmarshal points in security_cmd.go
2. Trivy scanner: "unknown command trivy for trivy"
- Trivy Docker image has ENTRYPOINT=[trivy], so command was doubled
- Fixed: command is now ["fs", "--format", "sarif", "/scan/source"]
3. Trivy scanner: "no space left on device" during DB download
- Trivy downloads 89MB vuln DB to /tmp on first run
- Tmpfs was 100MB with noexec — too small and restrictive
- Fixed: increased to 500MB, removed noexec (scanners need it)
4. Trivy Docker image: aquasecurity/trivy not on Docker Hub
- Changed to ghcr.io/aquasecurity/trivy:latest (GHCR registry)
Verified E2E: Semgrep + Trivy both complete scans successfully on
quarantined everything-server with real Docker containers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ores Findings now include: - help_uri: clickable link to CVE advisory (e.g., https://avd.aquasec.com/nvd/CVE-xxx) - cvss_score: CVSS severity score (0-10) from SARIF properties - package_name, installed_version, fixed_version: extracted from Trivy message format CLI report shows: [HIGH] CVE-2025-66414 (trivy-mcp) Package: @modelcontextprotocol/sdk v0.6.0 -> fix: 1.24.0 Details: https://avd.aquasec.com/nvd/cve-2025-66414 Web UI findings table shows clickable CVE links, package column, fix version badge, and CVSS score. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…categories Backend: SecurityScanSummary on Server contract, threat classification, scan summary computation from stored reports. Frontend: Security tab with risk score, threat summary cards, grouped findings, scan button with polling. Scan badge on server cards. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The /api/v1/servers endpoint uses management.ListServers(), not the legacy GetAllServers(). Moved scan summary enrichment to the httpapi handler. Also re-classify legacy findings without threat_level on read. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AggregateReports now classifies findings before summarizing. ReportSummary includes dangerous/warnings/info_level counts. Frontend reads summary from API response. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Risk score based on threat level instead of raw CVSS severity. Scanner stdout/stderr/exit_code stored on ScannerJobStatus. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Configure button shows for all installed/configured scanners. Dialog supports required, optional, and custom env vars with keyring integration. Users can add OPENAI_API_KEY etc. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each finding is now an expandable card with full details. Scanner Execution Logs section shows stderr/stdout per scanner. Fixed TS types to match Go API field names. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ScanContext on ScanJob with source method, path, isolation status, file list. File tree API with suspicious file markers. Auto-prune keeps last 20 scans. Frontend scan context banner + scanned files collapsible with lazy loading. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SARIF raw data can be 2MB+ (Semgrep includes all rule definitions). Web UI was stuck on "Loading scan report..." because of this. Now stripped by default; add ?include_sarif=true for CLI --output sarif. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ScanQueue with 3 concurrent workers, progress tracking, cancel support. REST API: scan-all, queue, cancel-all endpoints. CLI: --all flag and cancel-all subcommand. Web UI: Scan All button with progress card. Disabled servers auto-skipped with hint. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SECURITY: UI now shows red error instead of green "safe" when scanners fail. AggregatedReport tracks scan_complete, scanners_run/failed/total. Server card badge shows "Scan Failed" (red) for incomplete scans. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three fixes for scanner reliability: 1. resolveScanners() now checks ImageExists() before adding to run list. Scanners with non-existent Docker images (mcp-scan, cisco-mcp-scanner placeholders) are skipped with a warning log instead of failing at runtime with exit code 125. 2. Per-scanner cache directory persisted at ~/.mcpproxy/scanner-cache/<id>/ mounted at /root/.cache in containers. Trivy DB (90MB) is now downloaded once and reused across runs instead of re-downloading every scan. 3. Fixed test to use nil docker runner for resolution logic tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Semgrep timed out on ElevenLabs (14,953 files, 361MB including 6,979 Python files from site-packages). Two fixes: 1. Semgrep timeout increased from 5min to 10min for large source trees 2. Semgrep command now excludes site-packages, node_modules, dist-packages 3. Source resolver excludes dependency directories from docker diff extraction — these are third-party packages, not user code Before: ElevenLabs extracted 14,953 files (361MB) -> Semgrep timeout After: Only actual MCP server code extracted -> fast scan Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
For servers installed via uvx --from pkg@git+URL, the actual source code lives at /root/.cache/uv/git-v0/checkouts/<hash>/<rev>/. Previously this was extracted as /root/.cache (too broad) or filtered out entirely. Changes: - extractAppRoot recognizes UV git checkout paths specifically - isSystemPath excludes UV archive-v0 (dependencies) but keeps git-v0 - npm node_modules exclusion now allows npx cache paths - Tests updated for UV git checkout extraction Note: Scanner requires the server container to be fully connected. If uvx is still downloading from GitHub when the scan runs, the source won't be available yet. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
For servers installed via uvx --from pkg@git+URL (like gcore-mcp-server), the actual source lives at /root/.cache/uv/git-v0/checkouts/<hash>/<rev>/. Fixes: - extractAppRoot excludes /root/.cache and /root/.local (too broad) - Fallback path uses docker exec find to locate UV git checkouts directly when docker diff doesn't show them - Removed /root from fallback dirs (was copying entire 10K+ file cache) Before: 10,536 files (174MB) including all pip/uv dependencies After: 26 files (422KB) — just the actual MCP server source code Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pass 1: Semgrep on source + Trivy on lockfile (fast, immediate results) Pass 2: Trivy full filesystem (background, auto-starts after Pass 1) Results merged in single report with pass1/pass2 completion tracking. 7 new unit tests. Frontend shows both passes with progress indicator. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In-memory cache for scan summaries, invalidated on scan start/complete. Cold cache: 3.0s. Warm cache: 0.8s. Was: 12.1s. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pagination with limit/offset/suspicious_only. Progressive loading in frontend with "Load more" button. Suspicious files sorted first. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…PI key) Built Docker image for Cisco AI Defense MCP Scanner. Runs YARA + readiness analyzers offline. Detects tool poisoning, prompt injection, credential harvesting, data exfiltration in MCP tool descriptions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Evidence field on ScanFinding captures the tool description that triggered Cisco YARA warnings. Shown in Web UI and CLI report. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
What's Included
Backend (Go)
internal/security/scanner/— Scanner types, registry, Docker runner, SARIF parser, scan engine, serviceinternal/storage/scanner.go— BBolt CRUD for 4 new buckets (scanners, jobs, reports, baselines)internal/httpapi/security_scanner.go— 13 REST API endpoints + SecurityController interfaceinternal/runtime/events.go— 5 new SSE event types for scan lifecycleinternal/config/config.go— SecurityConfig sectioncmd/mcpproxy/security_cmd.go— CLI commands: scanners/install/scan/approve/reject/overviewFrontend (Vue 3)
frontend/src/views/Security.vue— Dashboard with scanner marketplace, scan trigger, findings viewerDocumentation
docs/features/security-scanner-plugins.md— Feature guide with CLI reference, API referencespecs/039-security-scanner-plugins/— Spec, plan, checklist, autonomous summaryTest plan
-race(registry, SARIF, engine, service)-race(CRUD for all 4 entity types)-race(all 13 endpoints)vue-tsc --noEmit)npm run build)go build ./...)