Skip to content

Security audit: platform.mcpruntime.org exposure (Prometheus public, unauth MCP tool exec, missing headers, HTTP served) #108

@Agent-Hellboy

Description

@Agent-Hellboy

(Copy/paste of /tmp/platform-mcpruntime-security-audit-2026-04-30.md)

Security audit: platform.mcpruntime.org (2026-04-30)

Unauthenticated Chrome DevTools + curl audit of:

  • https://platform.mcpruntime.org/ (Sentinel control plane UI)
  • https://platform.mcpruntime.org/prometheus/... (Prometheus via platform ingress)
  • https://platform.mcpruntime.org/grafana/... (Grafana via platform ingress)
  • https://mcp.mcpruntime.org/go-example-mcp/mcp (demo MCP server)

No credentials used, no brute force auth attempts, and no destructive requests.

High severity

1) Platform served over plain HTTP (no redirect)

curl -I http://platform.mcpruntime.org/ returned HTTP/1.1 200 OK with Content-Type: text/html; charset=utf-8.

Chrome navigation from http:// showed a 307 with non-authoritative-reason: HttpsUpgrades (browser-driven), which is not a substitute for a server-side redirect.

Impact: MITM downgrade/rewrites possible for clients that hit http://.

Fix:

  • Redirect http:// -> https:// at the edge.
  • Add Strict-Transport-Security once HTTPS is correct across required subdomains.

2) Prometheus HTTP API publicly reachable

Chrome DevTools and curl confirmed these unauthenticated URLs return 200:

  • /prometheus/api/v1/status/config
  • /prometheus/api/v1/targets?state=active
  • /prometheus/api/v1/query?query=up
  • /prometheus/api/v1/status/flags

Chrome DevTools confirmed additional API endpoints return data unauthenticated (e.g. status/flags, query) and include internal service names/targets.

Impact: reconnaissance of internal topology and runtime config; expanded attack surface.

Fix:

  • Require auth and/or IP allowlist for Prometheus routes.
  • Consider removing Prometheus from public ingress; access via VPN/port-forward.

3) Unauthenticated MCP tool execution is possible

https://mcp.mcpruntime.org/go-example-mcp/mcp accepted unauthenticated JSON-RPC calls. I was able to:

  • initialize (server returned mcp-session-id: <issued> header)
  • tools/list
  • tools/call (add -> returned 5)
  • tools/call (upper -> returned AUDIT)

This bypasses the trust/grant model implied by the control-plane UI. If this is not a deliberately public demo, require auth/session/grant checks at the MCP gateway before tools/list and tools/call.

Fix:

  • Enforce auth/grants/sessions in the gateway before allowing tools/list and tools/call.
  • If intentionally public demo behavior: isolate to a separate demo domain and rate-limit.

Medium severity

4) Missing baseline security headers on platform UI/API

Chrome fetch() checks on /, /config.js, /app.js, /auth/status, and /api/runtime/servers did not show:

  • Content-Security-Policy / Content-Security-Policy-Report-Only
  • Strict-Transport-Security
  • X-Frame-Options (or CSP frame-ancestors)
  • X-Content-Type-Options
  • Referrer-Policy
  • Permissions-Policy
  • Cache-Control

curl headers for https://platform.mcpruntime.org/ were minimal (content-type, date).

Fix:

  • Add a Traefik header middleware for platform routes.
  • Prefer CSP (frame-ancestors) over XFO; keep CSP compatible with Google Sign-In.

5) Public server inventory endpoint

GET https://platform.mcpruntime.org/api/runtime/servers returned 200 unauthenticated and includes server names, namespaces, readiness, public MCP URLs, tool names, and required trust levels. This materially helps reconnaissance and directly led to the public MCP execution test.

Fix:

  • Require auth, or publish a reduced public catalog.

Low / informational

6) Grafana version disclosure

Chrome DevTools: GET /grafana/api/health returned 200 unauthenticated and reported Grafana 10.2.3.

Cookie/header hygiene gaps:

  • Grafana set redirect_to=%2Fgrafana; Path=/grafana; HttpOnly; SameSite=Lax without Secure.
  • The Google sign-in flow sets a g_state cookie that is accessible via document.cookie (expected for the client-side Google Sign-In integration).
  • Platform auth cookies could not be assessed without signing in.

Fix:

  • Consider restricting this endpoint publicly; keep Grafana patched.

Positive checks

  • HTTPS loaded cleanly and the page was a secure context.
  • Authenticated platform APIs returned 401 unauthenticated (browser + curl): /api/dashboard/summary, /api/events, /api/runtime/grants, /api/runtime/sessions, /api/user/api-keys, /api/runtime/components.
  • No secrets were stored in localStorage or sessionStorage (browser check).
  • The auth form uses password fields for password/API key input.
  • Browser CORS blocked a cross-origin MCP call from platform.mcpruntime.org to mcp.mcpruntime.org via preflight 405 (OPTIONS not handled for that route).
  • Prometheus admin/lifecycle flags were disabled (browser check: web.enable-admin-api=false, web.enable-lifecycle=false).

Suggested fix order

  1. Enforce HTTPS (redirect + HSTS).
  2. Lock down Prometheus routes.
  3. Lock down MCP demo endpoints (or isolate).
  4. Add baseline security headers for platform UI/API.
  5. Review what data should be public via /api/runtime/servers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity vulnerabilities, hardening, threat-model concerns

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions