跳转到内容

NextPDF Connect 安全与运维

NextPDF Connect 通过 API key bearer token 对网络传输进行验证。它将本机 MCP 传输隔离为受信任的子进程,并在每个高风险工具执行前加入明确的人为确认把关。本页说明验证模型、传输安全和威胁模型。

Terminal window
composer require nextpdf/server

服务器有三道信任边界,分别对应三种传输。

这里的 MCP stdio 传输 是由本机客户端启动的子进程。它从标准输入读取 JSON-RPC,并将响应写回标准输出。这种传输没有网络监听器,也没有 API key。信任继承自操作系统的进程边界,这正是 MCP 规范为 stdio 定义的信任模型。日志输出到标准错误,因此绝不会污染协议流。

这里的 REST 传输gRPC 传输 属于网络传输。除不需验证的健康探测(health probe)之外,两者的每个请求都必须携带 API key bearer token。两种传输底层共用同一套密钥存储区、密钥格式与常数时间验证。gRPC 传输从调用元数据(metadata)读取 token,REST 则从 Authorization 标头读取。

如果验证实现不正确,就属于 OWASP API Security Top 10 标记为 API2:2023 Broken Authentication 的那类失误。这类实现缺陷会削弱 API 识别调用方的能力,从而损害 API 的整体安全性(OWASP API Security Top 10,API2:2023)。弱 token 或可预测 token 也被明确列为一种 broken-auth 反模式(同一来源,弱点清单)。下面的设计正是为应对这两类问题而构建。

密钥格式为 npk_live_{kid}_{secret}kid 是一个八字符标识符,用于 O(1) 记录查找;entropy(熵)由 secret 承载。存储区绝不保留原始密钥,只保存完整密钥材料的 SHA-256 摘要。每个请求进入时,服务器会对提交的 token 计算哈希,再通过常数时间比对(hash_equals)与已存储的摘要比较,因此错误密钥不会因计时差异泄漏任何信息。已停用或过期的密钥会在哈希检查之后被拒绝,而不是在此之前。

REST 与 gRPC 的验证器共用这套逻辑。REST 中间件(middleware)会读取 Authorization: Bearer npk_live_…。gRPC 验证器则从 gRPC 的 authorization 调用元数据读取同一组 bearer token;该元数据通过 HTTP/2 标头传输。验证器会以 gRPC 的 UNAUTHENTICATED 状态使该调用失败。

两个传输还会对预认证流量施加一道反自动化限流:来自同一客户端身份的过量尝试会触发速率限制并被拒绝——REST 上为 429 Too Many Requests,gRPC 上则为 gRPC RESOURCE_EXHAUSTED 状态。此控制默认启用,因此即使某个部署未额外配置速率限制存储区,也仍然受到保护;客户端应退避,而不是立即重试。

如果 REST 请求携带的密钥缺失、格式错误、已停用或已过期,会收到 401 Unauthorized,并附带一份 problem-details 响应体与一个 WWW-Authenticate: Bearer 响应标头。这符合 HTTP 要求:401 响应必须带有至少包含一项挑战的 WWW-Authenticate 标头字段(RFC 9110 §11.6.1)。这项要求又源自另一条规则:对于未提供凭证或携带无效凭证的请求,应以 401 加一个 WWW-Authenticate 挑战来响应(RFC 9110 §11.6)。

每条密钥记录都包含一个最高产品层级。REST 管道会将已验证客户端的身份与层级附加到请求上,供下游授权按层级强制限制能力与载荷上限。即使已安装相关包,core 层级的密钥也无法执行 Pro 或 Enterprise 操作。

  • MCP 传输没有 API key。 对本机子进程而言,这是刻意且正确的设计。不要通过任何网络 shim(兼容层)把 MCP 服务器对外暴露。如果某个网络 AI Agent(代理)需要使用这些工具,请把它放在会执行验证的 REST 或 gRPC 传输前面。

  • 健康探测刻意设计为匿名。 其中 /healthz/readyz 会略过验证,让编排器无须凭证即可探测存活与就绪状态。它们只返回状态,不会暴露任何工具或文档数据。

  • 确认 token 单次使用且有效期短。 human-in-the-loop 把关会发出一个绑定工具名称、有效期 300 秒的 token。该 token 首次使用后即被消耗。它不是验证凭证,也不能替代 API key。

