Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Arbitrary code execution via eval() of a third-party model pack's train.log field in the WebUI

未关闭 适合新手
#2,866 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
78/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
python
领域
security

调研方向

阅读 change_info_ 中的 webui.py:1719-1726,以及 webui.py:2820-2822 中 ckpt_path2.change 的连接方式。运行 issue 的恶意 train.log 和负面控制复现,然后验证解析会拒绝可执行表达式,同时有效的 model-info 数据仍会更新选择器,且不会创建 canary 文件。

由索引模型根据 Issue 内容生成。

描述

1. Summary

RVC WebUI wires the change event of the model-path textbox to change_info_ (webui.py:2821). change_info_ reads the sidecar file train.log shipped next to the selected model, takes the last tab-separated field of the first line, and passes it straight to eval() (webui.py:1719-1726). Model packs usually come from third-party sharing (cloud drives, model sites), so this train.log is attacker-controlled untrusted input: with a completely benign .pth, a single line of log text is enough to execute arbitrary Python code with WebUI process privileges on the victim's machine.

2. Affected version / environment

Repository: RVC-Project/Retrieval-based-Voice-Conversion-WebUI; verification anchor: commit 81eed5e (webui.py:1715-1731 change_info_; webui.py:2821 .change wiring); latest release: tag 2.3.260718 and the current main branch (checked 2026-09-30) still contain the same code; history: tag 2.2.231006 (2023-10) already had the same eval in infer-web.py:754-761, so the flaw is at least ~2 years old; PoC environment: Docker official python:3.11-slim image (Python 3.11.16) with the project's own CPU dependency list requirments_cpu_py312.txt (gradio 3.14.0; torch 2.4.1+cpu); the WebUI listens on 0.0.0.0:7897 by default.

3. Steps to reproduce

  1. Build a model pack evil_model/ containing two files: G_23333.pth is a normal, benign small checkpoint (generated with torch.save, byte-identical to the negative control); the first line of train.log follows the project's own log format "%(asctime)s\t%(name)s\t%(levelname)s\t%(message)s" with the last field (the message slot) replaced by the Python expression (import('pathlib').Path('/out/pwned_by_rvc_train_log_eval').write_text('MBE2E-CANARY-rvc-train-log-eval-v1\n', encoding='utf-8'), {'sample_rate': '48k', 'if_f0': 1, 'version': 'v2'})[1], which first writes a canary file and then returns the model-info dict, so the UI update completes normally without any error.
  2. Start the WebUI: python webui.py --pycmd python3 --port 7897
  3. Fire the same event a real user triggers: put the path evil_model/G_23333.pth into the "Path to Model" textbox of the checkpoint-extraction section (the .change event invokes change_info_); in the PoC the project's own Gradio queue API is used (/queue/join WebSocket, same protocol as the product frontend), submitting that path with fn_index pointing at the .change listener.
  4. Observe the server filesystem: /out/pwned_by_rvc_train_log_eval now exists with content "MBE2E-CANARY-rvc-train-log-eval-v1", while the UI shows no anomaly at all.
  5. Negative control: same directory layout and byte-identical .pth, but with the last train.log field replaced by the plain dict literal {'sample_rate': '48k', 'if_f0': 1, 'version': 'v2'}; repeat step 3 — it returns 48k/1/v2 and produces no file.

4. Expected behavior / Actual behavior

Expected: train.log is untrusted data carried inside a third-party model pack; parsing its field to prefill the sample-rate/if_f0/version selectors must never execute any code from it.
Actual: the field content is evaluated by eval(); the attacker's expression runs with WebUI process privileges, and because the payload returns a legitimate info dict the UI updates silently — no error, no warning.

5. Impact

  • Full arbitrary code execution with WebUI process privileges: file read/exfiltration, persistence, weight replacement, all possible.
  • The payload hides in "log text" while the .pth stays clean, so weight-based scanning and user intuition (people only look at the weights) both miss it; the expression returns a normal dict, so nothing is surfaced to the UI.
  • The trigger (selecting/pasting a model path in the WebUI) is the unavoidable step of loading community models; no training, no GPU, no extra interaction required.

6. Suggested fix

Replace the eval() at webui.py:1719 with a constrained parser: prefer ast.literal_eval(info_str), which accepts literals only and rejects any call or name lookup; treat parse failures as "no train.log info" (fall back to the UI defaults) instead of swallowing them into a traceback; the cleaner long-term option is a JSON convention (json.dumps on the writer side), fully dropping Python literal evaluation. Also consider warning the user when a model path with a sidecar train.log is loaded for the first time.

7. Additional context

  • Vulnerable code (webui.py:1719-1726, commit 81eed5e):
info = eval(
    read_text(
        ckpt_path.replace(os.path.basename(ckpt_path), "train.log")
    )
    .strip("\n")
    .split("\n")[0]
    .split("\t")[-1]
)
sr, f0 = info["sample_rate"], info["if_f0"]
  • Event wiring (webui.py:2820-2822):
ckpt_path2.change(
    change_info_, [ckpt_path2], [sr__, if_f0__, version_1]
)

rvc-train-log-eval-poc.zip

link:

https://github.com/3em0/cve_repo/blob/main/2026/Retrieval-based-Voice-Conversion-WebUI_Arbitrary_Code_Execution_via_eval()_of_Sidecar_train.log_in_WebUI_change_info_.md

主要语言
Python
星标
38.9k
派生
5.3k
PR 合并指标
30 天内没有已合并 PR

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

RVC-Project/Retrieval-based-Voice-Conversion-WebUI 的其他 Issue

查看 RVC-Project/Retrieval-based-Voice-Conversion-WebUI 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。