v0.3.0
Security-hardening release. Every change comes from an internal security audit of the hub; the full deployment guidance now lives in SECURITY.md.
Security
- Resource-bound tokens (RFC 8707): a client that sends a
resourceindicator receives an access token bound to/hubor one/<name>/mcp— usable nowhere else on the hub. The login/consent pages display the requested resource, and the code/refresh exchanges verify it. SetRESOURCE_BOUND_TOKENS=trueto make the indicator mandatory for every new token (recommended; legacy global tokens then stop working and clients re-authorize once). - Access tokens now expire after 15 minutes (down from 24 hours); refresh tokens keep rotating with family-reuse detection.
- Offline revocation:
mcp-hub-admin clients list|revoke(run against the mounted/datawhile the hub is stopped) removes a client's approval and refresh tokens and immediately rejects its outstanding access tokens via arevokedBeforemarker. - Stricter JWT verification: the EdDSA algorithm is pinned and issuer, audience, subject and
client_idare validated explicitly. - Request limits: cheap per-IP rate limits guard
/register,/authorize,/token,/loginand/consentbefore any body parsing; authenticated MCP traffic passes a per-client gate (MCP_REQUESTS_PER_MINUTE, default 120, andMCP_MAX_CONCURRENT_REQUESTS, default 4); the MCP JSON body limit drops to 1 MB (MCP_BODY_LIMIT) and is parsed only after bearer auth; the Node server gets header/request timeouts (HTTP_HEADERS_TIMEOUT_MS,HTTP_REQUEST_TIMEOUT_MS). - Browser hardening on the interactive auth pages: CSP with
frame-ancestors 'none'andform-action 'self',X-Frame-Options: DENY,nosniff,Referrer-Policy: no-referrer;x-powered-byremoved.
Supply chain
- Base images, the uv helper and every GitHub Action are pinned to digests/commit SHAs; npm installs run with
--ignore-scripts. - CI gates publishing behind CodeQL, a Trivy scan of both platform images (HIGH/CRITICAL, zero findings) and
npm audit; published images ship an SBOM andmode=maxprovenance. Dependabot watches npm, Docker and Actions weekly. - The runtime image replaces the base image's bundled npm 10 with npm 12 and patches its two remaining vendored CVEs (brace-expansion, ip-address) in place.
- The compose example now runs with a read-only root filesystem, explicit tmpfs mounts and all capabilities dropped.
Breaking / behavioral changes
/health(per-server status) now requires a bearer token. The new unauthenticated/livezanswers liveness only; the imageHEALTHCHECKuses it, and external monitoring should too.livezjoins the reserved server names.- Access tokens last 15 minutes — clients must use the refresh flow (Claude Web and Claude Code do).
- Enabling
RESOURCE_BOUND_TOKENS=trueinvalidates previously issued global access/refresh tokens; each client re-authorizes once. curlwas removed from the image andtiniis now PID 1.- Install stdio server binaries at exact, reviewed versions in a custom image instead of downloading them at runtime via
npx -y/uvx— required with the read-only root filesystem and strongly recommended regardless (see SECURITY.md).