Skip to content

CH 28 · 安全与合规

全文字数3492 字预估耗时约 20 分钟前置CH 04难度理解为主

本章目标

让一个能跑命令、能写文件的 Agent 在你电脑上干活,你会不会担心:它会不会乱删我文件?会不会偷偷把我密钥发出去?会不会改我系统设置?

这些担心是对的——一个没有安全边界的 Agent 就是定时炸弹。dsh 的回答是三层防护:文件沙箱、操作审批、密钥只写。前面 CH 04 讲权限模型时提过一些,这一章把每一层的原理讲透——它到底怎么管住 Agent、哪些是硬边界绕不过去、哪些需要你自己把关。理解了这些,你就知道什么能放心交给它、什么必须自己盯着。

先搞清楚:dsh 的安全思路

dsh 的安全设计核心是八个字:默认受限,按需放行

不是先给全部权限再靠你小心,而是反过来——默认它只能碰你明确允许的范围,想越界必须经过你同意。这和"给管理员密码让它自己看着办"是完全不同的思路。

三层防护从外到内:

层级管什么怎么管
第一层:文件沙箱能碰哪些文件三档权限,OS 内核级隔离
第二层:操作审批敏感操作能不能执行弹窗问你,你说不就不跑
第三层:密钥只写API Key 怎么存只写不落界面,本地存储不上传

下面逐层讲。

第一层:文件沙箱

CH 04 讲过三档权限,这里讲清楚它背后的原理。

沙箱不是一段 JavaScript 在做 if 判断——"如果路径不在工作区就报错"。那种做法模型可以绕过去(比如用相对路径跳转、用符号链接)。dsh 的沙箱是操作系统内核级的:在 Windows 上用作业对象限制进程能访问的资源,在 Linux/macOS 上用 namespace 和 seccomp 过滤系统调用。模型不管用什么花招,内核那关过不了就是过不了。

三档权限由严到松:

模式能写什么适合什么场景
read-only什么都不能写只读分析、代码审查、纯问答——让它看但不让它改
workspace-write(默认)只能写当前工作区目录 + 系统临时目录日常干活——能改项目文件,动不了系统和别的项目
danger-full-access不限制明确需要全盘操作时才开,比如系统维护、装软件——风险自担

一个容易忽略的点:沙箱只管文件系统副作用,不管网络和进程隔离。也就是说,workspace-write 模式下,Agent 不能写工作区外的文件,但它可以发网络请求、可以读工作区外的文件(只读)。所以别以为开了 workspace-write 就绝对安全——它能把你工作区里的敏感文件内容通过 API 请求发出去(虽然正常模型不会这么干,但这是理论上的边界)。

切换方式 CH 04 讲过:当前会话临时换用 /permission,改默认值走设置 → 通用 → 权限(只对之后新建的会话生效)。

第二层:操作审批

沙箱管住了"能碰哪些文件",审批管住了"敏感操作能不能执行"。

当 Agent 想做一件超出当前权限范围的事——比如在 workspace-write 模式下想写工作区外的文件、想执行一个可能改系统的命令——它不会直接跑,而是先发起一个审批请求,界面上弹出一个对话框,告诉你:

  • 它想执行什么操作(具体命令或文件路径)
  • 为什么要这么做(模型给出的理由)

然后给你三个选择:允许一次拒绝取消

图片占位:这里放一张「Agent 请求写工作区外文件,弹出审批对话框」的截图——能看到操作内容、模型理由、允许/拒绝按钮。

几个关键细节:

  1. 允许一次就是一次——不是"以后都允许"。下一次再遇到同样的操作,还会再问你。
  2. 拒绝就是拒绝——模型收到拒绝后,会换一条路走或者告诉你做不了,不会偷偷绕过。
  3. 审批是插件级的可扩展点——CH 11 讲过工具调用流水线,审批就是其中一个环节。你可以自己写插件定制审批策略,比如"某些命令自动允许,某些自动拒绝"。

