Security notes

  • Use HTTPS for production public_url, auth.issuer, and remote backend URLs. allow_insecure_http permits only loopback backends; it cannot make a remote plaintext URL valid.
  • public_url must appear in the token aud: a string aud equals public_url, while an audience array contains public_url; after TLS termination, a reverse proxy must preserve the public host and path and route both RFC 9728 metadata addresses.
  • Use exact allowed_origins entries and do not add untrusted consoles. Origin and preflight headers are strictly allowlisted; preflight permits only POST (with OPTIONS as the response method).
  • Put client secrets, API keys, and static Authorization values in environment variables or an external secret store, not in Git. Static headers are sent to backend data planes; do not put sensitive values in logs or capability names.
  • Validation rejects line breaks, duplicate headers, and transport-managed headers, including Proxy-Authorization and Proxy-Authenticate. OAuth rejects a static Authorization header to prevent competing authentication sources.
  • Overlong or invalid request IDs are regenerated, logged request/trace values are bounded or hashed, capability and resource-URI fields are validated and sanitized, and request failures record only external error types rather than raw external error text.
  • /healthz, /readyz, and metadata do not require Bearer authentication; restrict their network visibility as appropriate. The MCP entry accepts Bearer JWTs in the Authorization header.
  • Every MCP-listener HTTP route keeps the request_timeout request-body read deadline until the body is consumed or closed, so unauthenticated and rejected requests with slow bodies are bounded. A subscriptions/listen POST is exempt from ordinary response-write and request-context timeouts only after its body has been read.
  • Backend SSE responses are streaming passthrough. Progress inspection buffers at most 1 MiB per event; an oversized event is forwarded unchanged without progress inspection.
  • Acknowledged 2026 resource subscription IDs map updates back to their original subscription URI(s), including when an update event URI differs; timeout, cancellation, and session/reconnect cleanup remove the mapping.
  • Built-in local management requires account sign-in and permits only numeric loopback. Remote management requires a separate audience and admin scopes, HTTPS, exact Host/Origin checks, cookie CSRF protection and a restrictive CSP.
  • Keep MCPHUB_CONFIG_KEY outside YAML and backups. The SQLite file uses 0600, but its availability and recoverability depend on retaining the exact 32-byte key.