Files
dsh_shenxian/dsh-server-docs/04-调整方案/32-mcntimo会话取证与沙箱P0核查.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

6.1 KiB
Raw Blame History

32 · mcntimo 会话取证与「dsh 沙箱不可用」P0 核查

  • 日期:2026-09-11
  • 触发:用户要求「看 admin 在 mcntimo 工作空间下的对话记录,能发现哪些问题」
  • 状态:🔍 核查完成,P0 待决策(未修复)

TL;DR|结论:admin 在 mcntimo 工作区的会话取证 → 查出 「dsh 沙箱不可用 → 拒绝执行任何 shell」 这一 P0。 关键:取证方法可复用(会话事件流 → 错误归类 → 根因);该 P0 由档案 23/33 处置。 状态:🔍 核查完成(P0 当时待决策)

一、取证方法(可复用)

  • 会话文件:/var/lib/dshs/users/<UID>/home/sessions/--<cwd 路径把斜杠换成横杠>--/session-<uuid>/session.jsonl.zstd
  • 工作区注册表:$DSH_HOME/storages/workspace.json(id → path/title/sessionIds)
  • 坑:文件是追加式多帧 zstd。Node 内置 zstdDecompressSync / createZstdDecompress 只能解第一帧(得 240 字节 session 头,随后报 Unknown frame descriptor)→ 必须用 zstd CLI(服务器原先未装,已 yum install -y zstd 装上 zstd-1.5.1-2.0.2.al8)。
  • mcntimo 共 2 个会话:主会话 2268 行 / 1.61 MB;另一会话 4 行(空会话)。

二、P0:dsh 的 workspace-write 沙箱在平台环境下不可用 → 拒绝执行任何 shell

现象:实例里执行 shell 报

sandbox mode "workspace-write" is requested but no sandbox backend is usable on this host;
refusing to run the command unconfined. ... otherwise switch the consumer to danger-full-access.

出自 @deepseek-ai/dsh-sandbox/lib/index.js:185。fail-closed:没有可用后端就拒绝执行,不是降级。

独立核实(非仅凭日志):

项 实测值 结论
内核 5.10.134-19.1.al8.x86_64 Landlock 需 5.13+ → 不可用
LSM /sys/kernel/security/lsm = capability,selinux landlock 未启用
/sys/kernel/security/landlock 不存在 同上
bubblewrap 0.4.0 已装 但 dsh 的后端探测仍判为不可用
平台合成根 /bin /sbin /lib 符号链接 在位(档案 23 的修复) 该修复未解决本问题
实例内直接跑命令 nsenter -t <pid> -m -p ... /bin/sh -c "id" → 成功(uid=114801) 平台层没坏,坏的是 dsh 内部沙箱探测
实例命名空间内跑嵌套 bwrap 失败(execvp 阶段) 与「后端不可用」一致;未复现日志里的 Can't mount proc: Operation not permitted

会话证据(行号分布):沙箱报错出现在第 44 / 113-121 / 156 / 174 / 180 / 614-619 / 658 / 805-809 / 908 / 1060-1065 行 —— 分布全篇;而末 400 行报错数 = 0,因为用户中途手动把权限切到 danger-full-access。 → 定性:默认模式坏、切了就好的模式性问题,不是一次性故障。

影响面(判断):

  1. 新会话 / 新用户开箱即用不了 shell(默认 workspace-write)—— 最严重:普通用户第一件想做的事就撞墙。
  2. 报错文案是写给开发者的(「Install bubblewrap or run a Landlock-enforcing kernel…」),普通用户看不懂;且把「切 danger-full-access」这条降级路径直接写在报错里 —— 等于引导用户主动关掉沙箱。
  3. 用户为此连点三次要求「突破限制」(见下),产品侧无阻断、无上报。

未做(待决策):仍需在**新会话(默认 workspace-write)**里实测一次 shell,确认 P0 是否仍存活。若存活,候选方向:

  • A(推荐):平台层已提供 bwrap + uid + cgroup 隔离,dsh 自己的沙箱属冗余且有副作用 → 把 dsh 沙箱默认设为 danger-full-access,并在实例 UI/文档说明「隔离由平台层负责」。需同步评估语义(用户会看到「完全权限」字样)。
  • B:让 dsh 的 bwrap 后端在嵌套环境下可用(需 platform bwrap 放开 --unshare-user 等,风险与工作量都更高)。
  • C:保持现状 + 只做报错文案的产品化提示(治标)。

三、其他发现(P1/P2)

级别 问题 证据
P1 权限预设「每会话」、UI 不可持久化,新会话回落 workspace-write;报错却让用户去找 consumer 切换 会话内助手原话「默认仍是 workspace-write,预设是每会话的」
P1 摘护栏只需一次点击:ask → never + danger-full-access,无二次确认、无风险提示 会话出现 approval policy changed from "ask" to "never"
P1 工作区是空目录(ws/mcntimo 只有 ./..),建会话无校验、无提示 ls . 输出 total 8
P2 用户3 次要求「突破沙箱限制」,产品侧无阻断/无审计上报 会话原文「可以试试看能否突破限制」「现在已开启完全权限,是否可以突破限制」
P2 工具报错噪音大、常指向不存在路径,浪费轮次 rg: /opt/dshs: No such file、rg: /var/log: No such file

凭据扫描:0 命中(无 sk- / bearer / JWT / AKIA / 私钥)。 异常中断:未发现(6 轮 turn/end 全 completed;53 次工具调用,其中 7 次 bash 有 2 次被沙箱拒)。

四、附:同一批并行的另一条只读通道(dsh-market 安全审计)

结论摘要(尚未单独成档):dsh-market 不能装任意来源,但能自助安装官方目录全部 3408 款插件、零审批,且**「配置备份恢复」路径可绕过目录校验直接装任意 GitHub 源** → 对「admin 投放 → 用户启用」第三层管控构成实质绕过(风险等级:中;实例隔离兜住爆炸半径,越不到宿主/其他租户/平台 DB)。

证据:routes.ts:4193 安装前只校验「是否在社区目录里」;registry.ts:169 loadRegistry() 每次实时抓官方 plugins.json,无本地白名单;backup.ts:139 validatedBackup 只校验格式、不校验依赖 spec。

五、本次附带的环境变更

  • 服务器安装 zstd-1.5.1-2.0.2.al8(yum 官方源,经用户授权)—— 用于解压会话记录。