Repository: SamuelSupe/mcphub · documented version: v2.4.0 · module: github.com/SamuelSupe/mcphub/v2 · release notes · license: Apache License 2.0
MCPHub's security boundary includes:
- the public MCP Streamable HTTP endpoint and Bearer JWT verification;
- OIDC discovery/JWKS, JWT
iss/aud/sub/exp/nbf, andscope/scphandling; - backend URL validation, static headers, OAuth
client_credentials, and redirect behavior; - backend-local
tool_rulesand per-tool scope challenges; - CORS/origin checks, RFC 9728 Protected Resource Metadata, readiness/health exposure;
- configuration files, environment expansion, secrets, and SIGHUP reload behavior;
- the optional local/remote administration listener, encrypted SQLite/PostgreSQL backend configuration, bootstrap import, and runtime replacement API;
- admin-managed tool groups, hand-authored HTTP tools, OpenAPI 3.0/3.1 imports, source refresh, and the response/body limits on those paths.
The current published release explicitly does not provide stdio backends, a standalone legacy GET SSE endpoint, native TLS, dynamic tenants, opaque-token introspection, Tasks, or MCP Apps. Personal upstream credentials cover remote MCP endpoints through Vault; HTTP tool groups and dynamic cloud/database credentials are outside that integration. Local mode is loopback-only; authenticated remote mode is described below. TLS termination, external rate limiting, and edge access policy must be supplied by the deployment's reverse proxy or network layer.
The release also provides a separate mcpbridge executable with login/connect/status/logout for built-in or optional enterprise user login. The server executable mcphub provides serve/validate/init-admin. Only the local CLI connector speaks stdio; it sends user access tokens to its saved HTTP gateway, never to backend servers. Login uses a public client, PKCE S256, state/issuer validation and a loopback callback, and saves credentials only after the gateway accepts an authenticated handshake. Discovery and token requests require HTTPS and do not follow redirects. The callback listener is temporary and binds only 127.0.0.1.
Local credentials are unencrypted JSON. On macOS/Linux, ~/.mcphub/ uses owner-only permissions (directory 0700, files 0600). On Windows, %USERPROFILE%\.mcphub\ and credential files are created with a protected DACL granting access only to the current user; opening them checks ownership and access rules. Credential directories, profiles, and lock files that are reparse points or grant access to other accounts are rejected. Keep them out of shared storage and public backups. Platform file locks and temporary-file replacement serialize refresh-token rotation. A new login invalidates existing connectors; logout clears cached tokens and prevents subsequent requests, but does not revoke issuer tokens, terminate already accepted operations, or sign out browser sessions. connect never starts interactive authorization, retries a 401 only once after refreshing, and never replays a tool operation on a network failure. stdout is exclusively MCP protocol output. No token values are exposed by status or diagnostics.
Strict endpoints require a verified access JWT and a random opaque MCPHub-Grant credential. A grant ID, broker session ID, client display name, clientInfo or arbitrary client header does not authorize a request. Scopes are intersected with the current JWT; no claim is made that upstream service-account ACLs become end-user ACLs. Grant credentials are not forwarded upstream.
Consent is frozen, expires after five minutes, belongs to the exact issuer/subject/resource, and requires an ordinary-user browser session plus Origin and CSRF checks. An API bearer cannot confirm it; administrators can revoke but cannot consent for another user. Exchange proofs are single-use. Server grant/session credentials are stored as hashes; grant details and lifecycle events are encrypted. Configure the existing independent audit archive for signed chained delivery; a database alone is not a tamper-proof archive.
Endpoint UIDs cannot be reused after deletion. Grant/session deadlines, revocation, endpoint policy and tool/resource constraints are checked at admission. Revocation cancels active streams but does not reverse an already admitted upstream side effect. Write-request capability never bypasses per-operation approval. Approval lookup, resume, cancellation and cached results are bound to the grant revision, client and endpoint UID; business operation deduplication also survives grant replacement.
The local Broker uses owner-only Unix sockets with peer UID checks on macOS/Linux, and user-restricted named pipes with process SID checks on Windows. Local IPC entries have independent random credentials; MCP configuration contains only their IDs. Files remain unencrypted and accessible to the owning OS account. A malicious process under that account may impersonate an entry or steal credentials; strong application attestation, OS keychains and DPoP are outside this version. Windows named-pipe runtime security still requires validation on Windows; cross-compilation alone does not establish it.
Logout clears local secrets before network I/O and tries remote session revocation. If offline, only non-secret session references remain and remote revocation is explicitly unconfirmed; use the user portal to revoke them. Stopping the Broker does not revoke remote authorizations. No network error triggers automatic tool replay. Same-profile refresh is serialized with process locks and token rotation is saved atomically.
Tool policy inspection and access simulation require configuration-administrator privileges; reviewer-only and MCP user scopes cannot access them. The simulator treats supplied scopes as assumptions and checks saved grants against the exact issuer/subject and current policy. It never mints credentials, creates approvals, previews or executes tools, or consumes execution quotas. Results are a configuration snapshot, not a verified user's permissions or a promise that later execution will succeed. Policy edits use the existing revision and optional configuration-approval controls. mcpbridge doctor uses the connector's credential validation and refresh path and may persist rotated tokens. Its network actions are authorization status, MCP initialization and catalog discovery; it does not execute tools or start interactive authorization. Reports omit token, Grant credential and IPC secret values.
Please do not disclose a suspected vulnerability in a public issue, discussion, or pull request. Use GitHub's private vulnerability reporting/Security Advisory flow when it is enabled for this repository. If that flow is unavailable, contact the maintainers through the repository's private security contact channel.
Include, when safe:
- affected commit, tag, or deployment version;
- a concise impact statement and attack preconditions;
- a minimal reproduction or request/response transcript with secrets removed;
- suggested mitigation or workaround;
- whether the issue affects only a reverse-proxy deployment or the MCPHub process itself.
Never include live client secrets, API keys, bearer tokens, private keys, production URLs containing credentials, or unredacted personal data. If a secret was exposed, revoke/rotate it first and report only the redacted evidence.
- Use HTTPS for
server.public_url,auth.issuer, and remote backend URLs. HTTP is accepted only for loopback backend URLs with explicitallow_insecure_http: true. - Require
server.public_urlto appear in JWTaud, including its path: a stringaudmust equalpublic_url, while an audience array must containpublic_url. Route both RFC 9728 metadata paths through the same trusted origin. - Store
client_secret, API keys, static Authorization values, and environment files outside Git; mount configuration read-only where possible and restrict file permissions. - Use exact HTTPS
allowed_originsvalues. Keep the existing preflight header allowlist, permit onlyPOST(withOPTIONSas the preflight response), do not use wildcard origins, and do not expose management/probe endpoints more broadly than necessary. - Treat
/healthz,/readyz, and metadata as unauthenticated endpoints. Protect their network visibility at the proxy or network layer. - The stateless Streamable HTTP
/mcpendpoint accepts POST only; modern clients may use request-scoped SSE in the POST response, while MCPHub exposes no standalone GET SSE or DELETE session endpoint. Compatibility clients use the same/mcpPOST semantics. - Do not put secrets in backend IDs, capability names, logs, issue reports, or release artifacts. Static backend headers apply to data-plane requests; OAuth discovery/token requests intentionally do not receive them.
- Manage tool groups, manual HTTP tools, and OpenAPI imports only through the local or authenticated remote admin API under
/api/v1/tool-groups; the selected database is their source of truth. Do not add a YAML schema for these resources or treat SIGHUP as a migration mechanism. - A tool group shares one HTTPS base URL, static headers or OAuth
client_credentials, JWT required scopes, and request timeout across its tools. Its HTTP tools are exposed only as MCP capabilities through/mcp; MCPHub must not become a raw HTTP proxy or arbitrary method/path passthrough. - Group and OpenAPI source URLs must use HTTPS and fetchers do not follow redirects. A cross-origin OpenAPI source fetch must not send the group's static headers, bearer material, or OAuth client secret. Keep group secrets encrypted in the configuration database and outside logs, exports, and browser-visible API fields.
- Tool-group, manual-tool, and import resources each use
ETagrevisions; update/delete requests must supply the matchingIf-Match, and stale revisions must fail closed with409 revision_conflict. - Enforce a 1 MiB default HTTP-tool response limit (configurable only from 64 KiB through 16 MiB), a 5 MiB OpenAPI document limit, and a 6 MiB request limit for bodies carrying an OpenAPI document. URL-backed imports refresh every 15 minutes by default (allowed range 1 minute to 24 hours); failed refreshes retain the last-known-good document/tools and retry with backoff.
- During SIGHUP, an unavailable optional backend may reuse a previous in-memory catalog only when its backend ID/URL,
allow_insecure_http, every fixed header, and OAuth configuration presence plustype,issuer,client_id,client_secret, andscopesare unchanged. Credential, OAuth, or tenant-selection-header changes prevent reuse; non-identity fields such asrequired,required_scopes,tool_rules, and timeouts do not, and reuse never marks the new backend ready. - SIGHUP candidate startup uses a cancelable context; shutdown cancels a candidate that is still connecting. Required backends must connect successfully before the candidate replaces the current generation, and each candidate or retired generation closes its own backend sessions and connections.
- Backend IDs may contain uppercase letters but must be unique case-insensitively. Tool and prompt names preserve the configured ID; resource and resource-template URI authorities use the lowercase ID.
- Keep the numeric-loopback
mode: localadmin listener on its validated numeric loopback address and never publish it through a reverse proxy. StoreMCPHUB_CONFIG_KEYseparately from YAML and SQLite backups; stored secrets require the exact same Base64-encoded 32-byte key for recovery.
mode: remote requires HTTPS termination at a trusted proxy, an exact configured Host/Origin and a separate admin JWT audience (admin.public_url) plus all configured administrator scopes. Upstream HTTP listeners must remain private. Upstream role names and proxy identity headers never grant access. Verified group claims identify enterprise memberships; only locally configured group grants authorize members. UI sessions use opaque Secure/HttpOnly/SameSite cookies, CSRF checks for mutations, PKCE S256, single-use browser-bound state and authorization-response issuer validation. Access/refresh tokens stay in server memory; refresh rotation is serialized per session. Sessions expire in eight hours and are lost on restart. Logout clears the current browser/CLI session, not IDP SSO or already issued JWTs.
Configuration audit attributes remote writes to the verified subject; it is not a tamper-proof compliance log. PostgreSQL preserves encryption, revision checks and transactional audit. Use a dedicated database/schema and verify-full TLS for external database connections. The Compose example's unencrypted database connection is confined to its private container network. Both backends currently support one gateway instance; changing drivers does not migrate data. See deployment boundaries.
Endpoint rate/concurrency limits are opt-in and apply after authentication/scope checks. They reject before upstream execution, preserve cancellation/cleanup, and share budgets across callers of the same configured ID. Counters are process-local and reset on restart. They do not replace reverse-proxy protection for unauthenticated traffic.
Write and unclassified tools require an immutable, single-use server-side approval. Reviewers use a separate scope from configuration administrators, exact subject/resource grants, and optional separation of requester and reviewer. Listing and detail access enforce those grants. Reviewer browser cookies plus CSRF/Origin checks are required; authenticated built-in local mode can approve, while unauthenticated advanced local mode and bearer tokens cannot. Built-in step-up requires a fresh password and TOTP for that approval; ordinary password sign-in is not MFA. Enterprise strong-authentication policies require a fresh signed OIDC ID token with the configured ACR, matching subject/nonce/audience and recent auth_time. The proof is bound to one approval and session and consumed once; the provider must enforce the configured ACR's authentication meaning.
The original caller resumes the saved request; the gateway rechecks permission, generation, rate limits and any configured preview/version. Cancellation and revocation compete atomically with execution and cannot undo an admitted write. Preview tools must be explicitly published reads; upstream writes must enforce version preconditions atomically. Unknown results remain non-replayable after investigation notes. SQLite/PostgreSQL encrypt requests, previews, results and detailed audit; terminal details are removed after configured retention. General status events remain. Business operation IDs bind normalized requests to the original caller/source/tool, retain identity tombstones after history cleanup, and never restore an unknown operation to executable. Read-only status queries do not claim execution. Two-reviewer policies count distinct authorized subjects and exclude the requester. This is gateway admission control; the backend must provide business idempotency and atomic version checks.
Optional signed audit archival uses a transactional outbox, an Ed25519 signature and hash chain, and exact durable acknowledgements from an independent HTTPS sink. Failed delivery is visible and retains unarchived approval detail. Verifying an exported prefix cannot prove completeness: maintain a trusted checkpoint outside the database and use independent append-only retention. A compromised signer and archive remain outside this protection. Notifications are HMAC-authenticated links without execution arguments; they never authorize decisions. Detailed contracts and deployment boundaries are in the README.
Agents must not control reviewer browsers, configuration/database access, encryption keys or upstream write credentials. When policy_changes.enabled is true, creates/updates require a distinct security reviewer; pure disabling and deletion remain immediate. Proposals bind revisions and resolved OpenAPI definitions. With governance disabled, configuration administrators can reclassify tools directly. Deployment configuration, database access and signing/encryption keys remain trusted. Authentication strength does not prove that a human understood an operation, and a read classification cannot prove absence of side effects. Enforce downstream least privilege and network isolation. See limits and roles.
Backend access uses all-of scope semantics: every entry in required_scopes must be present in the verified token; JWT scope is a space-delimited string, while scp is a string or string array. Backend headers reject line breaks, duplicates, Accept, Content-Type, any Mcp-*, Proxy-Authorization, Proxy-Authenticate, and other HTTP/MCP transport-managed names. OAuth mode rejects a static Authorization header. client_credentials discovery needs only an exact issuer and token endpoint from RFC 8414/OIDC metadata, not interactive authorization or PKCE metadata. Initial OIDC readiness also requires an absolute HTTPS jwks_uri and a reachable JWKS response containing at least one parseable, valid, asymmetric public verification key; symmetric oct keys and invalid or empty keys do not satisfy this condition. OIDC discovery and JWKS responses are each capped at 1 MiB; OAuth metadata responses have the same cap. OIDC and backend HTTP clients do not follow redirects. Every MCP-listener HTTP route keeps the request_timeout request-body read deadline until the body is consumed or closed, including unauthenticated and rejected requests; once MCP handling proceeds, ordinary MCP POSTs set response-write deadlines and request contexts from the same value. The newer subscriptions/listen POST remains long-lived after its body is read and bypasses those ordinary response-write and request-context timeouts. Logs regenerate overlong or invalid request IDs, validate or sanitize capability/resource-URI fields, and record only external error types. A retiring runtime generation waits for its active requests, then cancels request contexts bound to that generation before closing Hub/backend state; this prevents late session registration. SIGINT/SIGTERM force-close remaining HTTP connections when the drain_timeout HTTP drain expires.
Backend SSE responses are streaming passthrough: progress inspection buffers at most 1 MiB per event, and oversized events are forwarded unchanged without progress inspection. Acknowledged 2026 resource subscription IDs map updates back to their original subscription URI(s), including when the update event URI differs; timeout, cancellation, and session/reconnect cleanup remove the mapping. A canceled or disconnected modern subscriptions/listen stream detaches cleanup from the canceled upstream context but remains bounded by the backend timeout and session lifecycle, so legacy backends still receive resources/unsubscribe. Runtime or client context cancellation expires the underlying write deadline, so slow or unread subscription writes are interrupted at generation drain while ordinary requests retain request_timeout.
Explicit-publication policy: published_tools is an exact allowlist, empty by default; discovery and scope globs cannot approve new tools. Manual HTTP tools also default to disabled. Invocation checks current publication/enable state and scopes, then applies every matching resource_rules constraint to the actual arguments. Resource values are exact strings (or non-empty all-allowed string arrays); missing or mistyped selectors are denied. Constrained arguments are normalized before forwarding to avoid duplicate-key parser differences. These shared allowlists do not establish per-user ownership or authorize SQL, filesystem symlinks, aliases or secondary selectors; the backend remains responsible for those semantics. Already admitted calls may complete after policy changes. See the configuration and migration notes.
Backend-local tool_rules match original backend tool names with full-string, case-sensitive Go path.Match semantics. Matching rules union and deduplicate scopes, and all resulting scopes plus backend-level required_scopes are required; unauthorized tools are omitted from tools/list, while known direct calls return 403 with WWW-Authenticate carrying error="insufficient_scope", the path-aware resource_metadata, and the missing scopes. ${ENV} expansion applies to match and scope strings; empty or invalid patterns, empty/whitespace/duplicate scope entries, and duplicate matches within one backend are rejected.
The managed HTTP-tool boundary is intentionally narrower than a proxy: manual definitions and OpenAPI imports are converted into named MCP tools, and only those names can be listed or invoked through /mcp. Base URL/header/OAuth/scope/timeout settings are inherited from the group; credentials are never inferred from a tool request. OpenAPI source inspection, persistence, and refresh are admin operations, with POST /api/v1/tool-groups/{groupID}/imports/inspect bounded to the 6 MiB document request and the 5 MiB parsed document limit.
JWKS readiness requires at least one usable public asymmetric verification key: use is empty or sig; any key_ops includes verify; and an explicit key alg matches a supported RSA, EC, or Ed25519 JWS algorithm declared by id_token_signing_alg_values_supported. If discovery omits that list, RS256 is assumed. Malformed or unsupported keys in the same JWKS do not hide another usable key.
Security-sensitive changes should include a focused behavior-boundary test and explain compatibility or threat-model impact in the pull request. Do not claim a release is secure merely because local tests pass; describe the deployment assumptions and remaining limits.
仓库:SamuelSupe/mcphub · 当前文档版本:v2.4.0 · module:github.com/SamuelSupe/mcphub/v2 · 发行说明 · 许可证:Apache License 2.0
MCPHub 的安全边界包括:
- 公共 MCP Streamable HTTP 入口和 Bearer JWT 验证;
- OIDC discovery/JWKS、JWT
iss/aud/sub/exp/nbf,以及scope/scp处理; - 后端 URL 校验、静态请求头、OAuth
client_credentials和重定向行为; - backend-local
tool_rules和按 tool 的 scope challenge; - CORS/Origin 检查、RFC 9728 Protected Resource Metadata、就绪/健康端点暴露;
- 配置文件、环境展开、secret 和 SIGHUP 重载行为;
- 可选的本地/远程管理监听器、加密 SQLite/PostgreSQL backend 配置、首次导入和 runtime 替换 API;
- admin 管理的工具组、手工 HTTP tool、OpenAPI 3.0/3.1 import、source 刷新以及这些路径上的响应/body 上限。
当前正式发布版明确不提供 stdio 后端接入、独立旧式 GET SSE 端点、原生 TLS、动态租户、opaque token introspection、Tasks、MCP Apps 或自定义 MCP 扩展。Vault 个人上游凭证覆盖远程 MCP endpoint,尚未覆盖 HTTP 工具组及动态云/数据库凭证。本地模式只允许回环访问,认证远程模式见下文。TLS 终止、外部限流和边缘访问策略必须由部署使用的反向代理或网络层提供。
本版本还提供独立的 mcpbridge 可执行程序,提供 login/connect/status/logout,供用户通过外部 OIDC 身份服务登录;服务端程序 mcphub 提供 serve/validate。只有本地 CLI 连接器使用 stdio;用户 access token 仅发往保存的 HTTP 网关地址,不会发给后端。登录使用公开客户端、PKCE S256、state/issuer 校验和回环回调,只有网关接受认证握手后才保存凭证。Discovery 和 Token 请求必须使用 HTTPS,且不跟随重定向;临时回调监听器仅绑定 127.0.0.1。
凭证以未加密 JSON 保存。macOS/Linux 的 ~/.mcphub/ 使用仅限所有者的目录 0700、文件 0600 权限。Windows 的 %USERPROFILE%\.mcphub\ 与凭证文件创建时设置受保护的 DACL,仅授权当前用户;打开时校验所有权和访问规则。凭证目录、profile 或锁文件若为 reparse point 或向其他账号授权,会被拒绝访问。凭证不应进入共享存储或公开备份。平台文件锁与临时文件替换串行化 refresh token 轮换。重新登录会让已有连接器失效;退出登录清除本地 Token 并阻止后续请求,但不吊销身份服务 Token、不终止已接受的操作、不退出浏览器会话。connect 不发起交互授权;401 仅在刷新后重试一次,网络失败不重放工具操作。stdout 专用于 MCP 协议,状态和诊断不输出 Token。
工具策略查看和权限模拟仅供配置管理员使用,普通 MCP 用户和只有审批权限的用户不可访问。模拟输入的 Scope 是假设条件,Grant 按精确 issuer/subject 和当前策略检查;不会签发凭证、创建审批、预览或执行工具,也不占用执行额度。结果只是配置快照,不证明用户实际权限或保证后续执行成功。策略修改沿用版本校验与可选的配置审批。mcpbridge doctor 复用连接器的凭证校验与续期路径,可能保存轮换后的 Token;网络操作仅包括授权状态、MCP 初始化和目录发现,不执行工具或发起交互授权。报告不包含 Token、Grant 凭证或 IPC secret。
疑似漏洞不要在公开 Issue、Discussion 或 Pull Request 中披露。仓库启用 GitHub 私有漏洞报告/Security Advisory 流程 时请使用该流程;如果不可用,请通过仓库配置的私下安全联系人联系维护者。
在安全的前提下,请提供:
- 受影响的 commit、tag 或部署版本;
- 简洁的影响说明和攻击前提;
- 最小复现或请求/响应记录,并删除 secret;
- 建议的缓解措施或临时方案;
- 问题只影响反向代理部署还是 MCPHub 进程本身。
绝不要提交真实 client secret、API key、Bearer token、私钥、含凭证的生产 URL 或未脱敏个人数据。若 secret 已泄露,应先吊销/轮换,再只提交脱敏证据。
server.public_url、auth.issuer和远端后端 URL 使用 HTTPS。HTTP 仅在后端 URL 是 loopback 且显式设置allow_insecure_http: true时接受。server.public_url必须作为 JWTaud出现,包括路径:aud为字符串时必须等于public_url,为数组时必须包含public_url。两个 RFC 9728 metadata 地址都应路由到同一受信任 origin。- 将
client_secret、API key、静态 Authorization 和环境文件放在 Git 之外;尽可能只读挂载配置并限制文件权限。 - 使用精确的 HTTPS
allowed_origins,保持现有预检 header allowlist,预检只允许POST(由OPTIONS返回预检响应);不要使用通配符 Origin,也不要比必要范围更广地暴露管理/探针端点。 /healthz、/readyz和 metadata 不需要认证,应在代理或网络层限制可见范围。- Stateless Streamable HTTP
/mcp入口只接受 POST;现代客户端可以在 POST 响应中使用 request-scoped SSE,但 MCPHub 不暴露 standalone GET SSE 或 DELETE session 会话端点。兼容客户端使用同一/mcpPOST 语义。 - 不要把 secret 放入后端 ID、能力名称、日志、Issue 或发布产物。静态后端请求头用于数据面请求;OAuth discovery/token 请求会刻意排除这些请求头。
- 工具组、手工 HTTP tool 和 OpenAPI import 只能通过本地或已认证的远程 admin API 的
/api/v1/tool-groups管理,所选数据库是它们的事实来源。不要为这些对象添加 YAML schema,也不要把 SIGHUP 当作迁移机制。 - 每个工具组在其 tool 之间共享一个 HTTPS Base URL、静态 Header 或 OAuth
client_credentials、JWT required scope 和请求 timeout。HTTP tool 只能作为 MCP capability 通过/mcp暴露;MCPHub 不得变成 raw HTTP proxy 或任意 method/path 透传。 - 工具组和 OpenAPI source URL 必须使用 HTTPS,抓取器不跟随重定向。跨 origin 的 OpenAPI source 抓取不得发送该组的静态 Header、Bearer 材料或 OAuth client secret。工具组 secret 要在配置数据库中加密保存,并且不进入日志、导出或浏览器可见的 API 字段。
- 工具组、手工 tool 和 import 资源各自使用
ETagrevision;更新/删除必须提交匹配的If-Match,过期 revision 必须 fail closed 并返回409 revision_conflict。 - HTTP tool 响应默认限制 1 MiB(只允许配置在 64 KiB 至 16 MiB),OpenAPI 文档限制 5 MiB,携带 OpenAPI 文档的请求限制 6 MiB。URL-backed import 默认每 15 分钟刷新(允许 1 分钟至 24 小时);刷新失败保留 last-known-good 文档和 tools,并采用退避重试。
- SIGHUP 期间,只有 unavailable optional backend 的 backend ID/URL、
allow_insecure_http、全部固定 header,以及 OAuth 配置是否存在和type、issuer、client_id、client_secret、scopes均未变化时,才可复用上一代内存目录。凭证、OAuth 或 tenant-selection header 变化会阻止复用;required、required_scopes、tool_rules、timeout 等不标识目录来源的字段不会阻止,且复用不会把新 backend 标记为 ready。 - SIGHUP candidate 启动使用可取消的 context;关停开始时仍在连接的 candidate 会被取消。required backend 必须先连接成功,candidate 才能替换当前代际;每个 candidate 或已退役代际都会关闭自己持有的 backend session 和连接。
- Backend ID 可以包含大写,但必须按大小写不敏感规则唯一。tool/prompt 名称保留配置 ID;resource 和 resource-template URI authority 使用小写 ID。
- 数字回环的
mode: localadmin listener 必须保持在配置校验允许的数字回环地址,不能通过反向代理发布。MCPHUB_CONFIG_KEY应与 YAML、SQLite 备份分开保存;已存 Secret 只能由完全相同的 Base64 编码 32 字节密钥恢复。
mode: remote 必须通过可信代理终止 HTTPS,并校验精确的 Host/Origin、独立管理员 JWT audience(admin.public_url)及全部管理员 scope。上游 HTTP 监听器必须保持私有;IDP 角色名和代理身份头不会授予权限;已验证的组声明只决定企业成员关系,授权仍来自管理员配置的组权限。浏览器会话使用不透明 Secure/HttpOnly/SameSite cookie、变更请求 CSRF 校验、PKCE S256、绑定浏览器的一次性 state 和授权响应 issuer 校验。令牌仅在服务端内存保存,每个会话串行刷新并保存轮换结果;会话最长 8 小时,重启需重新登录。退出只清理当前浏览器/CLI 会话,不退出 IDP SSO,也不撤销已签发 JWT。
配置审计记录已验证的管理员 subject,不是不可篡改的合规日志。PostgreSQL 保留加密、版本冲突和事务审计语义。使用独立数据库/schema,外部数据库连接使用 verify-full TLS;Compose 示例的非加密数据库连接只在私有容器网络内使用。两种后端目前都支持一个网关实例;切换 driver 不迁移数据。详见部署边界。
Endpoint 速率和并发限制默认关闭,在认证与 scope 检查后、上游执行前生效。同一配置 ID 的调用者共享额度;取消和退订保持可用。计数在进程内维护,重启重置,不能替代反向代理对未认证流量的防护。
写工具和未分类工具必须取得绑定不可变请求的单次批准。审批人与配置管理员使用独立 scope,并通过精确 subject、资源条件和可选的禁止自审限制授权;列表与详情也检查范围。批准要求审批人浏览器 Cookie 和 CSRF/Origin 校验,已认证的内建本地模式可以审批,无身份高级本地模式与 Bearer Token 无权批准。内建加强认证要求为该审批单重新验证密码与 TOTP,普通密码登录不构成 MFA。企业强认证策略要求新的、已验签的 OIDC ID Token,校验配置的 ACR、同一 subject、nonce、客户端 audience 及最近 auth_time。证明只绑定一个审批单和会话、短时单次有效;ACR 的实际认证强度必须由身份服务执行。
原调用人恢复保存请求时,网关重新检查权限、代次、限流以及配置的预览/版本。取消和撤销与执行原子竞争,不能回滚已接纳的写入。预览工具必须显式发布并标为只读,写后端必须原子检查版本前提。人工核查只记录证据,不恢复不确定操作的执行额度。SQLite/PostgreSQL 加密保存请求、预览、结果与详细审计,终态详情按配置保留期清理,通用状态事件保留。这不是分布式恰好一次或不可篡改审计保证。
Agent 不应控制审批人浏览器、配置/数据库、加密密钥或上游写凭证。启用 policy_changes 后,管理 API 的配置新增/修改需由另一位安全管理员批准;停用和删除可立即阻断访问。YAML、数据库和部署运维仍属于信任边界。加强认证不代表人已经理解具体操作,标为只读也不能证明后端没有副作用;下游仍须最小权限及网络隔离。参见限制、角色和升级说明。
双人审批由不同的授权 subject 投票,禁止申请人参与;资源风险条件只能提高人数或认证强度。业务操作 ID 绑定身份、工具和不可变参数,终态 ID 的哈希登记不会随详情清理;换用新 ID 或绕过网关的写入仍需上游幂等约束。mcphub_approval_status 只读查询不会消费批准,缓存结果和上游状态查询仍受当前权限与配置检查。
可选的独立归档对审批事件使用 Ed25519 签名和哈希链,校验接收方的序号/哈希回执,失败持久化重试并阻止相关详情清理。外部校验方必须独立保存公钥和可信检查点、保护追加式存储,才可发现归档篡改、断链与回滚;有效前缀本身不能证明没有尾部删除。此机制不能防御同时控制签名者和归档的操作者,也不覆盖所有普通活动日志。通知只提供受认证的审批链接,Webhook 回调没有批准权限。
后端访问使用 scope all-of 语义:required_scopes 的每一项都必须出现在已验证 token 中;JWT scope 是空格分隔字符串,scp 是字符串或字符串数组。后端请求头会拒绝换行、重复、Accept、Content-Type、任意 Mcp-*、Proxy-Authorization、Proxy-Authenticate 以及其他 HTTP/MCP transport 管理的名称。OAuth 模式会拒绝静态 Authorization。client_credentials discovery 只需要 RFC 8414/OIDC metadata 中精确匹配的 issuer 和 token endpoint,不要求交互式 authorization 或 PKCE metadata。OIDC verifier 首次 ready 还要求绝对 HTTPS 的 jwks_uri,以及可达的 JWKS 响应中至少包含一个可解析、有效且非对称的公开验证密钥;对称 oct 密钥以及无效或空 key 均不满足此条件。OIDC discovery 和 JWKS 响应分别限制为 1 MiB;OAuth metadata 响应同样限制为 1 MiB。OIDC 和后端 HTTP 客户端不跟随重定向。MCP 监听器的所有 HTTP 路由在 request body 被消费或关闭前都保持 request_timeout 读取 deadline,包括未认证或被拒绝请求;MCP 处理继续后,普通 MCP POST 随后用同一值设置 response 写入 deadline 和 request context。新版 subscriptions/listen POST 在 body 读完后保持长连接,不受普通 response 写入和 request context timeout 限制。日志会重新生成超长或无效 request ID,校验并脱敏能力名/资源 URI 字段,并且只记录外部错误类型。runtime 代际退役时会等待活动请求,然后先取消绑定到该代际的 request context,再关闭 Hub/backend 状态,避免 session 晚到登记;SIGINT/SIGTERM 的 HTTP drain 超时后会强制关闭剩余 HTTP 连接。
后端 SSE 响应是 streaming passthrough:progress 检查每个 event 最多缓存 1 MiB,超大 event 原样转发但跳过 progress 检查。已确认的 2026 resource subscription ID 会把更新映射回原订阅 URI,包括 update event URI 不同的情况;timeout、取消订阅和 session/重连清理会删除映射。现代 subscriptions/listen stream 取消或断连时,清理会脱离已取消的 upstream context,但仍受 backend timeout 和 session lifecycle 约束,因此旧协议 backend 仍会收到 resources/unsubscribe。runtime 或 client context 取消会让底层 write deadline 到期,因此代际 drain 时会打断慢速或未读取的 subscription write,普通请求仍使用 request_timeout。
显式发布策略:published_tools 是默认空的精确允许名单,目录发现和 scope 通配规则不能批准新工具;新增手工 HTTP 工具也默认关闭。调用时检查当前发布/启停状态与 scope,再对实际参数应用所有匹配的 resource_rules。资源值必须是允许的精确字符串,或非空且全部获准的字符串数组;缺失和类型错误均拒绝。受限参数转发前会规范化,避免重复 JSON 键被不同解析器解释为不同值。这些共享允许范围不代表用户对资源的所有权,也不能代替后端对 SQL、符号链接、别名或其他选择参数的授权。策略变化前已接纳的调用仍可能完成。参见配置及升级说明。
Backend-local tool_rules 使用 Go path.Match 针对原始 backend tool name 做整串、区分大小写的匹配。所有匹配规则的 scope 会合并去重,并与 backend 级 required_scopes 一起全部满足;未授权 tool 不出现在 tools/list,已知 tool 的直接调用返回 403,WWW-Authenticate 携带 error="insufficient_scope"、路径感知的 resource_metadata 和缺失 scope。match 与 scope 字符串支持 ${ENV} 展开;空或无效模式、空/含空白/重复 scope,以及同一 backend 内重复 match 都会被拒绝。
托管 HTTP tool 的边界刻意小于 proxy:手工定义和 OpenAPI import 会转换为命名 MCP tool,只有这些名称能经 /mcp 列出或调用。Base URL/Header/OAuth/scope/timeout 从所属工具组继承,不能从 tool 请求中推断凭证。OpenAPI source 的 inspect、持久化和刷新都属于 admin 操作;POST /api/v1/tool-groups/{groupID}/imports/inspect 的文档请求受 6 MiB body 上限和 5 MiB 解析后文档上限约束。
JWKS ready 要求至少一个可用的非对称公开验签 key:use 为空或为 sig;存在 key_ops 时必须包含 verify;显式 key alg 必须匹配 OIDC discovery 的 id_token_signing_alg_values_supported 中支持的 RSA、EC 或 Ed25519 JWS 算法。若 discovery 未声明该列表,则按 RS256。同一 JWKS 中的坏 key 或不支持 key 不会遮蔽其他可用 key。
安全相关改动应包含聚焦于行为边界的测试,并在 Pull Request 中解释兼容性或威胁模型影响。不要因为本地测试通过就声称发布版本绝对安全,应说明部署假设和剩余限制。
setup uses the existing browser login and consent paths. Its consent-options API requires a verified MCP token and only reveals eligible published tool names, effects, required scopes and resource constraints. This control-plane disclosure does not unlock strict MCP catalogs or permit calls. Selection is explicit; write/unknown tools require opt-in and still require per-operation approval. Configuration output contains no credentials and does not overwrite application files.
Cross-user grant queries, request diagnostics and NDJSON exports require configuration-administrator authorization on the admin listener. The owner portal remains subject-scoped. Managed SQLite/PostgreSQL persist completed MCP POST metadata for 30 days by default (admin.request_retention, 1–365 days); unmanaged deployments retain only the bounded in-memory diagnostics. Records exclude arguments, results, resource values, tokens and arbitrary error bodies. Detailed records are encrypted, but query indexes retain identity/routing metadata. Protect database backups and exports as personal operational data. Persistence follows request processing; failures are reported without replaying operations, and a crash before persistence can leave a gap. In-flight requests and GET streams are outside this history, which does not replace an independent audit archive.
Personal-account diagnostics read bindings and credential status without refreshing credentials or executing tools. A successful check cannot prove downstream business permissions.
setup 复用既有浏览器登录和同意流程。授权候选目录要求已验证的 MCP Token,仅披露当前身份可申请的已发布工具名称、读写属性、Scope 和资源限制;这项控制面展示不会开放严格模式 MCP 目录或调用权限。工具必须明确选择,写入/未分类工具需单独同意且仍受单次审批限制。生成配置不含凭证,不覆盖客户端文件。
跨用户授权查询、请求诊断与 NDJSON 导出仅允许管理监听器上的配置管理员访问,个人门户仍限定当前 Subject。托管 SQLite/PostgreSQL 默认保存 30 天已完成 MCP POST 的元数据(admin.request_retention,1–365 天),非托管部署仅保留有容量上限的内存诊断。不保存参数、结果、资源值、Token 或任意错误正文;详细记录加密,查询索引仍含身份/路由元数据。应按人员相关运维数据保护数据库备份和导出文件。持久化在请求处理之后执行,失败会提示缺口且不重放业务操作,保存前崩溃可能丢失记录。执行中请求和 GET 流不在范围内,请求历史不能替代独立审计归档。
个人账号诊断只读取绑定与凭证状态,不刷新凭证或执行工具;检查通过不证明后端业务权限。
v2.4.0 targets fresh deployments. auth.mode: builtin requires managed storage and derives the issuer from the public MCP origin plus /sso. Initialize locally with mcphub init-admin; there is no default password, anonymous web bootstrap or migration workflow. The first account belongs to a locally managed Administrators group. All roles, scopes, tools and business-resource grants belong to groups; users hold account state and memberships only. Authorization checks current active groups on every request. Group changes or membership removal cancel affected in-flight requests and reject stale views. The final active administrator is protected against account disable, membership removal and group demotion. Enterprise directory deactivation remains authoritative.
Passwords use salted Argon2id (19 MiB, 2 iterations, 1 lane). Five consecutive failed attempts lock an account for five minutes; IP and hashing concurrency limits protect login capacity. Password changes/resets, MFA enrollment and account disable revoke sessions and refresh credentials. Credential epochs reject earlier password proofs and authorization codes. TOTP secrets are encrypted; verification checks adjacent 30-second windows and rejects code reuse. Approval proof is bound to a user, session and request, expires after two minutes and is consumed once.
Local console cookies may use HTTP only on a validated numeric loopback listener; remote and personal-portal cookies remain Secure and require trusted HTTPS. Both require browser session, Origin and CSRF checks for mutations. Enterprise and local identities retain separate providers and stable IDs. Independent permission groups accept local members or explicit administrator-owned mappings from source organization groups; identical names never create mappings. Upstream claims/directory snapshots cannot edit permission groups, mappings or local memberships. Enterprise membership must remain fresh within auth.enterprise_membership_max_age; directory suspension remains authoritative.
v2.4.0 仅面向新部署。默认使用内建账号,本机初始化首位管理员及 Administrators 组;角色、Scope、工具与业务资源权限只分配给组,用户只维护状态和成员关系。权限每次请求重新计算,退组、停用组或收回授权阻止越权调用;保护最后一位有效管理员,但企业目录停用仍然生效。内建密码采用带随机盐的 Argon2id,连续失败锁定持久化;密码修改、重置、MFA 绑定或停用账号撤销会话与刷新凭证。普通密码登录不构成 MFA,审批加强认证需要绑定本审批单的密码和 TOTP 证明。本地组成员关系与身份源成员关系分别维护,不按同名身份自动合并。详见内建账号与组管理。
Built-in mode keeps a local recovery administrator and supports one LDAP directory and one OIDC connection together. Administrator writes and probes require the same console authorization, CSRF/Origin and revision checks as other managed settings. Connection records and secrets are encrypted with the configuration key; API responses expose only secret-presence flags. Saving applies immediately and revokes affected enterprise users' sessions, refresh credentials and incomplete login proofs, including credential epoch zero. Persisted settings take precedence over an optional YAML seed after restart.
LDAP uses verified TLS (LDAPS or mandatory StartTLS) before any bind, rejects empty user/service passwords and escapes filter substitutions. User and group IDs come from immutable attributes; binary AD GUIDs are encoded rather than treated as text. Ambiguous users, missing IDs, incomplete group searches and TLS failures deny login. Login attempts have IP, username and concurrency limits. New enterprise users remain pending. LDAP/OIDC organization groups stay source-owned; administrators can explicitly map them to shared permission groups. Matching names never confer access. LDAP password login is single factor and cannot satisfy an OIDC or local TOTP approval requirement. Directory membership refreshes on sign-in; directory password changes/offboarding do not immediately revoke issued MCPHub sessions. Disable the account or connection in MCPHub when immediate revocation is needed. See identity services.
内建模式保留本地恢复管理员,LDAP 与 OIDC 可同时在 UI 配置。密钥加密保存,API 只返回是否已配置;保存后即时生效,并撤销受影响企业用户的会话、刷新凭证及未完成登录证明。LDAP 必须使用校验证书的 LDAPS 或 StartTLS,拒绝空密码并转义过滤器参数;稳定 UUID/GUID、完整组查询与身份源隔离保护授权边界。LDAP 密码登录不构成 MFA。目录成员关系在登录时刷新,目录停用或修改密码不立即撤销已签发凭证;需要立即撤销时在 MCPHub 停用账号或连接。见身份服务指南。
Optional auth.sso makes MCPHub a separate issuer. Only configured HTTPS upstreams and pre-registered downstream client/redirect/resource tuples are accepted. Authorization uses S256, browser-bound single-use state, nonce and one-minute single-use codes. OIDC identities require signed ID tokens; OAuth2 uses the configured HTTPS UserInfo response, stable subject mapping, optional success-code and tenant restrictions. Unverified email, proxy headers and upstream role names never assign local privileges. Upstream OAuth2 without verified OIDC evidence cannot satisfy approval MFA.
Local users are isolated by provider connection (issuer, protocol, client ID and subject/tenant mapping) and subject, pending by default. Only active permission-group grants form the user’s permissions; direct user grants are rejected. Source organization membership cannot cross providers; explicit mappings resolve it to independent permission groups. Tool/write/resource predicates must match together within one access entry. Shared tool publication, scope/resource policy, client grants and per-operation write approvals remain additional restrictions. Admin role alone does not grant business tools. Directory sync has a separate secret and strictly accepts identity/active/membership fields, never roles or grants; snapshots replace membership atomically and reject stale versions. Directory-active and locally-enabled states are both required. Claim-only login cannot detect upstream offboarding between logins; directory-mode revocation depends on sync cadence.
Ten-minute signed access tokens also require a live local session and current permissions on each request. Rotating refresh families last at most eight hours; replay of a consumed credential revokes the family. Upstream refresh credentials are not retained or periodically checked. Signing keys are encrypted with the existing configuration key; refresh credentials are hashed. Permission changes cancel affected admitted requests and reject stale cached views, but cannot undo writes already accepted by a backend. Pending login codes are process-local; deployment remains single instance for both database engines. Local identity and membership records contain operational personal data; protect database backups and administrator access. See deployment contract.
开启 auth.sso 后,MCPHub 自己签发凭证;上游应用密钥留在服务端,上游 Token 不透传给 MCP 客户端或后端。身份校验与本地授权分离,用户首次登录待授权;引导管理员只在首次创建时加入本地管理的管理员组,不能在后续登录覆盖管理员的撤权。部门/组同步不能修改本地授权;完整目录快照需先核验所有分页,不能在上游失败时用空快照覆盖。声明模式只在登录时更新成员关系,离职实时性需要目录推送;本实现没有上游全局退出联动。管理员修改组权限/用户组成员关系会审计并立即影响新请求;既有工具配置审批与写审批边界继续保留。配置接口是管理员权限,不是审批动作本身。详细配置见中文说明。
Local SSO permission edits protect the final effective administrator, including group/department inheritance and concurrent changes. Authoritative directory revocations remain effective even for the final administrator. This safeguard cannot protect against direct database/configuration edits; trusted operators can recover with the built-in local administrator, whose password/MFA can be reset using the local init-admin procedure.
本地 SSO 权限编辑会保护最后一位有效管理员,覆盖部门/组继承和并发修改;权威目录停用即使影响最后管理员也继续生效。此保护不防御直接修改数据库或部署配置,可信运维人员可使用内建本地管理员恢复,其密码/MFA 可在服务器本机通过 init-admin 重置。
Vault KV v2 integration stores personal upstream tokens outside the managed database. It is opt-in and currently covers remote MCP endpoints. Personal connections require a valid user identity and ClientGrant; upstream credentials do not bypass scopes, resource restrictions or per-action write approvals. Tokens are never returned to a Broker or Agent. Changing or disconnecting an upstream account invalidates its owner’s existing endpoint grants and cancels admitted work; completed downstream writes are not reversible. Vault outages fail closed, and disconnected secrets are queued for deletion. Provider-side OAuth revocation remains a separate operation.
Protect Vault policies, the Hub process and configuration administration. Use a separate Vault prefix per deployment, retain coordinated database/key/Vault backups, and review restored authorization state. Single-instance refresh serialization does not provide distributed transactions or multi-instance coordination. See Vault setup and operational limitations.
Native clients registered by administrators use authorization code + PKCE S256, exact redirect/resource validation and explicit per-service consent. Registrations are revision-bound: editing or removing a client revokes its sessions and grants. Bearer sessions carry server-side service-grant bindings, with each service authorized independently; revoking one service leaves unrelated valid grants usable. New tools do not widen old grants. Device pairing still selects one service and does not expose credentials to the Agent.
Configuration drafts are encrypted with the deployment key. Previews redact secrets; validation and application check the base revision and existing approval policy. Rollback creates a new draft and never restores revoked sessions or grants. Direct management API writes retain their existing authorization and governance checks.
Logical backups contain encrypted secrets and readable identity/configuration metadata. Protect the complete backup and retain the matching key separately. Recovery requires the same engine, current schema and an empty target; it revokes old sessions, refresh families, Broker/service grants, pending device requests and unfinished approvals, and rotates signing keys. Users must authenticate and consent again. Isolated database verification does not prove recovered backend calls work; complete business checks before switching production.
标准 OAuth 客户端使用 PKCE S256、明确注册的回调与资源地址,以及逐服务同意。注册变更撤销该客户端的会话与授权;各服务独立检查和撤销,新工具不自动进入旧授权。配置草稿加密保存,脱敏展示并检查基础版本及既有审批规则;回退不恢复已撤销凭证。逻辑备份包含加密密钥字段与可读身份元数据,须保护完整备份并单独保存匹配的配置密钥。恢复只接受同引擎、当前 schema 的空目标,并撤销旧安全状态、轮换签名密钥;用户需重新登录和授权。切换生产前还须验证真实后端调用。详见恢复手册。