Files
dsh_shenxian/dsh-server-docs/04-调整方案/37a-guest会话取证与平台缺陷清单.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

15 KiB
Raw Blame History

37a · guest 会话取证与平台缺陷清单(MCN短视频创作)

  • 日期:2026-09-11
  • 触发:用户要求「看看 guest 用户的 MCN短视频创作 工作区的对话记录,能发现哪些问题」
  • 状态:🔍 取证完成(本档只记录缺陷,不含代码改动)
  • 关联:档案 32(同一方法,mcntimo 工作区)、档案 33(沙箱默认档位已改)、档案 21(guest 卡顿排查,服务端侧)、档案 23(实例内能力限制核查)

TL;DR|结论:从 guest 的「MCN短视频创作」会话反查平台缺陷清单(只记录缺陷,不含代码改动)。 关键:含 P0/P1 分级与证据;方法可复用于其他工作区(同档案 32)。 状态:🔍 取证完成


一、取证范围

项 值
用户 guest = 4092b965-2f68-4977-9989-68b3966f7df0(uid 100002,dsh-eeccbc638afc46bdb663)
工作区 ws/MCN短视频创作(workspace id 7f9fd72c-1cf3-49f3-bb72-ba3de28a16fe)
主会话 session-bd54c7cc-7620-4cf3-9bff-9084bcc5ae88,4190 行 / 2.8 MB 明文 / 1.3 MB zstd
副会话 session-b83ae69b-...,5 行(空会话,见 P2-3)
时间跨度 2026-09-10 12:12 → 09-11 14:52(CST)
规模 12 turns / 106 steps / 111 tool calls(bash 100、web_search 2、web_fetch 3、write 3、edit 3)
任务 单一诉求:获取抖音热门短视频榜单,以及围绕它的能力追问

产出物(工作区,agent 手写脚本抓取): scripts/douyin_hot.py、scripts/douyin_hot_videos.py、scripts/probe_shape.py; data/douyin_hot_2026-09-10_2148.{md,json}(97 行)、data/douyin_hot_2026-09-11_1447.{md,json}(52 行)、data/douyin_videos_2026-09-10_2154.{md,json}(75 行)。

产出质量本身可用(含话题名/热度/播放量/最高排名/首次出现时间/搜索链接)。问题不在产出,在下述代价、路径与平台缺口。


二、新增 P0

P0-1 · 存量会话不会被迁移到新档位 —— 全平台 10/10 会话仍卡在 workspace-write

档案 33 把新会话默认档位改为 danger-full-access(env 注入已落地:spawn.ts ALLOWED_ENV + orchestrator.ts baseEnv,已核实)。

但权限档位是会话级播种(会话创建时一次性写入 permission/preset / sandbox/mode / approval/policy 三条种子事件,resume 不重播)。实测全平台:

总会话=10   workspace-write=10   danger-full-access=0

即 10 个存量会话(含 admin 自己在 mcntimo / mcnworkspace / maiyamcn 的)全部仍是 workspace-write,只要它们被 resume 并执行 shell,就会撞上「sandbox backend is unusable → 拒绝执行」。guest 这条会话就是已经真实踩中的样本。

  • 缺口:平台没有任何 UI/文案提示「老会话需新开一个会话才生效」。用户唯一能得到这条信息的渠道是让 AI 去分析自己的会话日志(本次就是这么发现的)。
  • 候选方向:① 会话列表给旧档位会话打标记 + 一键「在新档位继续」;② 门户 enter 时对旧档位会话做一次性重播种(改会话数据,需评估);③ 最低成本:产品文案层提示。

P0-2 · 平台零技能投放:用户在 MCN 工作区里「无技能可用」

