Files
dsh_ai1net_server/dsh-server-docs/04-调整方案/23-实例内AI能力与权限限制核查.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

66 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 23 · 实例内 AI 能力与权限限制核查(guest 对话记录)
- 日期:2026-09-11
- 触发:用户提供 guest 账号在 AI 对话中遇到的 9 条"平台/环境限制"清单,要求判定**哪些正常、哪些不正常**
- 结论一句话:**9 条中 1 条是真 bug(且是 P1,实例内 bash 工具被整体拒绝,已定位并已打补丁待重启生效)、3 条可优化、4 条属设计使然、1 条与平台无关**。
- 状态:修复已编译(CI ✅),**待重启服务生效**;其余为建议项
> **TL;DR**|**结论**:guest 报的 9 条环境限制逐条判定:**1 条真 P1**(合成根缺 `/bin /sbin /lib` → dsh 沙箱探针失败 → **实例内 bash 工具被整体拒绝**,已修)+ 3 条可优化 + 4 条设计使然 + 1 条与平台无关。
> **关键**:修复 = bwrap 补 3 个符号链接(不扩大可见面);另记一条安全点:统一 `DEEPSEEK_API_KEY` 注入实例 env 的外泄面。
> **状态**:✅ 修复已上线(§五为建议项)
---
## 一、逐条判定
| # | 用户观察 | 判定 | 依据(实测) |
|---|---|---|---|
| **1** | 🔴 沙箱后端缺失 → `sandbox mode "workspace-write" is requested but no sandbox backend is usable on this host; refusing to run the command unconfined`,**整个 bash 工具被拒**(2 轮) | 🔴 **真 bug(P1)—— 已修复待生效** | 见 §二 |
| 2 | 只读根文件系统(`/etc`、DSH 安装目录、`ws` 上级 → Read-only file system,4 处) | ✅ **正常(设计)** | `spawnAsUser` 的 bwrap 参数:`--ro-bind /usr /lib64 /etc`,仅用户根目录 `--bind` 可写 → agent 写系统路径本就不该被允许 |
| 3 | 无 sudo(`/etc/sudo.conf` 属主 uid 65534、sudo 未设 setuid) | ✅ **正常(且是安全特性)** | 宿主上 `/usr/bin/sudo` 实为 `---s--x--x`(setuid root)、`/etc/sudo.conf` 为 root:root;实例内失效是因为 **bwrap 默认 `no_new_privs`** → setuid 提权无效,且租户不在 sudoers |
| 4 | 他人目录 `Permission denied`(`ls /var/lib/dshs/users/`) | ✅ **正常(隔离生效)** | `users/` 为 711(可穿越不可列),每用户目录 700;这正是多租户隔离,**探测被拒是预期结果** |
| 5 | 工具缺失:`rg` `jq` **`ffmpeg`** MISSING | ⚠️ **可优化**(ffmpeg 影响视频业务) | 宿主实测三者皆缺;因 `/usr` 是 ro-bind,**宿主装好 → 实例立即可用**,无需改 bind/重启实例 |
| 6 | 无浏览器(chromium/chrome/firefox 全 MISSING,无 playwright),抖音签名解不了 | ⚠️ **预期内,但影响抖音类任务** | 宿主确无浏览器;headless 浏览器需额外安装(体积/内存),而每实例有 **MemoryMax=512M** 上限 → 需评估 |
| 7 | Python 过旧:3.6.8 + pip 9.0.3 | ⚠️ **可优化**(3.6 已 EOL,很多包装不了) | 宿主系统 python3 即 3.6.8(Alibaba Cloud Linux 8),实例经 ro-bind `/usr` 看到同一份 |
| 8 | 无 DeepSeek 密钥:直接 curl → http=401(5 轮) | ⚠️ **半正常 + 一个安全点** | 实测实例进程 env **确实含 `DEEPSEEK_API_KEY`**(键名存在)→ 401 是因请求未带鉴权头。**但**:统一 key 注入实例意味着 **租户 agent 可读取并外泄平台 key**(P1 风险) |
| 9 | `api.vvhan.com` → `curl: (6) Could not resolve host`(3 轮) | ✅ **与平台无关** | 公共 DNS 亦返回 **NXDOMAIN**(`vvhan.com` 本身可解析)→ 该子域不存在,第三方 API 地址已失效 |
## 二、第 1 条根因与修复(P1)
**现象**:实例内 bash 工具**完全不可用**(不是被拒某条命令,而是工具整体被拒)。
**根因链**:
1. `dsh-sandbox-local` 在 Linux 的 runner 链 = **bwrap → Landlock**;两者探测都失败时抛 `SANDBOX_UNAVAILABLE`,上层 `dsh-sandbox` **拒绝无沙箱运行**("refusing to run the command unconfined")。
2. **Landlock 不可用**:内核要求 ≥ 5.13,本机 Alibaba Cloud Linux 8 内核为 **4.19**。
3. **bwrap 探针失败**:我们给实例构造的是**合成根**(只 bind `/usr`、`/lib64`、`/etc`、`/dev`、`/proc`、`/tmp` 与用户根),**缺 `/bin`、`/sbin`、`/lib`** → 探针要执行的 `/bin/sh` 之类 `execvp` 失败。
> 对照实测:宿主 userns 正常(`kernel.unprivileged_userns_clone=1`、`user.max_namespaces=7322`),**嵌套 bwrap 本身可运行**(补上三个符号链接后 `NESTED-SHELL-OK`);因此问题不在"能不能嵌套",而在"根布局不标准"。
**修复(已实施,待重启服务生效)**:`src/supervisor/orchestrator.ts#spawnAsUser` 的 bwrap 参数补三个符号链接(**不扩大可见面**,仅三个链接):
```ts
'--symlink', 'usr/bin', '/bin',
'--symlink', 'usr/sbin', '/sbin',
'--symlink', 'usr/lib', '/lib',
```
**验证**:`bash scripts/ci.sh`(typecheck + build + 单测)✅;ci 外还做了嵌套 bwrap 实测 ✅。生效需 `systemctl restart dshs`(会 drain 实例)。
## 三、建议项(按性价比)
| 项 | 建议 | 成本 | 影响 |
|---|---|---|---|
| **ffmpeg** | 宿主 `dnf install ffmpeg`(或放一份静态构建到 `/usr/local/bin`) | 低(一次安装) | 解锁视频抽帧/转码(MCN 核心场景) |
| **python** | 宿主装 python3.11/3.12(或引入 `uv` 供用户在 ws 内自建环境) | 中 | 解锁现代依赖(现 pip 9.0.3 基本装不了东西) |
| **rg / jq** | 宿主 `dnf install ripgrep jq` | 极低 | 提升 agent 检索/JSON 处理效率与准确性 |
| **headless 浏览器** | 评估 playwright + chromium(注意 512M 内存上限与体积) | 中高 | 抖音签名等重前端任务;**建议先只给需要的账号开** |
| **统一 key 的外泄面** | 三选一:① per-user key ② 内网 LLM 代理网关(带记账/限流,实例只拿短期令牌)③ 接受现状并写进已知风险 | 中 | 现状下租户可用 agent 读出平台 key;属"设计层"取舍 |
## 四、不受影响/无需处理的项
- **第 2/3/4 条**:多租户隔离与该有的边界,**保持**。修复第 1 条后,实例内 bash 将恢复可用,但写权限仍受 `workspace-write` 限制(只在工作区内可写)、系统路径仍只读——这正是期望形态。
- **第 9 条**:第三方域名失效,与平台无关(建议 agent 侧记录"该 API 已下线")。
## 五、红线遵守
- 核查全程**只读**(`ps` / `/proc/*/environ` 只取键名 / 公共 DNS 查询 / 官方包源码 grep),未读取任何密钥正文、未导出对话内容。
- 修复只改编排器自身的 bwrap 参数(不碰官方 dsh 主程序与缓存,R2 满足)。