Repository navigation
Conversation
POST /api/plugins/install 的自定义 url 可让服务端从任意地址下载 .py,
配合 POST /api/system/reload-plugins 的 exec_module 在进程内以 root 执行代码。
四处缺口叠加成链:
1. 控制器把请求体 url 直接透传给下载器,下载源完全由客户端决定
2. 完整性校验条件是 `if url is None and entry is not None`,自定义 URL 时恒假
3. target = plugin_dir / f"{name}.py",name 无白名单,可穿越写入
4. exec_module 无条件加载插件目录任意 .py,无审计、无签名、无沙箱
修复遵循保留能力、收敛边界:自定义来源安装是既有特性,不做删除。
- 接口层:HTTP 拒绝 url,安装源只能是 registry 登记的官方源;自定义来源
收敛到 CLI(install-provider --from),需在服务器上显式执行
- 下载层:仅允许 http/https;自定义来源拦截回环、私网、链路本地、保留地址
与云元数据主机(先解析 DNS 再逐地址判定)
- 名称层:白名单 ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,63}$ 且拒绝 ..,落点父目录复核
- 内容层:基于 ast 的源码审计,拒绝 subprocess/ctypes/socket 等导入与
eval/exec/compile/__import__/system 等调用;要求继承 TempMailProviderBase
- 完整性:官方源声明 sha256 必须匹配,未声明时改用源码审计,
消除「源里没写 sha256 即完全不校验」的口子
- 加载层:插件目录内符号链接不再加载
测试:插件相关 101 项通过,新增 17 项加固用例覆盖各道防线。
Refs: docs/BUG/2026-10-25-临时邮箱Provider插件安装RCE安全缺陷BUG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull request type / PR 类型
What is the current behavior? / 当前行为是什么?
POST /api/plugins/install把请求体中的url直接透传给服务端下载器,配合POST /api/system/reload-plugins的exec_module构成远程代码执行链。仅需后台登录态(
@login_required,无管理员角色校验),即可让服务端从任意地址下载 Python 文件并在容器内以 root 执行任意命令。
四处缺口叠加:
controllers/plugins.py:install_plugin(name, url=url),下载源完全由客户端决定temp_mail_plugin_manager.py:完整性校验条件是if url is None and entry is not None,自定义 URL 时
entry恒为None,sha256 分支整段失效target = plugin_dir / f"{plugin_name}.py",name无白名单,可路径穿越写入temp_mail_provider_factory.py:spec.loader.exec_module(mod)无条件加载插件目录内任意
.py,模块顶层代码在执行期即生效,无静态审计、无签名、无沙箱另:
requests.get(url)未限制协议与目标地址,可访问回环、内网与云元数据端点。Issue Number / Issue 编号: N/A(安全问题,未开公开 issue)
What is the new behavior? / 新行为是什么?
修复原则是保留能力、收敛边界——自定义来源安装是既有特性(CLI
--from、文档中的自定义安装),不删除,改为分层设防:
url,返回PLUGIN_CUSTOM_URL_DISABLED;安装源只能是registry 登记条目。自定义来源安装收敛到命令行
install-provider --from,需在服务器上显式执行_check_download_url()仅允许 http/https;自定义来源额外拒绝回环、私网、链路本地、保留地址与云元数据主机(先解析 DNS 再逐地址判定)
_validate_plugin_name()白名单^[A-Za-z0-9_][A-Za-z0-9_.-]{0,63}$且拒绝..;_resolve_plugin_target()复核落点父目录必须等于插件目录_audit_plugin_source()用ast解析后拒绝subprocess/ctypes/pty/multiprocessing/socket/pickle/marshal导入与eval/exec/compile/__import__/system/popen等调用;要求继承TempMailProviderBase或使用@register_providersha256必须匹配;未声明时改用源码审计,消除「源里没写 sha256即完全不校验」的口子
load_plugins()对插件目录内符号链接标记 failed,不加载验证 / Verification
在真实实例(Debian 12 / Python 3.11 /
uid=0)上修复前确认可执行,修复后同一实例:纵深防线:
测试:
886 passed, 3 skipped;tests/test_pool_cf_real_e2e.py4 项失败为既有问题(依赖外部 CF Worker,改动前后表现一致,与本次无关)
Breaking change / 破坏性变更
POST /api/plugins/install不再接受url字段。若部署侧依赖接口做自定义安装,需改用:后续建议 / Follow-ups(未包含在本 PR)
/api/plugins/*与/api/system/reload-plugins增加管理员角色校验,降低单账号泄露影响面相关文档
docs/BUG/2026-10-25-临时邮箱Provider插件安装RCE安全缺陷BUG.md(完整根因、攻击链、验证记录)CHANGELOG.md(未发布段)临时邮箱Provider插件接入说明.md(安装链新约束与源码审计规则)