DSH 插件安全开发指南(作者底线)
August 16, 2026 · View on GitHub
用途:自己开发 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:本插件用本文档配套的《安全检测指南》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 导致)都算缺陷 |