# 脆弱性分析(AVA)— dsh-workplan v1.8.0 **性质:开发者自评的脆弱性分析,不是实验室的 AVA_VAN 评定。** 本文件回答三个问题:**能被怎么打 → 打了会怎样 → 现在挡不挡得住**。 --- ## 1. 方法 | 步骤 | 做法 | 可复核性 | |---|---|---| | 1. 攻击面枚举 | 列出 TOE 的全部外部接口(2 条 HTTP 路由 + 4 个模型工具 + 1 个随包文件) | `src/host.ts` 的 `webServer.register` 与 `registerTool` | | 2. 危险能力扫描 | 对危险 API 做源码特征扫描 | 本文 §5 命令 | | 3. 威胁建模 | 7 条威胁,逐条给对策与残留风险 | 本文 §3、ST §3 | | 4. 依赖审计 | 运行时零依赖;第三方文件记哈希 | [../SBOM.md](../SBOM.md) | | 5. 已知缺陷清单 | 列出已知但未修复的问题 | 本文 §6 | **未做**:第三方渗透测试、模糊测试(fuzzing)、形式化分析、侧信道分析。这三项是 N-01~N-03 差距的直接来源。 --- ## 2. 攻击面清单(穷举) | # | 入口 | 输入可控点 | 潜在滥用 | |---|---|---|---| | AS-1 | `GET/HEAD /dsh-workplan/plans` | 请求头、查询串(未使用)、方法 | 越权读取计划内容 | | AS-2 | `GET/HEAD /dsh-workplan/vendor/chart.umd.js` | 同 AS-1 | 路径穿越读任意文件(理论) | | AS-3 | `dsh_workplan_dispatch` | 模型生成的参数 | 未经确认的派发、重复派发 | | AS-4 | `dsh_workplan_update` | `subtaskId`、`status`、`expectedRevision` | 并发覆盖、伪造完成 | | AS-5 | `dsh_workplan_cancel` | `planId` | 取消他人计划 | | AS-6 | `dsh_workplan_status` | `planId` | 只读,风险最低 | | AS-7 | 随包 `vendor/chart.umd.js` | 文件本身(供应链) | 被替换为恶意版本 | **没有的入口**:文件上传、WebSocket、子进程、SQL、模板渲染、反序列化、命令执行、环境变量写入。 --- ## 3. 威胁 → 对策 → 残留风险 | 威胁 | 攻击路径 | 现有对策(实现层) | 残留风险 | 等级 | |---|---|---|---|---| | **T-01 未授权读取** | 直接请求 AS-1 | `route()` 先 `await connectionCtx.connection.requestRejection(req)`,拒绝即终止 | 若部署方能绕过 DSH 直连端口,或 DSH 未配置认证 → 可读 | **中**(取决于部署) | | **T-02 数据外泄** | 诱导插件出站 | 源码无出站 API;唯一 `fetch` 为浏览器同源 | 模型可把计划内容写进自己的回复,属 DSH/模型层问题,非本 TOE 可控 | **低**(TOE 内) | | **T-03 注入/穿越** | 构造 `../../etc/passwd` 之类路径 | 两条路由均为 `kind: 'exact'` 精确匹配;静态文件路径在代码中写死;响应带 `nosniff` | 未做模糊测试,未知边界行为 | **低** | | **T-04 状态篡改** | 并发 `update` 覆盖 | `expectedRevision` 乐观锁,不匹配返回 `STALE_WRITE` | 主代理自身可合法改写(设计如此) | **低** | | **T-05 资源耗尽** | 超长计划 / 子代理挂起 | 子代理超时 + 总预算双上限且夹紧;响应 > 2.5 MB 截断 | 极长计划仍占会话 token(受 DSH 限制) | **低** | | **T-06 供应链** | 替换上游依赖 | 运行时零依赖;唯一第三方文件随包固定,记录 sha256 | 开发依赖(3 个 @types/TS)被投毒可影响构建,不影响运行时 | **低** | | **T-07 虚假完成** | AI 自述"已完成" | 完成需附 `verification`(structured/unverified/failed/legacy)与 `acceptance`;`structured` 之外必须人工/主代理复核 | 主代理若不核对仍可能误信 | **中**(流程依赖) | --- ## 4. 已识别的具体缺陷与处置 | 编号 | 缺陷 | 影响 | 处置 | 状态 | |---|---|---|---|---| | V-01 | `respondJson` 与两处 `writeHead` 未设置 `x-content-type-options` | 某些浏览器可能对响应做 MIME 嗅探 | 新增 `HARDENING_HEADERS` + `applyHardeningHeaders()`,两条路由均调用 | **已修复 1.8.0** | | V-02 | 缺少 `referrer-policy` | 面板被嵌入外站时可能泄露 URL | 同上(`no-referrer`) | **已修复 1.8.0** | | V-03 | 缺少公开的漏洞报告渠道 | 研究者只能开公开 issue,扩大暴露 | 新增 `SECURITY.md`(私密 advisory + 时限) | **已修复 1.8.0** | | V-04 | 无依赖清单 | 无法快速回答"用了什么第三方代码" | 新增 `docs/SBOM.md` | **已修复 1.8.0** | | V-05 | 无 ST / AVA 文档 | 无法回答"保护什么、防谁" | 新增 `docs/cc/*` | **已修复 1.8.0** | | V-06 | `x-frame-options`/CSP 未设置 | 若被第三方页面 iframe 嵌入,存在点击劫持理论风险 | **未修复**:面板由 DSH 主页面同源加载,未以可嵌入形态对外;加 CSP 需与 DSH 主站策略协调,单独加会破坏面板 | 接受(记录在案) | | V-07 | 未做模糊测试 | 边界输入行为未知 | 未修复(需工具与时间预算) | 接受 | | V-08 | 无多租户隔离 | 多用户共用同一 DSH 实例时,计划数据在同进程内 | 设计边界:由 DSH 承担隔离;已在 SECURITY.md 写明 | 接受(设计边界) | --- ## 5. 复核命令(任何人都能验证上面的说法) ```bash # 1) 危险 API 扫描:预期 0 命中 grep -RInE "child_process|execSync|eval\(|new Function|writeFileSync|appendFileSync|mkdirSync|https?\.request" src || echo "0 命中(预期)" # 2) 网络调用:预期只有浏览器同源 fetch grep -RIn "fetch(" src # 3) 鉴权与硬化响应头 grep -n "requestRejection" src/runtime.ts grep -n "HARDENING_HEADERS\|x-content-type-options\|referrer-policy" src/runtime.ts # 4) 路由为精确匹配(非前缀) grep -n "kind: 'exact'" src/host.ts # 5) 响应截断阈值 grep -n "2_500_000" src/runtime.ts # 6) 全量测试 npm run verify ``` --- ## 6. 结论 - TOE 的攻击面**很小且可完全枚举**:2 条只读路由 + 4 个受控工具,无文件写入、无子进程、无出站请求。 - 本版本修掉了 5 项可修的缺陷(V-01~V-05),剩余 3 项(V-06~V-08)已写明理由,属**接受的风险**而非遗漏。 - 与 CC 的 AVA 类对照:材料层面满足自评要求,**不满足**第三方评定的要求(见 `CC-2026-ASSESSMENT.md` §7 N-02/N-03)。 - 最重要的残留风险不是技术性的:**T-07 虚假完成**依赖流程纪律,而不是代码。这一点必须在使用文档里反复讲清楚。 --- ## 8. v1.12.0 攻击面刷新(T5,2026-11-03,对应差距 G-24) §2 攻击面清单原锚定 v1.8.0(2 路由 + 4 工具)。v1.12.0 工具增至 **9 个**,新增 5 个入口全部纳入攻击面并按同一方法评估: | # | 新增入口 | 输入可控点 | 潜在滥用 | 对策(实测) | |---|---|---|---|---| | AS-6 | `dsh_workplan_replan` | changes[]、reason | 用重规划绕过旧计划验收/篡改范围 | 旧行保留可追溯不计入剩余项;执行中调用返回 REPLAN_PLAN_RUNNING 不改写;`workplan-replan-progress` 回归 | | AS-7 | `dsh_workplan_supersede`(经 cancel 的 superseded 处置) | 承接计划映射 | 伪造"责任已转移"掩盖未完成 | 运行时 V1–V8 逐条复算(承接计划更晚、证据 structured、验收全 pass),任一不满足返回 SUPERSEDE_*;`workplan-supersede` 回归 | | AS-8 | `dsh_workplan_followup` | sessionId、message | 向非直接子会话投递、诱导子会话虚假收尾 | 非父会话 catalog 登记的直接子会话一律拒绝;文案硬约束"不要求虚假完成";`workplan-followup-tool` 回归 | | AS-9 | `dsh_workplan_instruct` | subtaskId、instruction | 恢复非「待指示」行、越权改判 | 仅接受 closure=escalated 行;投递失败状态不变;`workplan-closure-ack-escalation` 回归 | | AS-10 | `dsh_workplan_escalate` | question/options | 子 Agent 借请示把决策推给主会话、空转 | 调用后子任务置「待指示」并停止推进,由主 Agent 决定;`workplan-pending-diagnosis` 等回归 | 新增接口的完整参数/失败行为见 `docs/cc/ADV-FSP-FUNCTIONAL-SPEC.md`。本节不改 §1 方法与「未做」声明:仍未做渗透测试、模糊测试与形式化分析;AVA_VAN.2+ 需外部实验室,为固有残留、如实披露。