Skip to content

v1.3.6 — 进程身份、凭据边界与跨进程互斥

Choose a tag to compare

@cullysu cullysu released this 16 Oct 18:25
· 1 commit to main since this release

v1.3.6 — 进程身份、凭据边界与跨进程互斥

针对 v1.3.5 独立审计(50 项行为缺陷,13 项带隔离实测,commit e0e4364)逐条处置:40 项行为缺陷已修,8 项按审计自身的说明归入"已知未结"(见文末),1 项(F07 发布签名)只能由证书账号闭合。

桌面壳不再被假服务骗到(F01)

  • 旧实现把"端口上有人回 HTTP/1.x 200"当成工作台,会把 API token 交给占位进程。现在 Electron 与 Tauri 都向新增的免鉴权 GET /api/identify?n=<hex> 发一次性随机 nonce,要求 x-piwb-proof = HMAC-SHA256(API_TOKEN, nonce);Tauri 侧手写 HMAC(sha2)+ 常数时间比较,3 秒读超时保留。scripts/ui-contract-probe.mjs 增加该项的运行时断言。

凭据只在信任域内流转(F02–F04、F17–F19、F32、F38)

  • "不含密钥"导出写明范围并真正执行:manifest 带 scope/scopeNote,config.json/settings.json 以脱敏副本入包,baseUrl 的 userinfo 与凭据类查询值一并剥离,恢复前对 provider 行做形状校验。
  • MCP 哨兵不再跟着改掉的命令走:*** 环境/参数只在 command + args 身份一致时还原;配置文件改为 mkdir 后先暂存再替换。
  • 只写 key 字段在所有出现处都脱敏(scrubUrlCreds / scrubArgSecrets / maskApiKeys),被掩码的 models.json 往返不再摧毁已存 baseUrl。
  • key 冷却绑定凭据的 env 名,而不是数组下标(provider#env:NAME)——换序/移动过的 key 不再冷却错误的槽位;字面 key 供应商 keyEnvsFor 返回 [];nextInChain 拒绝 models.json 里不存在的 provider/model,不再把它当免密供应商。
  • 损坏配置留证进 corrupt-backups/,最多 3 份、0600。
  • Windows 凭据文件 ACL 不再只保护 token(F08):服务端与备份模块写入的每个凭据文件都按当前用户收紧 DACL(icacls /inheritance:r /grant:r <user>:F)——token、config.json、models.json、mcp.json、routing.json、cron.json、settings.json、model-meta.json,以及导出的 zip、恢复快照与恢复临时文件。POSIX 的 0600 本来就是对的,Windows 之前等于没设。

日志脱敏如实说明范围(F05、F06)

  • cron 单次运行日志创建即 0600(F05)。
  • docs/TROUBLESHOOTING.md 不再暗示"日志已脱敏":明确列出会替换的模式,以及不会替换的秘密(其它格式 key、Cookie 值、URL 查询串 token、子进程 stderr),并要求提交前人工确认(F06)。

Cron:单写者 + 诚实的窗口(F09–F16)

  • 跨进程单写者:每个任务一把锁文件(openSync('wx')、0600、30 分钟后可接管、bootReset 清扫),两个服务实例不再跑同一个任务(F09/F10)。
  • daily 当天窗口只在 spawn 成功后消费:spawn 抛错、key/model 冷却都改为延期而不是烧掉当天(F11–F13)。
  • settle 记录本次实际使用的 provider/model/key 身份,__keyIdx 从子进程环境剥离(F14)。
  • 运行中的任务可以取消:停用/删除任务会终止其子进程;settleWatch 在 close 永不到达时兜底终结;日志 fd 0600(F15/F16/F05)。

界面不再展示乐观假象(F20–F22、F40–F45)

  • WS open 解析生效模型(默认模型 + 停用供应商门禁)并固定路由 key env;跨供应商 set_model 会重启该 tab 的 pi 并上报 pi-restarted(F20/F21)。
  • 用过工具的那一轮不再自动重发——副作用重复前必须由用户确认(F22)。
  • set_model 未被确认时模型 chip 回滚(F41);goal 对话框先回答等待中的 modal 再替换(F42);goals/主题/供应商/技能/cron 与高级 JSON 编辑器都检查后端回执并在失败时回滚(F43/F40);结构化 API 错误按错误渲染,不再显示成"空文件"/"没有会话"/"今日 0"(F44);附件在发送前做尺寸门禁,不再因超过 8 MiB WS 帧而清空草稿并断连(F45)。

读取器与账本不再丢数据(F23–F31、F34)

  • Codex 导入保留真实的重复轮次(合并不同轮次的去重已移除);pi/Claude 导入保留原始时间戳与工具错误语义;各会话解析器的头部读取补齐 null 守卫(F23/F24/F29/F30)。
  • 会话导出默认按活动分支(?all=1 导出全部分支),中途失败回包带可见错误块而不是静默截断的 200,无内容时降级为文本说明而不是空文件(F25/F28)。
  • Claude 账本按 message.id last-wins(旧实现 first-wins 会丢掉最终 usage);会话树上报 windowed;readJsonl 返回 {items, truncated},用量/账本暴露 cappedFiles/truncatedFiles(F26/F27/F31)。
  • saveModelMeta 改为 tmp+rename(F34)。

开发一致性与文档(F49)

  • README 代码围栏修正;README.en 补齐它缺的 prepare-runtime + embed-token 流程;prepare-runtime.mjs 拷贝 data/,开发环境 KB 不再静默为空。

验证

lint 0、测试 40/40、路由扫描 47 PASS、探针(ws / failover / ui / chat / contract)全 PASS;契约测试 23 → 39 项:新增 16 条锁定本轮修复(env 名 key 身份、字面 key 供应商、回退链校验、daily 窗口延期、导出分支与空transcript、错误形状渲染),ui-contract-probe.mjs 增加 F01 挑战应答检查。CI 8 job 全绿后从 CI 产物发布(5 件资产 + SBOM + SHA256SUMS.txt,逐件校验 artifact digest 与条目名)。

已知未结(按审计原文的口径):F07 发布签名(等证书账号——hash 清单能查损坏,不能认证恶意发布)、F33 恢复的崩溃安全事务日志、F35 Tauri 子服务监督/自动重启、F36 启动校验失败后自动从可信 ZIP 重建 runtime、F46 侧栏重绘引起全会话重扫、F47 长期运行资源全生命周期预算、F48 键盘/辅助技术路径与 modal 语义、F50 安装器级实机验收与供应链深度(action 摘要固定、Node 校验和签名、SBOM 分层、Windows/macOS 安装器冒烟)。