第 17 章 · 安全边界与隔离
本篇目标:正确理解「沙箱不是安全边界」这句话,并据此做架构决策。 这一章的结论可能不讨喜:DSH 目前不能作为生产安全基座。
17.1 官方声明的准确含义
官方 SAFETY.md 逐条拆开:
| 条款 | 原文要点 | 工程含义 |
|---|---|---|
| Experimental status | 未经过安全审计,must not be treated as secure or production-ready | 不能作为唯一安全控制 |
| 能力面 | 可执行模型生成代码与命令、加载第三方插件、访问网络/进程/凭据/文件 | 攻击面覆盖宿主大部分资源 |
| 风险来源 | 错误模型输出、缺陷、错配置、恶意输入、不可信插件 | 不只防外部攻击者,也防自己的模型 |
| Sandbox limitations | 沙箱、审批、权限能降低风险,但不保证隔离;「Even correctly enforced restrictions cannot protect resources that the project is allowed to access」 | 允许访问的资源,沙箱保护不了 |
| 唯一控制 | Do not rely on DeepSeek Harness as the sole security control for untrusted workloads | 必须外层再加隔离 |
| 免责 | MIT,无担保,自担风险 | 没有厂商兜底 |
原文 作者补的一句与官方完全一致:「动态插件虽然运行在沙箱环境里,但沙箱不是安全边界。」
判据 21:凡是需要「保证」的隔离,必须由 Harness 之外的边界提供——一次性 VM / 容器 / 独立主机 / 网络策略 / 专用账号。Harness 内部的沙箱只是降低概率的一层,不是保证。
17.2 纵深防御:权限与沙箱是两层,不是一层
官方 Claude Code 文档给出目前最清晰的表述:
| 权限 Permissions | 沙箱 Sandbox | |
|---|---|---|
| 管什么 | 哪些工具、文件、域名可被使用 | Bash 及其子进程的OS 级文件系统与网络访问 |
| 作用范围 | 所有工具(Bash / Read / Edit / WebFetch / MCP) | 仅 Bash 命令及子进程 |
| 机制 | Deny / Ask / Allow 规则,Deny 优先 | macOS Seatbelt、Linux bubblewrap + socat |
| 被绕过时 | prompt injection 可能让模型「决定」访问 | 即使模型决策被绕过,OS 仍挡住越界 |
关键结论:两者结合才是纵深防御。Deny 规则阻止尝试,沙箱阻止 Bash 越界;PreToolUse hook 返回 allow 不会绕过 Deny 规则(Deny 仍会被评估)。
官方 常用配置键:
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false,
"filesystem": {
"allowWrite": ["/tmp/session"],
"denyWrite": ["~/.ssh", "~/.aws", ".env"],
"denyRead": ["~/.ssh", "secrets/"]
},
"network": { "allowedDomains": ["api.example.com"] },
"credentials": {
"files": ["~/.ssh", "~/.aws"],
"envVars": { "API_TOKEN": { "mode": "mask" } }
}
}
}
envVars 的 mask 模式值得单独说:真实 token 在命令里被替换成哨兵值,只对允许的主机注入真值。这样即便模型把命令打印进日志,凭据也不会泄漏。
--dangerously-skip-permissions 在官方文档里被标注为仅容器场景适用,不推荐用于 CI;更安全的模式是 sandbox + auto-allow。
17.3 威胁模型(逐条给对策)
| # | 威胁 | 入口 | 对策 |
|---|---|---|---|
| 1 | Prompt injection | 网页、文件内容、issue、PR 描述、MCP 返回 | 把外部内容当数据;独立 guardrail 模型检查;工具返回不进指令通道 |
| 2 | 恶意 / 有缺陷插件 | GitHub 第三方插件、社区预设 | 加载前通读代码;锁版本;不引多余依赖;最小 inject |
| 3 | 凭据泄露 | 环境变量、.env、日志、trace |
denyRead + mask;audit 脱敏;专用可撤销 key |
| 4 | 未授权外联 | Bash / WebFetch / MCP | 默认 deny 网络 + allowedDomains 白名单 + 出站代理审计 |
| 5 | 越权文件读写 | ../、符号链接、绝对路径 |
强制路径校验(第 02 章 is_relative_to)+ OS 沙箱双层 |
| 6 | 不可逆副作用 | 删除、发送、支付、push | 必须在 Harness 之外由业务逻辑保证幂等 + 人工 gate |
| 7 | 成本攻击 / 死循环 | 恶意输入诱导无限重试 | max_steps、max turns、budget 上限、时间窗告警 |
| 8 | 供应链 | npx / pnpm / 插件依赖 | 锁文件、固定版本、私有镜像、审计依赖 |
| 9 | 审计缺失 | 容器 stdout 随容器销毁 | audit 外送持久存储、always on |
| 10 | 自进化越界 | 创造模式自己装插件 | 禁止 Agent 放宽自己的权限预设 / 沙箱配置 |
第 6 条最容易被忽略:
ctx.effect()能撤销注册,撤不回一条已经 push 的 commit(第 11 章)。唯一解法是在动作发生前拦住。
17.4 在 DSH 上的最小安全配置
官方 subsystems/approval / permission-presets / sandbox 三个子系统页是入口。落地动作:
| # | 动作 | 依据 |
|---|---|---|
| 1 | 一次性 VM / 容器 / 独立主机里跑,宿主不放生产凭据 | SAFETY.md Responsible use |
| 2 | 工作区先 git 提交或开副本,保证可回滚 | 同上 Keep backups |
| 3 | 专用、限额、可撤销的 API key | 同上 |
| 4 | /permission 切到限制性预设,陌生仓库先跑一轮 |
原文 五分钟体检 |
| 5 | 从 GitHub 装的插件,加载前通读代码 | SAFETY.md Review plugins |
| 6 | 审批弹窗逐条看清再同意,不批量放行 | 原文 |
| 7 | 固定 DSH 版本,不追最新 | breaking change + 供应链 |
| 8 | 公网暴露前自行完成认证、隔离、凭据治理 | 默认只监听 127.0.0.1:3080 官方 |
| 9 | 告警与审计外送到 Harness 之外的系统 | 第 16 章 |
| 10 | 明确写入架构文档:本 Harness 不是安全边界 | 防止后来者误用 |
⚠️ 本教程不提供「一键公网暴露 DSH」或「关闭审批以提速」的配置。这两件事在官方安全声明下都属于不负责任的建议。
17.5 事故响应
出事时按固定顺序,别先去查模型:
① 隔离:停宿主 / 断网 / 撤销 API key
② 保全:复制 append-only 事件日志与 audit log(别重启覆盖)
③ 重建:从 Trajectory 按来源还原「模型当时看到了什么」
④ 定责:外部注入?插件?配置?还是模型输出?(第 06 章二分法)
⑤ 固化:新增一条规则 + 一个 hook / deny 规则 + 一个 coverage test(第 07 章)
⑥ 验证:用事故输入做一条 eval 用例,进 suite,永不移除
第 ⑥ 步是 ratchet 在安全场景的形态:每一次事故都必须变成一条永久回归用例。
17.6 本章产出与验收
核心产出:一份本项目威胁模型表(10 类逐条对策)+ 最小权限配置 + 一次「注入攻击被拦下」的验证记录。
验收点:
- 能逐字说清
SAFETY.md对「生产就绪」的结论 - 能解释权限与沙箱为何互补、各自覆盖不到什么
- 能说出
ctx.effect()撤不回什么,以及唯一解法 - 能列出至少 3 条必须放在 Harness 之外的安全控制
- 能把一次事故转成一条永久 eval 用例
延伸阅读
| 来源 | URL | 等级 |
|---|---|---|
DSH SAFETY.md / SAFETY.zh.md |
https://github.com/deepseek-ai/deepseek-harness/blob/master/SAFETY.md | 官方 |
| 官方文档 · 沙箱 / 审批 / 权限预设 | https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/sandbox | 官方 |
| Claude Code · Sandboxing | https://code.claude.com/docs/en/sandboxing | 官方 |
| Claude Code · Permissions | https://code.claude.com/docs/en/permissions | 官方 |
| Claude Code · Hooks(PreToolUse 阻断) | https://code.claude.com/docs/en/agent-sdk/hooks | 官方 |
@anthropic-ai/sandbox-runtime |
https://www.npmjs.com/package/@anthropic-ai/sandbox-runtime | 官方 |
| OWASP LLM Top 10 | https://genai.owasp.org/llm-top-10/ | 社区 |
| FDE-Wiki · 第 22 章 合规、安全与数据治理 | https://fde-wiki.github.io/ch22 | 社区 |