审批和沙箱是配合的:沙箱是硬边界(内核级,绕不过),审批是软边界(策略级,可以放行)。日常用 workspace-write + 审批弹窗,就是"默认安全,需要时你手动放行"的平衡。

第三层:密钥只写

API Key 是最敏感的东西——丢了别人就能用你的额度、甚至用你的身份调 API。dsh 对密钥的处理是只写(write-only)

什么叫只写?你在 设置 → 模型 里填了 API Key 点保存后,界面上那串 Key 就"消失"了,只剩下一个脱敏描述符(比如 deepseek://sk-...x8f2)。你再也无法从界面上读回完整的明文 Key。

这不是 bug,是刻意设计:

  • 明文 Key 只落在本地 $DSH_HOME/.credentials.yaml(Windows 上是 C:\Users\<你的用户名>\.dsh\.credentials.yaml
  • 界面和 settings.yaml 里只存引用(apiKeyEnv 之类的字段名),不存明文
  • 浏览器内存、网络日志、前端状态里都不会二次暴露完整 Key

图片占位:这里放一张「设置 → 模型页面,DeepSeek 卡片保存后只显示脱敏描述符」的截图——能看到密钥字段已变成 deepseek://sk-...xxxx 格式。

密钥的优先级(从高到低):

  1. 进程环境变量(export DEEPSEEK_API_KEY=sk-xxx
  2. $DSH_HOME/.credentials.yaml 文件
  3. 项目目录下的 .env 文件

环境变量优先级最高,适合临时用;文件方式最常用,适合长期配置。

安全提醒.credentials.yaml 文件权限是 0600(只有你能读写),但如果你把整个 ~/.dsh 目录备份到云端或共享给别人,密钥就跟着走了。备份时注意脱敏。

数据隐私

除了密钥,dsh 产生的所有数据也都在本地:

数据存在哪会上传吗
会话记录~/.dsh/sessions/不会
轨迹(Trajectory)会话记录内嵌不会
插件配置~/.dsh/profiles/不会
API Key~/.dsh/.credentials.yaml不会
工作区文件你选的工作区目录不会

dsh 没有云端同步、没有账号体系、没有遥测上报。你和模型的对话内容只在你发请求时传给模型提供商(DeepSeek 等),dsh 本身不存一份在云端。

这意味着:

  • 好处:数据完全在你手里,隐私可控
  • 代价:换电脑就得手动迁移 ~/.dsh 目录,没有一键同步

安全最佳实践

把上面的机制落到日常使用,记住这几条:

  1. 日常用 workspace-write,别常开 full access——full access 下沙箱等于没有,Agent 能碰你整个硬盘。只有明确需要系统级操作时才临时开,用完切回去。
  2. 别把 ~/.dsh 目录直接传 GitHub——里面有 .credentials.yaml 明文密钥。如果要备份配置,单独导出 settings.yaml(不含密钥),密钥另行管理。
  3. Docker 团队部署注意无多用户隔离——CH 27 讲过,当前版本所有人用同一个 Basic Auth 登录后看到的是同一份会话和配置。团队共用时别在里面存敏感信息,或者每人部署一个独立实例。
  4. 工作区选干净的目录——别把整个 C:\Users 或 home 目录设为工作区。选一个专门的项目目录,Agent 能碰的范围就限定在那里。

这一章你学到了什么

能自己完成下面几条,就算过关:

  • [ ] 知道 dsh 安全设计的核心思路:默认受限,按需放行
  • [ ] 知道三层防护分别是什么:文件沙箱、操作审批、密钥只写
  • [ ] 知道沙箱是 OS 内核级的,不是 JS if 判断,模型绕不过去
  • [ ] 能说清三档权限(read-only / workspace-write / danger-full-access)的区别和适用场景
  • [ ] 知道审批是"允许一次",不是永久放行
  • [ ] 知道 API Key 是只写的,保存后界面不回显,明文只在本地 .credentials.yaml
  • [ ] 知道 dsh 所有数据都在本地,没有云端同步
  • [ ] 能说出至少 3 条日常安全最佳实践

Open Source · MIT · Community Driven