CH 28 · 安全与合规
本章目标
让一个能跑命令、能写文件的 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 请求写工作区外文件,弹出审批对话框」的截图——能看到操作内容、模型理由、允许/拒绝按钮。
几个关键细节:
- 允许一次就是一次——不是"以后都允许"。下一次再遇到同样的操作,还会再问你。
- 拒绝就是拒绝——模型收到拒绝后,会换一条路走或者告诉你做不了,不会偷偷绕过。
- 审批是插件级的可扩展点——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 格式。
密钥的优先级(从高到低):
- 进程环境变量(
export DEEPSEEK_API_KEY=sk-xxx) $DSH_HOME/.credentials.yaml文件- 项目目录下的
.env文件
环境变量优先级最高,适合临时用;文件方式最常用,适合长期配置。
安全提醒:.credentials.yaml 文件权限是 0600(只有你能读写),但如果你把整个 ~/.dsh 目录备份到云端或共享给别人,密钥就跟着走了。备份时注意脱敏。
数据隐私
除了密钥,dsh 产生的所有数据也都在本地:
| 数据 | 存在哪 | 会上传吗 |
|---|---|---|
| 会话记录 | ~/.dsh/sessions/ | 不会 |
| 轨迹(Trajectory) | 会话记录内嵌 | 不会 |
| 插件配置 | ~/.dsh/profiles/ | 不会 |
| API Key | ~/.dsh/.credentials.yaml | 不会 |
| 工作区文件 | 你选的工作区目录 | 不会 |
dsh 没有云端同步、没有账号体系、没有遥测上报。你和模型的对话内容只在你发请求时传给模型提供商(DeepSeek 等),dsh 本身不存一份在云端。
这意味着:
- 好处:数据完全在你手里,隐私可控
- 代价:换电脑就得手动迁移
~/.dsh目录,没有一键同步
安全最佳实践
把上面的机制落到日常使用,记住这几条:
- 日常用
workspace-write,别常开full access——full access 下沙箱等于没有,Agent 能碰你整个硬盘。只有明确需要系统级操作时才临时开,用完切回去。 - 别把
~/.dsh目录直接传 GitHub——里面有.credentials.yaml明文密钥。如果要备份配置,单独导出settings.yaml(不含密钥),密钥另行管理。 - Docker 团队部署注意无多用户隔离——CH 27 讲过,当前版本所有人用同一个 Basic Auth 登录后看到的是同一份会话和配置。团队共用时别在里面存敏感信息,或者每人部署一个独立实例。
- 工作区选干净的目录——别把整个
C:\Users或 home 目录设为工作区。选一个专门的项目目录,Agent 能碰的范围就限定在那里。
这一章你学到了什么
能自己完成下面几条,就算过关:
- [ ] 知道 dsh 安全设计的核心思路:默认受限,按需放行
- [ ] 知道三层防护分别是什么:文件沙箱、操作审批、密钥只写
- [ ] 知道沙箱是 OS 内核级的,不是 JS if 判断,模型绕不过去
- [ ] 能说清三档权限(read-only / workspace-write / danger-full-access)的区别和适用场景
- [ ] 知道审批是"允许一次",不是永久放行
- [ ] 知道 API Key 是只写的,保存后界面不回显,明文只在本地
.credentials.yaml - [ ] 知道 dsh 所有数据都在本地,没有云端同步
- [ ] 能说出至少 3 条日常安全最佳实践
