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.envprocess.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.jsonscripts 无 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 导致)都算缺陷