每个请求的验证只是一次哈希加上一次常数时间比对。相对于一次 render(渲染)的成本,这项开销微不足道。支持热重载的密钥存储区会在密钥文件变动时重新加载,因此轮换密钥不需要重启,也不会增加每个请求的成本。

每个工具都会声明一个风险等级。风险等级为最高等级 ApprovalRequired 的工具,在第一次调用时不会执行。确认把关会返回一个包含单次使用 token 的挑战。代理必须将这个挑战呈现给人类,再携带该 token 重新调用该工具。这是在自动化行动引入风险的节点上有意设置的控制。这正是 IEC 31010 所指出的位置:在人为(此处为代理)行动引入风险的当下或邻近处控制风险(IEC 31010:2019)。这道把关不能通过配置削弱:配置覆写只能提高某个工具的风险等级,绝不能调低一个 ApprovalRequired 工具。参见 /connect/hitl-risk-tiers/.

网络传输本身不负责 TLS 终止;TLS 属于部署层面的考量。参考的组合部署会以 mutual TLS(双向 TLS)运行 gRPC 传输,其中密钥、证书和客户端 CA 都以部署机密的形式提供。在 mutual TLS 之下,服务器会出示一张证书,并要求且验证一张客户端证书。请将 REST 传输运行在 TLS 终止器(反向代理或服务网格)后面,并且绝不在不受信任的网络上暴露明文监听器。配置细节见 /connect/deployment/;这是一份态势声明,不是开箱即用的保证,安全传输需要正确的部署配置。

写文件工具会以配置的基准目录为基准,对请求路径进行 resolve(解析)和规范化,并拒绝 null 字节、protocol wrapper 以及 .. 路径穿越。任何解析后落在基准目录之外的路径都会被拒绝。请将基准目录放在专用卷上,并应用最小权限的文件系统权限。

服务器只会在设定的 TTL(默认 1800 秒)和有界数量(默认 50)范围内,将文档保存在内存文档存储区中。除非明确调用了写文件工具且路径通过限定检查,否则它不会把文档内容持久化到磁盘。服务器不会为了渲染或检视文档而发起任何出站网络调用,因此除非某个工具被明确配置为抓取远端资源,文档字节不会离开该部署。对于无状态且对驻留敏感的部署,请停用文件输出(allow_file_output: false),并将 enabled_tools 限制到最小集合。

审计日志会记录 Caution 风险等级以上的工具执行,以及每次发出的确认挑战。审计记录会带上工具名称、风险等级与成功标志。请将工具参数视为可能包含敏感信息:将日志导向具备访问控制的接收端,并且不要把全局日志等级调高到会在共享环境中回放参数载荷的详细程度。MCP 传输将日志写入标准错误,目的正是确保日志内容绝不会进入标准输出上的协议流。

主张来源reference_id
验证失误会削弱 API 安全性OWASP API 安全性 Top 10,API2:2023
弱 token 或可预测 token 是一种 broken-auth 反模式OWASP API 安全性 Top 10,API2:2023
401 必须包含一个 WWW-Authenticate 挑战RFC 9110 §11.6.1
缺失/无效凭证 → 401 加挑战RFC 9110 §11.6
在(人为)引入风险的当下控制风险IEC 31010:2019

Model Context Protocol 的 stdio 信任模型遵循官方 MCP 规范修订版 2025-06-18。由于 MCP 规范并不属于受管标准语料库,因此它及其网址记录在 /transports/mcp/。

签章、遮蔽、合规与取证工具,仅当 nextpdf/premium 与服务器一同安装时才会存在。它们的存在不会改变验证模型。其风险层级仍会把具有破坏性的工具置于 human-in-the-loop 把关之后。

  • /connect/hitl-risk-tiers/ — 风险模型与确认封套的详细说明
  • /connect/deployment/ — TLS、mutual TLS、机密与 worker 调优
  • /transports/rest/ — REST 中间件管道与 OpenAPI 安全方案
  • /transports/grpc/ — gRPC 元数据验证与状态码
  • /connect/configuration/ — enabled_tools、密钥存储区选择、风险覆写