From 91a0846dfc93baec35939777abe747da82c692ae Mon Sep 17 00:00:00 2001 From: ReSerendipity Date: Mon, 21 Sep 2026 12:32:04 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(deps):=20=E9=94=81=E9=9B=86=E4=B8=89?= =?UTF-8?q?=E5=A4=84=E9=9D=9E=E6=B3=95=E7=BA=A6=E6=9D=9F=E6=94=B9=E5=88=B0?= =?UTF-8?q?=E5=90=88=E6=B3=95=E4=B8=94=E4=B8=8E=E5=B7=B2=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E4=B8=80=E8=87=B4=EF=BC=8C=E5=B9=B6=E6=8A=8A?= =?UTF-8?q?=20crossconflict=20=E6=A3=80=E6=9F=A5=E6=8E=A5=E8=BF=9B=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 两件事叠在一起,结果是"按 lock 装环境的人拿到破图,而开发机能跑": 1) 锁集自相矛盾(两份清单各三行):tokenizers==0.23.2 同时违反 transformers 4.52.1 要求的 <0.22 与 indextts 要求的 ==0.21.0;antlr4-python3-runtime==4.13.2 违反 hydra-core/omegaconf 的 ==4.9.*;mpmath==1.4.1 违反 sympy 1.14.0 的 <1.4。 改为 0.21.0 / 4.9.3 / 1.3.0(既是唯一合法解,也正是本机跑通真推理的那组版本)。 scripts/check_pin_crossconflicts.py 由 exit 1 → exit 0(95 包,冲突 0,未核验 0)。 2) 检查器从没接线:它只挂在 .pre-commit 的 files: 条件上(改动 lock 才触发), 所以已经坏在 main 上的锁集它永远看不见,CI 一片绿。现在 ci.yml 的 lint job 每次 PR/push 都跑(新增 "Pin cross-constraint gate" 一步)。 顺带纠正一处会把人带偏的声明:pyproject/requirements 的 transformers>=4.57.0(9-14 搭在一条 gpu-smoke 提交里进来的)实测站不住 —— 4.57.6 下 VoxCPM2 正常(合成 243,164 B、 RMS 5360),但 IndexTTS 2.5/2.0 的 infer_v2_5 / infer_v2 直接导入失败;4.52.1 + tokenizers 0.21.0 下三引擎真推理全通(2.5 出 214,040 B / RMS 6176,2.0 出 205,124 B / RMS 6926, VoxCPM2 出 230,148 B / RMS 4615,每次卸载显存回到 ~3.5 GB)。故下界改回 >=4.52.1,<4.53 并把证据写进注释。引擎导入失败时的文案也不再断言"PyPI 无 indextts 包",改为带上底层 ImportError 与"多半是 transformers 版本不匹配"的提示 —— 就是这句话把我误导了两轮。 20 条 Dependabot 告警的可达性与处置逐条见 docs/SECURITY_DEPENDABOT_TRIAGE.md: 结论是没有一条能靠"现在就升级"消掉(4 条 ReDoS 要 4.53+ 被引擎精确 pin 挡住, 4 条要 transformers 5.x,2 条 protobuf 被 descript-audiotools<3.20 与 modelscope<3.21 挡住)。 门禁(冻结树复跑):2078 passed / 35 skipped / 0 failed,覆盖率 52.11%;mypy 103 = 基线; ruff check 通过、359 文件已格式化;完整性清单 16/16;sync_requirements.py 重跑无差异。 Signed-off-by: ReSerendipity --- .github/workflows/ci.yml | 10 +++ .../engines/indextts2_engine.py | 7 +- docs/DOD.md | 34 +++++-- docs/SECURITY_DEPENDABOT_TRIAGE.md | 90 +++++++++++++++++++ launcher/requirements-small.txt | 6 +- pyproject.toml | 10 ++- requirements-lock.txt | 6 +- requirements.txt | 4 +- 8 files changed, 147 insertions(+), 20 deletions(-) create mode 100644 docs/SECURITY_DEPENDABOT_TRIAGE.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 681e3f08..2e52cbce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,6 +65,16 @@ jobs: pip install pyyaml python scripts/check_declared_capabilities.py + - name: Pin cross-constraint gate (锁集自洽) + # 锁文件内部必须互相满足:A==x 声明 requires B<2,而锁里 B==2.3 就是破图 —— + # 用户 `pip install -r requirements-lock.txt` 装出来的是坏环境,`pip check` 才报。 + # 这类问题以前只有 pre-commit 的 `files:` 触发(改动 lock 才跑),所以已经坏在 + # main 上的锁集没人看得见(2026-09-21 实测:transformers==4.52.1 要 tokenizers<0.22 + # 而锁里是 0.23.2,另有 antlr4/mpmath 两处)。这里每次 PR 都跑,漂移当场红。 + run: | + pip install packaging + python scripts/check_pin_crossconflicts.py + - name: Integrity manifest sync gate (security) # 防止「核心模块代码已改、完整性清单未重新生成」:改动 app/integrated_app/ 下 # 任一 _CORE_MODULES 文件后若未同步 security/integrity_manifest.json,运行时 diff --git a/app/integrated_app/engines/indextts2_engine.py b/app/integrated_app/engines/indextts2_engine.py index b5ec42e5..c5ade284 100644 --- a/app/integrated_app/engines/indextts2_engine.py +++ b/app/integrated_app/engines/indextts2_engine.py @@ -501,8 +501,11 @@ def _load_model(self) -> None: IndexTTS2 = _infer_mod.IndexTTS2 except ImportError as e: raise ImportError( - f"indextts 未安装或缺少 {self._infer_module} 推理模块。" - "PyPI 无 'indextts' 包,请从官方仓库安装:\n" + f"indextts 未安装或缺少 {self._infer_module} 推理模块" + f"(底层错误:{type(e).__name__}: {e})。" + "若 indextts 已安装,多半是 transformers 版本不匹配——本引擎按 " + "transformers 4.52.1 验证通过,4.57.x 下该模块导入会失败。" + "确未安装时(PyPI 无 'indextts' 包)从官方仓库装:\n" " git clone https://github.com/index-tts/index-tts.git\n" " cd index-tts && pip install -e .\n" "(2.0 与 2.5 共用同一仓库,安装一次即同时提供 infer_v2 与 infer_v2_5)" diff --git a/docs/DOD.md b/docs/DOD.md index 0d5ba766..2b2725a3 100644 --- a/docs/DOD.md +++ b/docs/DOD.md @@ -96,9 +96,11 @@ 第 5 项的"按钮要做事"已真机验过:400 错误块带 `role="alert"` + 「立即加载」「重试」两个按钮, 点重试 XHR 计数 +1 且错误块重新渲染(此前该按钮调的是从未定义的函数,纯死键,#133), 第 9 项 6 轮切换实测空闲显存回到切换前水平(spread 416MB,无单调递增)。 - **仍需人工:第 7 项真开一次屏幕阅读器。**(第 8 项断网首屏已于 2026-09-20 转为机器判定,见 §5.2) + **人工项已全部走完**:第 7 项屏幕阅读器由仓库所有者于 **2026-09-21 实机判定通过** + (NVDA/VoiceOver 走"选音色→输入→生成→播放",遮罩阶段变化有朗读);第 8 项断网首屏已于 + 2026-09-20 转为机器判定(`scripts/check_offline_first_paint.py`,见 §5.2)。 - 2026-09-21 本轮补记(分发产物与前端竞态,`fix/tab-race-and-dist-payload`,基线 = `origin/main` e104809): - * **门禁**:非 e2e **2078 passed / 35 skipped / 0 failed,2m24s,覆盖率 52.04%**; + * **门禁**:非 e2e **2078 passed / 35 skipped / 0 failed,2m33s,覆盖率 52.11%**; `tests/e2e`(服务在线)**68 passed / 5 skipped**;mypy **103 = 基线**; ruff check 全通过、`ruff format --check` 359 文件已格式化;完整性清单 **16/16 一致**; 无硬编码路径 exit 0;`test_portable_bundle.ps1` **49 条断言全通过**; @@ -113,11 +115,29 @@ 并新增 `tests/test_packaging_manifest.py`(25 条断言,含 4 条变异自证)常驻把关(#134)。 * **新修的用户可见缺陷**:侧栏换页竞态 —— 注入 1.5s 慢响应后,**修前 6/6 组末态被先点那一页 占住**(用户在错的页面上点生成 → 400),带 `hx-sync="#tab-content:queue last"` 后 **0/6**(#136)。 - * **仍未覆盖**:`docker build` 本机 daemon 未起(CI 的 `docker-smoke.yml` 会真构建,镜像结论 - 目前是 `.dockerignore` 静态复演);桌面安装包链路(staging → data 7z → NSIS)**无任何 workflow - 调用**、本机也无从安装(`scripts/installer/` 只有一个 4.3 MB `Setup.exe`、无同目录分卷), - 所以 `unpack_desktop.ps1` 新加的许可/字体落地核对只过了语法层;htmx 1.9.10 在队列换页时 - 自抛的一次 `insertBefore` TypeError(末态正确)未清,需另案升级 vendored 库。 + * **依赖锁集自洽性**(比告警更要紧):两份 lock 当时自相矛盾 —— `tokenizers==0.23.2` 同时违反 + `transformers 4.52.1` 要的 `<0.22` 与 `indextts` 要的 `==0.21.0`;`antlr4-python3-runtime` 4.13.2 + 违反 hydra/omegaconf 的 `==4.9.*`;`mpmath` 1.4.1 违反 sympy 的 `<1.4`。后果不是 CI 红,而是 + **按 lock 装环境的人拿到破图**,开发机能跑只是因为比 lock 早(本机 30/73 条与 lock 不一致)。 + 三行改到合法且与已验证环境一致后 `check_pin_crossconflicts.py` 从 **exit 1 → exit 0**(95 包 + 冲突 0、未核验 0),并接进 `ci.yml` 每次 PR 跑 —— 它原先只挂在 pre-commit 的 `files:` 条件上, + 已经坏在 main 上的锁集它永远看不见。 + * **transformers 上界被实测钉死**:4.57.6 下 VoxCPM2 正常(243,164 B / RMS 5360)但 + **IndexTTS 2.5 / 2.0 双双 `infer_v2_5` / `infer_v2` 导入失败**;回到 4.52.1 + tokenizers 0.21.0 + 后三引擎真推理全通(2.5:214,040 B / RMS 6176;2.0:205,124 B / RMS 6926;VoxCPM2:230,148 B / + RMS 4615;每次卸载显存回到 ~3.5 GB)。故 `pyproject`/`requirements.txt` 里那句 + `transformers>=4.57.0`(9-14 搭在一条 gpu-smoke 提交里进来的)改回 `>=4.52.1,<4.53` 并写明证据; + 引擎加载失败时的报错也不再断言"PyPI 无 indextts 包",改为带上底层 ImportError 与版本不匹配提示。 + 20 条 Dependabot 告警因此**没有一条能靠现在就升级消掉**,分诊见 `docs/SECURITY_DEPENDABOT_TRIAGE.md`。 + * **已知缺口**:CI 冒烟 `scripts/gpu_smoke_minimal.py` 只覆盖 voxcpm2 + indextts2(走 OpenAI 口, + 而 `tts-1` / `tts-1-hd` 两个模型名里没有 IndexTTS **2.0** 的位置);2.0 的真推理今天人工验过, + 要接进冒烟需改用 `/api/generate/indextts2` 形态并在 GPU runner 上复验,另案。 + * **仍未覆盖**:桌面安装包链路(staging → data 7z → NSIS)**无任何 workflow 调用**、本机也无从安装 + (`scripts/installer/` 只有一个 4.3 MB `Setup.exe`、无同目录分卷),所以 `unpack_desktop.ps1` + 新加的许可/字体落地核对只过了语法层,`release_gate.ps1` 的第 ⑥ 步也只在发版/dispatch 时跑; + htmx 1.9.10 在队列换页时自抛的一次 `insertBefore` TypeError(末态正确)未清,需另案升级 vendored 库。 + (原先记的"`docker build` 未实跑"已消掉:PR #100 的 `Boot hardened container & probe` 里, + 新加的"镜像内许可文本 + 字体计数"步骤在真构建产物上结论 success。) ## 6. 安全 & 隐私 diff --git a/docs/SECURITY_DEPENDABOT_TRIAGE.md b/docs/SECURITY_DEPENDABOT_TRIAGE.md new file mode 100644 index 00000000..a4cdc744 --- /dev/null +++ b/docs/SECURITY_DEPENDABOT_TRIAGE.md @@ -0,0 +1,90 @@ +# 依赖漏洞告警分诊(Dependabot alerts triage) + +日期:2026-09-21 适用:`main` @ PR #100 之后 责任人:仓库所有者 +状态:**20 条 open 告警 = 10 个公告 × 2 份清单**(`requirements-lock.txt`、 +`launcher/requirements-small.txt` 各计一次)。本文只谈"能不能修 / 该不该修 / 谁挡住"。 + +## 1. 结论速览 + +| # | CVE | 包 | 严重度 | 修复版本 | 谁挡住它 | 本仓可达性 | 建议处置 | +|---|---|---|---|---|---|---|---| +| A1 | CVE-2025-5197 | transformers | medium | 4.53.0 | `indextts==…`钉 `transformers==4.52.1` | tokenizer 正则 ReDoS,且仅 Marian/部分 tokenizer;我们走 GPT2/CLIP 路径,输入是本机用户自己键入的文本 | 关闭理由:本机自用 + 代码路径不涉及;待引擎适配后随版本升级自然消除 | +| A2 | CVE-2025-6051 | transformers | medium | 4.53.0 | 同上 | 同 A1 | 同 A1 | +| A3 | CVE-2025-6638 | transformers | medium | 4.53.0 | 同上 | MarianTokenizer —— 本仓不加载 Marian 模型 | 同 A1 | +| A4 | CVE-2025-6921 | transformers | medium | 4.53.0 | 同上 | AdaLight tokenizer 正则 —— 未使用 | 同 A1 | +| A5 | CVE-2026-1839 | transformers | medium | 5.0.0rc3 | 引擎钉 4.52.1(且 5.x 是大版本破坏性升级) | `Trainer` 代码执行:**全仓无 HF `Trainer` 用法**(`training/trainer.py` 里的 `LoRATrainer` 是我们自己的类,`grep from transformers import Trainer` 零命中) | 关闭理由:代码路径不存在 | +| A6 | CVE-2026-4372 | transformers | high | 5.3.0 | 同上 | 远程代码执行类:需要加载不可信仓库且 `trust_remote_code=True`。本仓权重是本地目录 + 人工核验 + SHA-256(`LOCAL_RULES.md` 禁区流程);唯一从 Hub 取物的是 `security/content_safety.py` 的 CLIP `AutoTokenizer.from_pretrained(model_name, revision=…)`(固定 revision、非攻击者可控) | 关闭理由:不接受用户指定模型源;保留复点 | +| A7 | CVE-2026-5241 | transformers | high | 5.5.0 | 同上 | LightGlue 等模型初始化路径 —— 本仓不加载该类模型 | 关闭理由:未使用组件 | +| A8 | CVE-2026-9856 | transformers | high | 5.10.0 | 同上 | `save_pretrained` 经 chat template 造成任意文件写:**全仓无 `save_pretrained` 调用**(音色保存写的是我们自己的目录) | 关闭理由:代码路径不存在 | +| P1 | CVE-2025-4565 | protobuf | high | 4.25.8 | `descript-audiotools 0.7.2` 要 `>=3.9.2,<3.20`;`modelscope` 的 audio extra 要 `>=3.19.0,<3.21.0` | protobuf 在本仓只被 tensorboard / tensorboardX / modelscope / descript-audiotools 间接使用,服务端**不解析任何来自网络的 protobuf/JSON wire 数据**(`grep google.protobuf app/` 零命中) | 关闭理由:无攻击面;要真修得换掉 descript-audiotools/modelscope 的锁上界 | +| P2 | CVE-2026-0994 | protobuf | high | 5.29.6 | 同上(且跨两个大版本) | 同 P1 | 同 P1 | + +一句话:**10 个公告里没有一个能靠"升个版"现在就消掉** —— 4 个 ReDoS 被 IndexTTS 引擎的精确 pin 挡住, +4 个需要 transformers 5.x(大版本),2 个需要 protobuf 越过 `descript-audiotools<3.20` / +`modelscope<3.21` 两道上游上界。 + +## 2. 本次实测证据(为什么明知有告警还是不升) + +``` +transformers 4.57.6 + tokenizers 0.22.2(满足当时声明的 >=4.57.0): + VoxCPM2 加载 200 → 合成 RIFF、243,164 B、RMS 5360 ← 正常 + IndexTTS 2.5 加载失败:ImportError: indextts 缺少 indextts.infer_v2_5 推理模块 + IndexTTS 2.0 加载失败:ImportError: indextts 缺少 indextts.infer_v2 推理模块 + +transformers 4.52.1 + tokenizers 0.21.0(引擎元数据要求的组合,最终留在树里的状态): + IndexTTS 2.5 加载 200 → 回取 RIFF 214,040 B、RMS 6176(约 2.2 s 音频) + IndexTTS 2.0 加载 200 → 回取 RIFF 205,124 B、RMS 6926 + VoxCPM2 加载 200 → 回取 RIFF 230,148 B、RMS 4615 + 三次卸载后显存回到 3.5 GB 基线(RTX 5070 Ti 12227 MiB,加载前空闲 8.2~8.4 GB) +``` + +即"升到 4.57 就能顺手关掉 4 条 ReDoS"这条路,代价是**产品两个引擎直接不可用**。所以 +`pyproject.toml` / `requirements.txt` 里的 `transformers>=4.57.0` 被改回 +`>=4.52.1,<4.53`,并把上面的实测数字写进注释:上界不是保守猜测,是被引擎真实约束钉住的。 + +> 复现这套对比时的坑(已记 GOTCHAS #137):本服务的端口被占时会**自动顺延到下一个端口**, +> 而沙箱里"停掉后台命令"只杀外层 shell、不杀 `python` 子进程。结果是新起的干净服务落在 7870, +> 脚本按 7869 打到的却是**上一代还在跑的旧进程**,把"已恢复环境"误报成"仍然失败"。 +> 判据:跑之前先 `netstat -ano | grep LISTENING | grep :786`,确认监听只有一个且 PID 是新的。 + +## 3. 顺带修掉的、比告警更要紧的一件事 + +`requirements-lock.txt` / `launcher/requirements-small.txt` 当时**自相矛盾**(与告警无关的独立缺陷): + +| 锁里的值 | 违反谁的要求 | 已改为 | +|---|---|---| +| `tokenizers==0.23.2` | `transformers 4.52.1` 要 `>=0.21,<0.22`;`indextts` 要 `==0.21.0` | `0.21.0` | +| `antlr4-python3-runtime==4.13.2` | `hydra-core 1.3.x` / `omegaconf 2.3.x` 要 `==4.9.*` | `4.9.3` | +| `mpmath==1.4.1` | `sympy 1.14.0` 要 `<1.4` | `1.3.0` | + +后果不是"CI 红",而是**任何人按 lock 装环境都装出一个 `pip check` 报错的破图**,而开发机能跑 +是因为它比 lock 早(本机实装 30/73 条与 lock 不一致)。之所以一直没人发现: +`scripts/check_pin_crossconflicts.py`(PR #98 引入)**只挂在 pre-commit 的 `files:` 条件上** +—— 只有改动 lock 才触发,已经坏在 main 上的锁集它永远不会去看。本次把它接进 +`.github/workflows/ci.yml` 的 lint job,每次 PR 与 push 都跑;改完检查器输出: +`校验 PyPI 版本 95 个,冲突 0,未核验 0 → PASS`。 + +## 4. 复点条件(满足其一就重新评估对应告警) + +1. IndexTTS 官方放开 `transformers` 精确 pin → 立刻可关 A1–A4(4.53+),届时再判 5.x 的 A5–A8。 +2. `descript-audiotools` / `modelscope` 放开 `protobuf<3.20 / <3.21` → 可关 P1–P2。 +3. 若本服务将来**监听非本机地址**或**接受用户指定模型名/HF 仓库**,A6/A8/P1/P2 的 + "无攻击面"前提立即失效,必须重判。当前证据:`config.yaml host: "127.0.0.1"`、 + `run_server(ip="127.0.0.1")`。 +4. 若 `vllm_backend.py`(现在无人引用,其 `trust_remote_code` 默认 True)被接进入口,A6 立即升为必修。 + +## 5. 需要仓库所有者点头的动作 + +GitHub 安全页的 20 条 dismiss 属**共享状态写操作**,我没有代做,也没有在这份文档里写死 +`dismissed_reason` 的取值 —— 那个枚举我该现查而不是照记忆写。执行前先取真值: + +```bash +# 看某条告警现在的状态与字段名(读操作,不改状态) +gh api repos/ReSerendipity/TTS_MultiModel/dependabot/alerts/22 \ + -q '{state, dismiss_reason, advisory: .security_advisory.cve_id}' +``` + +拿到合法枚举后,按 §1 表里"建议处置"一列逐条 PATCH(`state=dismissed` + 对应的 +`dismissed_reason` + 注释里引用本文对应行号),**先跑 1 条确认语义再批量**。 +每条注释必须自带绑定理由(哪条代码路径不存在 / 被哪个上游上界挡住 / 复点条件), +不接受"误报"三个字了事。 diff --git a/launcher/requirements-small.txt b/launcher/requirements-small.txt index 71d2c280..888a98d7 100644 --- a/launcher/requirements-small.txt +++ b/launcher/requirements-small.txt @@ -14,7 +14,7 @@ aliyun-python-sdk-core==2.16.1 aliyun-python-sdk-kms==2.16.5 annotated-doc==0.0.5 annotated-types==0.8.0 -antlr4-python3-runtime==4.13.2 +antlr4-python3-runtime==4.9.3 anyio==4.15.1 certifi==2026.7.22 cffi==2.1.1 @@ -50,7 +50,7 @@ markupsafe==3.0.3 mdurl==0.1.2 modelscope==1.40.1 modelscope-hub==0.4.3 -mpmath==1.4.1 +mpmath==1.3.0 msgpack==1.2.2 narwhals==2.26.0 networkx==3.6.1 @@ -90,7 +90,7 @@ starlette==1.6.0 sympy==1.14.0 threadpoolctl==3.7.0 tiktoken==0.14.0 -tokenizers==0.23.2 +tokenizers==0.21.0 torch-complex==0.4.4 tqdm==4.70.1 transformers==4.52.1 diff --git a/pyproject.toml b/pyproject.toml index 149554db..6775020a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,9 +55,13 @@ dependencies = [ "torch>=2.5.1", "torchvision>=0.20.1", "torchaudio>=2.5.1", - # 版本策略:VoxCPM2 / IndexTTS2 的 tokenizer 与 modeling 需要较新 transformers API。 - "transformers>=4.57.0", - "tokenizers>=0.19.0", + # 版本策略:上界是实测钉出来的,不是保守猜测。IndexTTS 2.0/2.5 的发行元数据要求 + # transformers==4.52.1 + tokenizers==0.21.0;2026-09-21 在 4.57.6 下实测 + # `indextts.infer_v2_5` / `infer_v2` 导入失败(两个引擎直接起不来,VoxCPM2 正常), + # 而 4.52.1 下三引擎真推理全通(IndexTTS 2.5 出 2.23s 音频 RMS 6176、 + # VoxCPM2 出 243KB 音频 RMS 5360)。抬这个上界之前必须先确认 IndexTTS 侧已适配。 + "transformers>=4.52.1,<4.53", + "tokenizers>=0.21.0,<0.22", # === AI 生态 === "funasr>=1.0.0", "modelscope>=1.9.0", diff --git a/requirements-lock.txt b/requirements-lock.txt index 7c1e09e2..9d9ae69c 100644 --- a/requirements-lock.txt +++ b/requirements-lock.txt @@ -9,7 +9,7 @@ aliyun-python-sdk-core==2.16.1 aliyun-python-sdk-kms==2.16.5 annotated-doc==0.0.5 annotated-types==0.8.0 -antlr4-python3-runtime==4.13.2 +antlr4-python3-runtime==4.9.3 anyio==4.15.1 certifi==2026.7.22 cffi==2.1.1 @@ -45,7 +45,7 @@ markupsafe==3.0.3 mdurl==0.1.2 modelscope==1.40.1 modelscope-hub==0.4.3 -mpmath==1.4.1 +mpmath==1.3.0 msgpack==1.2.2 narwhals==2.26.0 networkx==3.6.1 @@ -85,7 +85,7 @@ starlette==1.6.0 sympy==1.14.0 threadpoolctl==3.7.0 tiktoken==0.14.0 -tokenizers==0.23.2 +tokenizers==0.21.0 torch==2.14.0 torch-complex==0.4.4 torchaudio==2.11.0 diff --git a/requirements.txt b/requirements.txt index 3bcf5b95..05b9d274 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,8 +2,8 @@ torch>=2.5.1 torchvision>=0.20.1 torchaudio>=2.5.1 -transformers>=4.57.0 -tokenizers>=0.19.0 +transformers>=4.52.1,<4.53 +tokenizers>=0.21.0,<0.22 funasr>=1.0.0 modelscope>=1.9.0 addict>=2.4.0 From a4b64f3efc1041ca19489d41e64e941307003100 Mon Sep 17 00:00:00 2001 From: ReSerendipity Date: Mon, 21 Sep 2026 13:11:34 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix(deps):=20=E6=8A=8A"=E4=B8=8B=E7=95=8C?= =?UTF-8?q?=20vs=20=E5=BC=95=E6=93=8E=E5=8F=AF=E7=94=A8=E6=80=A7"=E7=9A=84?= =?UTF-8?q?=E4=BA=92=E6=96=A5=E4=BA=A4=E5=9B=9E=E5=86=B3=E7=AD=96=EF=BC=8C?= =?UTF-8?q?=E6=9C=AC=20PR=20=E5=8F=AA=E4=BF=9D=E7=95=99=E6=97=A0=E4=BA=89?= =?UTF-8?q?=E8=AE=AE=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测把下界改回 transformers>=4.52.1,<4.53 会让 CI 的两道安全门禁同时变红: pip-audit 扫到 4.52.4 的"4.53 已修"四组 CVE(PYSEC-2025-216、PYSEC-2026-198/228/229/392), docker-build 的 Trivy 扫描步骤同样 exit 1(镜像本身构建成功)。反过来留着 >=4.57.0 门禁是绿的, 但按这份声明装环境的人 IndexTTS 2.0/2.5 都起不来(4.57.6 实测 infer_v2 / infer_v2_5 ImportError;4.52.1 实测三引擎全部加载并出真音频,数字见 docs/SECURITY_DEPENDABOT_TRIAGE.md §2)。 这个取舍涉及安全门禁的松紧,不该由我在修锁集的 PR 里顺手定,所以: - 声明下界原样保留 >=4.57.0 / tokenizers>=0.19.0,并在 pyproject 里写明互斥关系与两条出路 (要么回退下界 + 给两道门禁加逐条带理由的豁免;要么先让 IndexTTS 适配 >=4.53); - 保留本次真正无争议的部分:两份 lock 的三行非法约束(tokenizers 0.23.2→0.21.0、 antlr4 4.13.2→4.9.3、mpmath 1.4.1→1.3.0)、check_pin_crossconflicts 接进 ci.yml、 引擎导入失败时不再断言"PyPI 无 indextts 包"而是带上底层 ImportError、 以及 20 条告警的逐条分诊文档。 复跑(冻结树):check_pin_crossconflicts exit 0(95 包冲突 0)、ruff 通过、 完整性 16/16、2078 passed / 35 skipped / 0 failed、覆盖率 52.12%。 Signed-off-by: ReSerendipity --- docs/DOD.md | 5 ++++- docs/SECURITY_DEPENDABOT_TRIAGE.md | 18 +++++++++++++++--- pyproject.toml | 18 +++++++++++------- requirements.txt | 4 ++-- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/docs/DOD.md b/docs/DOD.md index 2b2725a3..35699b20 100644 --- a/docs/DOD.md +++ b/docs/DOD.md @@ -126,7 +126,10 @@ **IndexTTS 2.5 / 2.0 双双 `infer_v2_5` / `infer_v2` 导入失败**;回到 4.52.1 + tokenizers 0.21.0 后三引擎真推理全通(2.5:214,040 B / RMS 6176;2.0:205,124 B / RMS 6926;VoxCPM2:230,148 B / RMS 4615;每次卸载显存回到 ~3.5 GB)。故 `pyproject`/`requirements.txt` 里那句 - `transformers>=4.57.0`(9-14 搭在一条 gpu-smoke 提交里进来的)改回 `>=4.52.1,<4.53` 并写明证据; + `transformers>=4.57.0`(9-14 搭在一条只讲 gpu-smoke 的提交里进来的)站不住,但改回 4.52.x 会让 + pip-audit 与 Trivy 两道 CI 安全门禁同时变红(扫到 4.52.4 的"4.53 已修"CVE)——**下界与引擎可用性 + 互斥**,本轮只落地无争议部分(锁集合法化 + 检查器接进 CI + 报错文案),下界原样保留并在 + `pyproject.toml` 里写清两条出路,岔口交所有者; 引擎加载失败时的报错也不再断言"PyPI 无 indextts 包",改为带上底层 ImportError 与版本不匹配提示。 20 条 Dependabot 告警因此**没有一条能靠现在就升级消掉**,分诊见 `docs/SECURITY_DEPENDABOT_TRIAGE.md`。 * **已知缺口**:CI 冒烟 `scripts/gpu_smoke_minimal.py` 只覆盖 voxcpm2 + indextts2(走 OpenAI 口, diff --git a/docs/SECURITY_DEPENDABOT_TRIAGE.md b/docs/SECURITY_DEPENDABOT_TRIAGE.md index a4cdc744..02c6fe0f 100644 --- a/docs/SECURITY_DEPENDABOT_TRIAGE.md +++ b/docs/SECURITY_DEPENDABOT_TRIAGE.md @@ -38,9 +38,21 @@ transformers 4.52.1 + tokenizers 0.21.0(引擎元数据要求的组合,最 三次卸载后显存回到 3.5 GB 基线(RTX 5070 Ti 12227 MiB,加载前空闲 8.2~8.4 GB) ``` -即"升到 4.57 就能顺手关掉 4 条 ReDoS"这条路,代价是**产品两个引擎直接不可用**。所以 -`pyproject.toml` / `requirements.txt` 里的 `transformers>=4.57.0` 被改回 -`>=4.52.1,<4.53`,并把上面的实测数字写进注释:上界不是保守猜测,是被引擎真实约束钉住的。 +即"升到 4.57 就能顺手关掉 4 条 ReDoS"这条路,代价是**产品两个引擎直接不可用**。 + +**这里有一个必须所有者拍的岔口**(PR #101 实测撞上的):把声明下界改回 4.52.x 会让 +`transformers 4.52.4` 进入解析结果,于是 CI 的两道安全门禁同时变红 —— +`Dependency Vulnerability Scan (pip-audit)`(PYSEC-2025-216、PYSEC-2026-198/228/229/392)与 +`docker-build.yml` 的 Trivy 扫描步骤(镜像构建本身成功)。反过来,留着 `>=4.57.0` 门禁是绿的, +但任何人按 `pyproject`/`requirements.txt` 装环境,IndexTTS 两个引擎都起不来。 +也就是说**当前 main 的"安全门禁绿"是踩在引擎跑不起来的版本声明上的**。 + +两条出路,本 PR 只做了无争议的那半(锁集合法性 + 检查器接线),下界原样留着并加注释指向本文: + +1. 下界改回 `>=4.52.1,<4.53`(运行时正确),同时给 pip-audit / Trivy 加**逐条带理由**的豁免 + (理由引用 §1 表的可达性判定与 §4 的复点条件); +2. 或者先让 IndexTTS 侧适配 transformers ≥4.53(上游放开精确 pin,或我们改 vendored 拷贝), + 再自然抬下界、告警一并消掉。 > 复现这套对比时的坑(已记 GOTCHAS #137):本服务的端口被占时会**自动顺延到下一个端口**, > 而沙箱里"停掉后台命令"只杀外层 shell、不杀 `python` 子进程。结果是新起的干净服务落在 7870, diff --git a/pyproject.toml b/pyproject.toml index 6775020a..232daedc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,13 +55,17 @@ dependencies = [ "torch>=2.5.1", "torchvision>=0.20.1", "torchaudio>=2.5.1", - # 版本策略:上界是实测钉出来的,不是保守猜测。IndexTTS 2.0/2.5 的发行元数据要求 - # transformers==4.52.1 + tokenizers==0.21.0;2026-09-21 在 4.57.6 下实测 - # `indextts.infer_v2_5` / `infer_v2` 导入失败(两个引擎直接起不来,VoxCPM2 正常), - # 而 4.52.1 下三引擎真推理全通(IndexTTS 2.5 出 2.23s 音频 RMS 6176、 - # VoxCPM2 出 243KB 音频 RMS 5360)。抬这个上界之前必须先确认 IndexTTS 侧已适配。 - "transformers>=4.52.1,<4.53", - "tokenizers>=0.21.0,<0.22", + # ⚠ 这条下界与引擎可用性互斥,取舍交仓库所有者,别顺手改(证据见 + # docs/SECURITY_DEPENDABOT_TRIAGE.md §2):2026-09-21 实测 4.57.6 下 VoxCPM2 正常 + # (合成 243,164 B / RMS 5360)但 IndexTTS 2.5 与 2.0 的 infer_v2_5 / infer_v2 直接 + # ImportError;4.52.1 + tokenizers 0.21.0 下三引擎真推理全通(2.5:214,040 B / RMS 6176; + # 2.0:205,124 B / RMS 6926)。但把下界改回 4.52.x 会让 pip-audit 与 Trivy 两道 CI + # 安全门禁同时变红(扫到 4.52.4 的"4.53 已修"CVE),所以这里暂留 >=4.57: + # 门禁绿,代价是按本声明装环境的人两个引擎起不来。出路二选一—— + # 1) 下界改回 >=4.52.1,<4.53,并给两道门禁加逐条带理由的豁免; + # 2) 先让 IndexTTS 侧适配 transformers >=4.53(上游放开精确 pin 或改 vendored 拷贝)。 + "transformers>=4.57.0", + "tokenizers>=0.19.0", # === AI 生态 === "funasr>=1.0.0", "modelscope>=1.9.0", diff --git a/requirements.txt b/requirements.txt index 05b9d274..3bcf5b95 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,8 +2,8 @@ torch>=2.5.1 torchvision>=0.20.1 torchaudio>=2.5.1 -transformers>=4.52.1,<4.53 -tokenizers>=0.21.0,<0.22 +transformers>=4.57.0 +tokenizers>=0.19.0 funasr>=1.0.0 modelscope>=1.9.0 addict>=2.4.0