# PR13 LocalShell.exec —— 上 UAT / GA 前必清的硬阻塞清单

**日期**：2026-05-16
**载入**：Phase 2 PR12-15 批量 PR（`feature/agent-pr11-electron-shell` 分支）
**状态**：当前 codebase 已落 **skeleton**——backend `LocalShellExecTool` descriptor 注册了，desktop dispatcher 收到 `client:shell.exec` 显式拒绝（`error: "shell_exec_blocked:sandbox_poc_pending+redteam_pending"`）。任何启用 path **必须**通关下面 3 项硬阻塞，缺一即不上线。

---

## 1. macOS 沙盒方案 PoC（day-1 选定）

PRD 明示：`sandbox-exec` 已 deprecated；**ESF / Network Extension 是监控/拦截框架，不是沙盒**。可行方案二选一：

### A. App Sandbox + entitlements（Apple 推荐）
- 进 `desktop/build/entitlements.mac.plist` 加 sandbox=true + 细粒度 entitlement
- 限制：沙盒内子进程继承宿主沙盒；解释器（python / node / bash）受限严格，可能跑不了大多数实用脚本
- 必须实测："agent 跑本地 `python script.py` 分析 csv"这个 PRD US-305 能否在 App Sandbox 内跑通

### B. Firejail-style 自研子进程隔离
- 自己 fork + 给子进程套 seatbelt 配置 / `posix_spawn_setexec` + 文件系统 namespace
- 工作量大；好处是控制粒度细，能放过 python 但仍隔离 fs/net

**PR13 启动前完成 PoC + Apple notarization 申请**（PRD review 决议）。**否则 macOS 不上 LocalShell，仅 Windows**。
PoC 输出 → 落到 `docs/modules/agent/02-architecture.md` PR13 段。

### 同步硬性约束（无论 A/B）

- **解释器白名单**：`python` / `node` / `bash` **显式允许**，其他二进制拒。白名单实现在 desktop dispatcher 内。
- **网络 egress 默认禁**：白名单放通（NS PF rule 或 Network Extension 内联）。
- **fs 边界**：默认仅 `~/FFAI Workspace/`；扩展走 OS 文件选择器（不让 LLM 自选目录）。

---

## 2. 红队测试集（zero-failure gate）

PRD 明示：**CWE-Top-25 注入 5 类 × ≥5 case + 季度新增样本**。**任一 fail = block release**。

样本池跟 PR2 `red-team-fixtures` 单源管理（PRD 反馈）：
- 命令注入（CWE-78）：`;` / `&&` / `$()` / backtick / IFS 注入
- 路径遍历（CWE-22）：`../` / 绝对路径 / symlink 逃逸 / NTFS ADS
- 资源耗尽（CWE-400）：fork bomb / 大文件写 / 长超时
- 解释器逃逸（CWE-94）：`python -c "import os; os.system(...)"`、`bash -c "$(curl ...)"`、`node -e ...`
- env 越权（CWE-22 衍生）：`LD_PRELOAD` / `PATH` / `HOME` 注入

**测试 harness**：每个 case 在沙盒里跑，断言"不读到 sandbox 外 fs / 不发 egress / 不执行白名单外命令 / 不卡死"。**zero-failure**——25 case 全过才能上 UAT。

实现位置：`testing/security/redteam-shell-exec/` 待 PR13 真正启动时建。

---

## 3. Apple notarization

App Sandbox + Hardened Runtime 都要 notarize。当前 `desktop/electron-builder.yml` 已让 codesign / notarize 走 env：
- `APPLE_ID` / `APPLE_APP_SPECIFIC_PASSWORD` / `APPLE_TEAM_ID`

任何 PR13 上线前必须：
- 申请 Apple Developer Program team（如未申）
- 公司 IT 备案 / 法务审 Apple 协议
- 第一次 notarize 提单（人工 Apple 审 24-48h）

---

## 解封流程

PR13 真正落地时新开 branch `feature/agent-pr13-localshell-exec`，按顺序：

1. PoC（A or B）→ docs/modules/agent/02-architecture.md PR13 段填实
2. 红队 25 case harness 实现 + CI 集成（任一 fail block）
3. notarize 凭据齐备 + 公司账户就位
4. desktop dispatcher 解除 `shell_exec_blocked` 硬拒，替换为 OS 沙盒包装 + 解释器白名单
5. backend `LocalShellExecTool` 仍走 descriptor-only（执行在 client），不变
6. 灰度上线（admin 关停开关默认关，组织开启走 IT 审批）

**不可跳过任何一步**。

---

## 当前 PR（PR12-15 批量）里 PR13 涵盖的：

✅ backend `LocalShellExecTool` descriptor（`requiredCapabilities=['shell.exec']`, surface=[desktop, cli]）
✅ desktop dispatcher 收到 `client:shell.exec` 显式拒绝 + 错误码 `shell_exec_blocked:sandbox_poc_pending+redteam_pending`
✅ admin 关停开关：`OrganizationAgentSettings.disabledCapabilities` 在 PR2 day-1 已落 schema，运营态默认把 `shell.exec` 写进去（PR0.6 部署 runbook 跟）
✅ 本 learning 文件作为 release blocker 清单的事实源

❌ macOS PoC（不在本 PR 范围）
❌ 红队 25 case（不在本 PR 范围）
❌ notarize 提单（不在本 PR 范围）
