PR [#1719](https://github.com/makecindy/cindy/pull/1719) 触发了维护者确认门。 **触发类型**: product **触发原因**: feat 类型,新增插件凭证注入收窄策略 **作者**: FIERsity 请维护者审视此 PR 的产品方向,确认后在 PR 上 Approve;需要修改请 Request Changes,作者改完后重新 Approve 即可放行。 --- 关联 PR:#1719(作者 @FIERsity);本 issue 由 review-pr 流程自动创建,用于先讨论该 PR 涉及的产品 / UI 变更,维护者确认后 PR 会恢复推进。
Activity
dash-s-cindy commentedon Aug 6, 2026
判断
同一域名下的公开端点与鉴权端点需要不同的凭证注入范围,这是 Ghost network 能力中真实存在的表达缺口。为
network.secrets[].inject增加精确 pathname 与 HTTP method 白名单,可以让公开接口在未配置 Key 时正常访问,也能减少凭证被发送到不需要它的同域端点;这个产品方向值得继续推进。当前 file-converter 场景已有插件侧临时规避方式:删除未使用的 Secret/整域注入声明后,公开
/mcp可以恢复工作。但当插件未来必须同时调用同域的公开/mcp与鉴权/v1/convert时,现有 manifest 仍没有安全、准确的表达方式,因此临时规避不能替代宿主能力。行动
建议维护者确认产品方向,但暂时不要直接 Approve #1719。当前 PR 已经从 Draft 转为 Ready;直接 Approve 会解除合并门,而 mixed-version 的 fail-closed 发布机制仍未落地。更合适的处理是先 Request Changes,要求在放行前完成以下二选一方案,并以第一种为推荐:
inject.paths或inject.methods,就必须同时声明该标记。支持新版可正常安装;不认识该标记的旧版应整包拒绝,而不是忽略收窄字段后继续按整域注入。.cindy安装;只在服务端隐藏新版插件不足以保护手动安装包。当前源码快照中未发现 manifest 或安装链路可执行的minAppVersion/minimumAppVersion机制,因此不能把它当作现成保障。安全发布顺序应为:先落地 fail-closed capability/version gate 与 Desktop 支持并发布,再合入协议定义及服务端消费,最后才允许发布实际使用新字段的插件。若团队希望先合并纯宿主实现,也应把协议公开、作者手册对外宣告和插件发布继续锁在同一发布门后,不能把“暂不发布”作为唯一安全边界。
已确认的现状
基于
origin/main@3cce98e788c8fabfb913d3b27a1152c55094adfe:apps/desktop/src/shared/ghost.ts的GhostSecretInjectDecl当前只有hosts、header、format,没有 path 或 method 条件。validateGhostManifest()只校验inject.hosts是network.hosts的子集。由于 manifest 在规范化时只重建已知字段,旧客户端会接受包含未知paths/methods的原始对象,但在规范化结果中丢弃它们。apps/desktop/src/main/cindy-brain/networkSlot.ts的injectSecrets()仅以 hostname 判断是否注入。命中 hostname 但凭证未配置时,请求会在真正出网前快速失败,这与 [Ghost] 同域公开与鉴权端点无法分别控制凭证注入 #1714 中公开/mcp被可选 Key 阻断的表现一致。injectSecrets(),但重新判断的仍只有 hostname;因此同域从受保护 path 跳到公开 path 时,现有版本不会撤掉该域对应的凭证。对 #1719 实现的判断
#1719 的运行时方案整体已经收敛到合理的第一版:
paths使用精确URL.pathname匹配,query 不参与;methods显式声明时才限制,二者与 host 为 AND 关系;FORGE_GUIDE与中英日韩权限文案已同步。PR 描述报告的验证包括 Desktop typecheck、完整 unit tier、
ghost.test.ts/networkSlot.test.ts/forge.test.ts共 284 个定向测试,以及 i18n 与相关检查。PR patch 中也能看到精确 path/method、query、同域重定向、302 POST→GET 后按实际 method 重算、伪造凭证头剥除等覆盖。就匹配逻辑本身看,没有发现需要改变产品方向的反证。真正尚未闭合的是发布兼容:旧 schema-v2 客户端会忽略新字段并继续使用 host-only 语义。这虽然“不比旧产品现状更宽”,却会违反新版插件作者和用户所依赖的安全声明——作者以为凭证只会发往
/v1/convert,旧客户端实际上会把它发往同域所有路径。对于凭证授权边界,这种静默退化不能作为可接受降级。建议补充的验收项
在现有运行时测试之外,合并门应增加 mixed-version 验收:
paths/methods的 manifest 在支持版客户端上正常安装,并保持字段穿过安装、市场 release manifest 规范化和运行时读取链路。.cindy安装。..、尾斜杠、大小写和重复项保持固定的 fail-closed 测试。相关记录
/mcp因缺少可选 Key 被阻断,以及删除未使用 Secret 后恢复的实测结果。inject.paths/inject.methods及 delivery 规范化测试;在客户端能力与服务端发布顺序确定前,不应单独把该协议作为可安全分发的能力信号。FIERsity commentedon Aug 8, 2026
mixed-version fail-closed 门禁已实现(方案 1:capability/schema 标记)
按 bot 推荐方案 1,为 endpoint-scoped secret 实现了旧客户端必然拒绝的 schema 标记:schemaVersion 3。已同时推送到 #1719(桌面)与协议仓 #30(HEAD 6d1a4f2)。
机制
inject.paths/inject.methods仅在 schemaVersion 3 清单中合法;v2 清单声明这两个字段 → 校验直接拒装(报错指明必须升级到 3)。raw.schemaVersion !== 2→ 整包拒绝,桌面 ghost.ts 与协议仓 manifest.ts 均如此),因此声明了新字段的 v3 清单在旧客户端上必然拒装,不会被静默忽略收窄字段后退化为整域注入。逐条对照验收项
validateGhostManifest统一入口,覆盖市场安装、更新与本地.cindy安装新增测试:协议仓 3 个(拒绝 v2+paths/methods 三种形态、v3 host-only 放行、v2 拒装 reason),桌面 2 个(v2 拒装循环、v3 host-only 放行);两仓原有 endpoint 测试升级到 v3。桌面 178+133 测试、协议仓 274 测试全过,tsc/eslint/i18n 门禁干净。
发布顺序
符合 bot 建议的安全顺序:宿主实现 + 门禁先合并,协议与服务端消费随后,实际使用新字段的插件最后发布。#1719/#30 均未发布任何使用新字段的插件。
请确认后解除 Request Changes,放行 #1719 合并。