位置 实况
guest $DSH_HOME/home/skills/ 0 项
admin $DSH_HOME/home/skills/ 0 项
全员共享只读层 /var/lib/dshs/bundled-skills/ 0 项
各工作区 ws/*/ 内容 guest 只有 data/ + scripts/(无 SKILL.md、无素材库、无项目结构)
agent preset standard(无业务技能)

平台已建成技能机制(档案 10 共享只读层 + 档案 11 管理面 API/静态页),但一个技能都没投放。后果在会话里体现得非常直接:

  • 用户开的是「MCN短视频创作」工作区,却没有任何 MCN 技能被加载 → agent 只能从零 hand-roll 抖音抓取脚本、反复试错(100 次 bash 中相当一部分是抓取路径试错)。
  • 用户第 7 问「为什么需要写代码,不能获取后直接展示内容吗」、第 9 问「有安装网络搜索工具吗 比如 deepseek 搜索」——都是**「本该有技能/数据源,却没投放」**的症状。
  • 应投放而未投放:MCN 短视频创作技能(脚本/分镜/账号分析)、RedFox 数据源(日榜/飙升榜/账号诊断,本平台已有 API Key 与 7 赛道口径)、mcn-data-insight 系列技能。

这是本次取证最重的产品结论:不是能力不够,是已有能力没有接到用户面前。


三、修正档案 32 的两条结论

修正 1 · 「沙箱不可用」不是恒定状态,同一会话内会翻转

档案 32 结论为「bwrap 已装但 dsh 后端探测仍判不可用」,并附「实例内嵌套 bwrap 失败」。本次拿到同一会话内前后对比的强证据:

时间 同一会话内的实测 bash
09-10 12:12–12:13(turn 1) id / uname / read /etc/passwd / touch /tmp / mounts 全部正常返回 ✅ 可用
09-10 13:47:03 与 13:47:28(turn 2) Error: sandbox mode "workspace-write" ... no sandbox backend is usable on this host; refusing to run the command unconfined. ❌ 全拒

二者之间只隔一次 session/end-seed(13:46:07)→ 会话 resume(13:46:59),无用户侧改动。 另:本次在服务器以 guest uid 模拟实例内做嵌套 bwrap 实测 → NESTED_BWRAP_OK(bubblewrap 0.4.0),与档案 32 的「失败」相反。

→ 结论修订为:「后端可用性」是时序/环境相关,不是确定性不可用(与实例 respawn、平台 bwrap 挂参变化有关,同期平台确实改过实例内挂载:turn 1 $HOME 只读 → 09-11 变可写)。 → 因为档案 33 已让新会话绕开沙箱,该问题当前不阻塞新会话;但对存量会话仍是硬阻塞(见 P0-1),根因仍未定位。

修正 2 · 沙箱报错丢失根因细节,并把「关掉沙箱」写进了报错文案

@deepseek-ai/dsh-sandbox/lib/index.js:185 的报错支持附加 Runner failure: ${detail}。但本次会话日志中 Runner failure 命中 0 次 —— 模型拿到的只有那句脱敏后的通用文案。

后果链(会话内实际发生):

  1. 模型无法判断根因 → 只能猜 → 主动发起提权申请: approval/asked reason = "The sandbox backend is unavailable on this host so every shell command is refused; full access is the only mode that lets me run curl to fetch the Douyin hot list you asked for."
  2. 用户 7 秒内点了「允许一次」(allowed-once)。
  3. 6 秒后用户自己又跑了一次 /permission danger-full-access(command/run,source: user)→ approval/policy 同步变为 never。

→ 官方沙箱的 fail-closed 设计是对的,但报错文案("otherwise switch the consumer to danger-full-access")等于手把手教模型申请降级安全档位;再叠加「根因细节丢失」,模型没有别的选择。这与档案 32 的判断一致,本次补上机制性证据。


四、P1

# 问题 证据(会话内)
P1-1 模型被切到实验模型,且切换事件无法审计 model/selection → deepseek-v4-flash-vision-exp,reasoningEffort high→max(13:47:50 / 13:47:53,turn 2 中途)。model/selection 事件无 source 字段 → 无法判定是用户切、平台切还是自动切。后续整段会话跑在实验模型上
P1-2 智能体把「用户手动提权」误报为「平台能力增强」 turn 11 用户问「看看现在能力有增强吗」→ agent 结论「能力确实有增强…核心是 bash 从『完全不可用』变成『可用』🟢 最大增强」。实际是 turn 2 用户自己跑了 /permission danger-full-access(command/run source=user,就在同一份日志里)
P1-3 联网抓取路径不可持续,全靠「绕」 ① 抖音官方视频接口要签名 → Unsupported path(Janus) / HTTP 200 空 body;② tophub.today → 403 检测到异常访问行为;③ 最终靠伪装 Baiduspider UA 拿 SSR 页再正则扒 HTML(脆弱的爬虫 hack),并退回 GitHub 第三方镜像(时效差 3 小时,agent 自陈「镜像最后更新 18:49,我抓的是官方 21:47」)
P1-4 平台 web_search 可用但没人知道 官方 dsh-web-search-deepseek 已装且实测可用(web/deepseek-search-llm-request 3 次)。但前 8 轮 agent 一直用 curl/python 硬抓,第 9 轮用户主动问「有安装网络搜索工具吗」才开始用。111 次工具调用里 web_search 只有 2 次
P1-5 用户感知「卡」的原始证据(补充档案 21) 用户第 13 问「感觉对话过程卡吗」→ agent 用日志算出:69 步、平均 7.8s/步、中位 5.0s、最慢 81.1s、模型总生成 8m58s;单次 bash 最长 1m19s;turn 3 单轮 4m50s。档案 21 已证服务端全链路不慢(TTFT 1.0–3.5s),本次补上「用户侧体感来自哪 69 步 / 哪 111 次工具调用」的实测数据 —— 卡顿主因是工具调用轮次过多,而轮次过多的直接原因是「技能未投放 + 数据源未接入」(P0-2 / P1-3),不是网络
P1-6 会话导出产物用户打不开 用户点过 /export(command/done → "Session log download requested.")。格式是 .jsonl.zstd 追加式多帧,zstdDecompressSync 只解第一帧;连 agent 自己都踩了这个坑(流式解压失败: Unknown frame descriptor → 改用魔数 28 B5 4D FD 逐帧解出 1632 帧)。用户拿到的是一个无法阅读的文件
P1-7 环境基线太弱,MCN 场景几乎不可用(量化档案 23 的「可优化」项) agent 自统计 35 处失败/受限,含:Python 3.6.8 + pip 9.0.3(al8 自带)、rg / jq / ffmpeg 缺失、无任何浏览器(chromium/chrome/firefox 全 MISSING,Playwright 落地需 300MB + 11 个系统库缺失且 /usr 只读无 sudo 装不上)、/usr+/etc 只读、无 sudo。档案 23 已把这些列为「可优化」,本次量化了它们实际烧掉的轮次(100 次 bash 中约 1/3 耗在补环境与绕路径)
P1-8 过度承诺后自我推翻,浪费用户轮次 agent 先推荐装 Playwright,实测后自我否定:「我之前推荐它,根本没算过这笔账」;并承认「我上一条的说法确实站不住脚」(把第三方镜像数据当成实时数据)

五、P2

# 问题 证据
P2-1 会话列表出现空会话残留 session-b83ae69b:仅 4 条事件(preset/mode/policy + end-seed),0 个 turn,13:29 创建、21:26 才结束,挂 8 小时
P2-2 平台缓存污染用户工作区 ws/.npm/_cacache、ws/.npm/_logs、ws/.cache/pip/、ws/workspace-scoped-picker-0.1.4.tgz 均落在工作区根部,会出现在门户 #/files 列表里
P2-3 工作区根存在平台 bundle .tgz ws/workspace-scoped-picker-0.1.4.tgz(09-11 15:00 更新)。档案 35 已修 ws-cleanup 误删,建议确认该 picker 包也在豁免口径内(当前豁免逻辑按「profile 的 file: 引用」动态判定,需回归验证)
P2-4 工具报错噪音,指向不存在路径 rg: /opt/dshs: No such file、rg: /var/log: No such file(实例内看不到平台目录,agent 反复试)
P2-5 文档内部不一致:README 档案清单落后 8 个档案 docs/README.md 的「档案清单」表止于 28-用户数据清理策略,29–35 全部缺失;而 docs/INDEX.md 是全的(到 04-35)。README 自称「档案清单只在本文件维护」,与该「单一来源约定」已失效(本次只在 INDEX + docs-status 维持,未擅自重排 README)

六、安全观察(平台挡住了,但值得记录)

guest(普通租户)在会话中主动做了横向/越权探测,全部被平台层挡住:

探测动作 结果
ls /var/lib/dshs/users/ Permission denied ✅
touch /etc/dsh-probe、touch /usr/local/lib/node_modules/@deepseek-ai/dsh/probe Read-only file system ✅
ls /root、/home/admin、/home/www、/home/dsh-cce6d1cdb376430480f0 不存在 / 不可访问 ✅(bwrap 只暴露自己的用户根)
sudo 不可用(/etc/sudo.conf 属主 uid 65534、未 setuid)✅
ps -eo user,pid,cmd 可看到进程列表(bwrap 只 --unshare-pid,未做 PID 视图隔离)⚠️
curl http://127.0.0.1:3080/ (门户) 返回 200,可读到门户首页 HTML ⚠️(仅静态首页,无数据泄漏)
内网端口扫描 3080/80/443/888/8765/58888/32022 可探测,返回状态码与 Server 头 ⚠️
env | grep -iE 'api_key|token|secret'、读 $DSH_HOME/.credentials.yaml agent 主动做了脱敏打印;扫描会话全文:0 处明文凭据 ✅
起本地监听 python3 -m http.server 39777 成功(127.0.0.1 绑定 OK)+ pip install / npm 出网均可用 ⚠️(与既有「实例共享宿主网络、出网未全封」结论一致)

结论:数据面与文件面隔离有效;网络面(内网侧)与审计面是缺口 —— 上述探测没有任何阻断、限速或审计上报。


七、建议行动项(按优先级)

# 行动 说明
1 投放技能到 bundled-skills(P0-2) 最高性价比:MCN 短视频创作 + mcn-data-insight 系列。技能机制已就绪、watch 即时生效、无需重启
2 存量会话档位提示/迁移(P0-1) 10/10 会话受害;最低成本先做 UI 标记 +「新开一个会话」文案
3 接 RedFox 数据源到平台(P1-3/P1-4) 替代「伪装爬虫 UA 扒抖音」这条不可持续路径;已有 API Key 与 7 赛道口径
4 补环境基线(P1-7,延续档案 23) 最低集:rg / jq / ffmpeg / Python 3.8+;评估基线镜像方案
5 会话导出给可读格式(P1-6) 导出时转 .md 或解开的 .jsonl
6 model/selection 补 source 字段(P1-1) 属官方行为,只做记录与观测;先确认实验模型是否为预期

八、取证方法补充(相对档案 32 的新坑)

  1. 服务器 /tmp 下存在 package.json("type":"module") → 在 /tmp 放分析脚本必须用 .cjs 扩展名,否则 require is not defined in ES module scope。(本次踩坑)
  2. 会话日志里 tool/result 的报错常被 || echo 兜住,表面看不出失败 → 分析时要按「错误特征词」扫全文并统计位置分布,而不是只看退出码。
  3. request/header 每条含完整 system prompt + 工具表,体量大(占 2.8MB 相当比例)→ 提取时按 type 过滤,勿全量 dump。
  4. 分析脚本本地写好 → scp → 远端 node 执行最稳(内层引号转义会在 ssh '...' 里坏掉)。