插件系统:增加安全的 ZIP 导入与原子安装 - #48
Merged
Playa-0v0 merged 4 commits intoSep 1, 2026
Merged
Conversation
# Conflicts: # src/main/index.ts
# Conflicts: # src/main/channels/bootstrap.ts # src/main/channels/init.ts # src/main/index.ts # src/main/music/shutdown-latch.test.ts # src/main/music/shutdown-latch.ts
Closed
Owner
|
怎么还超额完成了,我先把42关了再review一下 |
Playa-0v0
added a commit
that referenced
this pull request
Sep 1, 2026
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.
PR 关系与审查范围
本 PR 实现上游在插件系统审查中提出的社群分发流程:
本 PR 依赖 #42(插件运行时、生命周期、资源所有权与卸载)。当前以 #42 的头提交为父提交,新增功能集中在提交
5684b908。在 #42 合并前,GitHub 的整体 diff 会同时显示基础插件系统;建议本轮优先审查该新增提交。#42 合并后会将本分支 rebase 到最新master,届时该 PR 只保留 ZIP 导入增量,再转为 Ready for review。用户体验
设置页“功能插件”区域新增“导入 ZIP”按钮:
.zip;%APPDATA%\live2d-cyrene\plugins\<plugin-id>\;plugin-data/<plugin-id>/私有数据。ZIP 支持两种常见结构:
正式安装目录始终由经过校验的
manifest.id决定,不信任压缩包文件名或顶层文件夹名。安装事务
第一阶段:选择文件
plugins:import-zipIPC;window.plugins.importZip();第二阶段:隔离解压和预检
ZIP 不会直接解压到
userData/plugins。每次导入在以下目录创建随机 staging:检查或解压失败时递归清理该次 staging,不触碰正式插件目录。
第三阶段:插件结构校验
解压完成后复用插件 loader 的正式校验逻辑:
apiVersion必须为当前 v1;.cjs、.js或.mjs文件;这避免“扫描时一套规则、安装时另一套规则”造成差异。
第四阶段:冲突确认与原子提交
第五阶段:状态和重扫
defaultEnabled为 true,首次导入仍保持停用;userData/plugin-data/<plugin-id>/不参与程序目录替换。ZIP 安全边界
路径与文件类型
导入会拒绝:
.、..、NUL 和 NTFS ADS 冒号路径;CON、NUL、COM1、LPT1;extract-zip自身的目标目录边界检查仍然保留,本 PR 的检查属于额外的 fail-closed 层。资源上限
这些限制用于降低 ZIP bomb、资源耗尽和平台路径歧义风险。它们不代表插件代码进入安全沙箱;插件仍是 Electron Main Process 中的可信本地代码。
主要文件
src/plugins/installer.ts:ZIP 预检、staging、结构校验、备份与原子提交;src/plugins/installer.test.ts:自包含 ZIP fixture 与安全回归;src/plugins/manager.ts:安装生命周期、冲突确认、状态处理和重扫;src/plugins/loader.ts:导出统一 manifest 检查入口供扫描和安装复用;src/main/plugin-runtime.ts:原生选择文件和替换确认对话框;src/shared/ipc-channels.ts、src/preload/index.ts:最小导入桥接;src/renderer/settings/feature-plugins/**:导入按钮、忙碌状态和错误展示;docs/plugins/plugin-authoring.md:ZIP 结构、事务、安全上限和验证说明。自动化测试
ZIP 与插件专项测试
以下 4 个测试文件共
44/44通过:src/plugins/installer.test.tssrc/plugins/loader.test.tssrc/plugins/manager.test.tssrc/renderer/settings/feature-plugins/panel.test.ts新增覆盖包括:
完整构建
npm run build通过:Renderer 只有既有的大 chunk 提示,没有构建错误。
全量测试
2909/2911通过;harness-adapter-cancel.test.ts写入固定C:\cyrene-test-user-data时返回EPERM;2/2通过;2911/2911均已取得通过结果。明确不包含
上述内容涉及新的信任协议和兼容承诺,建议在 ZIP 本地导入链路稳定后分别设计,避免扩大本 PR 的审查面。
建议审查顺序
src/plugins/installer.ts:路径、资源限制、staging 和原子替换;src/plugins/manager.ts:串行生命周期、首次停用和失败恢复;src/main/plugin-runtime.ts:Main Process 文件选择和替换确认;installer.test.ts与文档:安全回归和对外约定。