# DSH 插件安全开发指南(作者底线) > **用途**:自己开发 DSH 插件时遵循的安全规则与底线。它同时是一份提示词:把本文交给 AI 并附上你的插件代码,让它按第十节清单逐条 review。 > > **立场**:用户给了你的插件和他自己一样的权限。插件能读他的文件、用他的凭据、碰他的网络。以下底线不是风格偏好,是这个信任关系下的义务。 ## 一、十条底线 ### 1. 最小权限:永远不申请你用不到的能力 - 不把执行命令放进 `danger-full-access` 能避免就避免;确实需要(如系统命令类插件)必须在 README 顶部显著说明并给出替代方案。 - 你 `inject` 的每个服务、注册的每个路由、读的每个目录,都应是功能必需。多一项就多一个被滥用面。 - **反例**:一个主题皮肤插件 inject 了 `shell`。 ### 2. 分发物里禁止 `!!js` - `cordis.patch.yml` / `cordis.yml` 里不写 `!!js` 指令——它在用户机器加载时被求值,等同于让用户执行任意代码。 - 需要可配置:提供声明式字段 + README 文档,或让用户自己在他的 patch 层覆盖。作者本机自用 `!!js` 无妨,**分发即越界**。 ### 3. 不碰用户的安全层 - 你的 patch 不得 `replace`/覆盖任何审批(approval)、权限预设(permission*)、沙箱(sandbox)相关行,不得调松任何默认策略。 - 需要更高权限的功能,引导用户显式选择(如"请在设置中切换预设"),而不是替他改。 ### 4. 网络出口最小化 - 默认不出网。必须出网时:域名固定且写进 README("本插件会访问 X,发送 Y");绝不发送凭据、环境变量、会话内容、用户文件;不做静默遥测,要上报必须默认关闭、开关可见。 - 出错上报不带数据负载,只带错误类型与堆栈,且默认关闭。 ### 5. 凭据纪律 - 不直接读 `~/.dsh/.credentials.yaml`、`.env`、`process.env` 里的 `*KEY*`/`*TOKEN*`/`*SECRET*`。需要模型服务就复用官方 llm provider/credentials 服务的按引用机制。 - 日志与错误消息脱敏:任何 `sk-` 样式串、`Bearer` 头不得出现在 console、会话记录、报告里。 - 只该出现凭据**文件名/权限位**的地方,绝不出现内容。 ### 6. 路由与输入安全(webServer 类插件) - 校验 HTTP 方法;不接受把请求参数拼进 shell 命令或文件路径(要传路径就白名单前缀 + 规范化后再校验)。 - 路由返回的数据自问一句"这段内容被同机任意页面拿到会怎样":不含凭据、会话正文、任意文件读取。 - 有破坏性/外发效果的路由(删除、重启、发送)加确认步骤或一次性令牌,并在 UI 明示。 ### 7. 副作用可清理、可逆 - 一切注册走 `ctx.effect()`/`apply` 返回 dispose;卸载后不留全局变量、样式、定时器、监听器、文件。 - 文件只写你声明并文档化的目录;不写 `~/.dsh` 全局配置、不写 shell 启动文件、不建计划任务/服务。 - 装得上也要卸得掉:`dsh plugin remove` 后用户环境恢复原状。 ### 8. 不带安装期脚本 - 不 ship `preinstall`/`postinstall`/`prepare`。pnpm ≥10 默认拦截构建脚本,用户被迫 `allowBuilds` 是在消耗整个生态的信任。 - 首选**无构建分发**:手写/生成好的 ESM 产物直接入库(`node --check` 可验证),或提供可复现构建(CI 从源码出产物、发布物与源码可对照)。 ### 9. 依赖卫生 - 依赖越少越好;git 依赖锁定 commit;不用无人维护的包;对每个依赖自问第 1 步的名字是否 typosquat。 - 升级依赖前看一眼 diff——供应链攻击常藏在"例行升级"里。 ### 10. 透明与文档一致 - README 声明数据流三问:**读什么、写什么、发什么**。声明之外的任何行为都算缺陷(包括 bug 导致的)。 - 声明权限与限制("本插件需要 X,因为 Y;不会做 Z")。用户按文档推理安全,文档失真即失信。 ## 二、发布前自查清单(交给 AI 执行也按这份) - [ ] `grep -r "!!js" .`(分发物内)无命中 - [ ] `package.json` 的 `scripts` 无 install/prepare 族 - [ ] patch 无 replace 安全行(approval/permission/sandbox) - [ ] 全部 `fetch`/`http` 出口域名已写进 README,且不携带凭据/会话/文件内容 - [ ] 无 `process.env.*KEY*`/`.credentials.yaml`/`.env` 直接读取;日志脱敏 - [ ] `webServer` 路由:方法校验、无参数拼接命令/路径、响应无敏感内容 - [ ] 无 `eval`/`new Function`/`vm.Script` - [ ] 所有注册可逆(effect/dispose 成对);文件写入仅在声明目录 - [ ] git 依赖锁定 commit;依赖名单最小化 - [ ] README 数据流三问齐全;安装/卸载/权限说明齐全 ## 三、与 Plugin Security Standard 的关系 本指南是 DSH 插件安全标准(16 权限位 / L0–L4 分级 / 100 分制准入评分)在单个作者能立即执行层面的**简化落地版**:十条底线 ≈ 标准中"一票否决"与"高危权限"两档。需要给插件标注权限等级、做准入评审时,按完整标准执行(权限声明 → 分级 → 评分 → 安装流程挂钩)。 ## 四、本插件(dsh-security-doctor)自身达标对照 > 完整的自审过程、发现与修复记录见 [SELF-AUDIT.md](SELF-AUDIT.md):本插件用本文档配套的《安全检测指南》T1–T10 十类威胁逐条审过自己,自审另发现 3 处可加固点(跨站读取路由、URL 凭据回显、CI tag 未钉 SHA)并已修复。 | 底线 | 本插件的做法 | | --- | --- | | 1 最小权限 | 仅 `inject: ['webServer']`(宿主)+ `['slots']`(客户端);无 shell;唯一子进程是 Windows `icacls` 只读 ACL 查询(execFile 固定参数,无用户输入) | | 2 无 `!!js` | 分发物零 `!!js`;自身也不执行被检对象的 `!!js`,只报告其存在 | | 3 不碰安全层 | patch 只有一行 insert 自身,不 replace 任何行 | | 4 网络出口 | 零外部域名;客户端仅 fetch 本机回环路由 | | 5 凭据纪律 | 凭据文件只查权限位(stat/icacls),内容零读取零回显;回显的配置行经 `maskSecrets()` 自动脱敏(URL userinfo/query 密钥/`sk-`/`gh?_` 令牌),测试断言凭据值零泄漏 | | 6 路由与输入安全 | 两个无参数 GET 只读路由;方法校验;**要求配对头 `x-dsh-security-doctor: 1` + 拒绝 `Sec-Fetch-Site: cross-site`,防本机其他网页跨站读取**;响应 `no-store` 且无凭据内容 | | 7 可清理 | 样式/插槽/路由全部 effect/dispose 成对;零文件写入;浏览器仅 localStorage 存体检摘要与哈希 | | 8 无安装脚本 | 无 scripts;无构建(手写线格式,`node --check` 验证) | | 9 依赖卫生 | 零运行时依赖;CI actions 钉 commit SHA;安装命令钉版本标签 | | 10 透明 | README 数据流三问 + SELF-AUDIT 数据明细表;声明之外的任何行为(含 bug 导致)都算缺陷 |