Skip to content

Latest commit

 

History

History
224 lines (148 loc) · 17.8 KB

experimental-native-execution.md

File metadata and controls

224 lines (148 loc) · 17.8 KB

实验性讨论:Windows 安全拒绝、typed native argv 与显式路径转换

状态:实验性实现讨论 / Draft,Unreleased。 本文介绍实验实现的设计、接口和工程取舍。它尚未完成生产验收,不是发布候选或完整安全认证。

关联:验证矩阵与复现、变更记录。

1. 要讨论的决定

本提案把三个容易混为一谈的问题拆开:

  1. 没有可靠的 Windows Git Bash 围栏时怎么办? 当前实验选择 fail-closed,不再“标注无围栏后继续”。
  2. 必须精确保留 Windows 原生参数、明确解码原生输出时怎么办? 新增独立 typed argv 入口,复用 Core 托管执行。
  3. 原生 Node API 如何使用模型得到的 MSYS 路径? 新增完整值运行时转换,不再把源码字符串猜测当作可靠机制。

另补 Agent 路由指引,让上述机制不是仅存在于 README 中的“需要用户手动教模型”的能力。

维护者已在 PR #26 裁决接受 fail-closed 方向,要求默认开启且可实时关闭的行 Config 开关。正式验收门槛仍未完成。

2. 问题与非目标

2.1 MSYS 参数转换

在 Bash 启动原生程序时,MSYS 可能把 /all、/c 当作路径。单命令 EXCL、双斜杠等只适用于确定场景;EXCL 按前缀匹配,排除 /c 也可能影响真正的 /c/... 文件参数。

实验不全局设置 MSYS2_ARG_CONV_EXCL=*,不重写 Bash command,不猜某个字符串究竟是 option、路径还是程序源码。

2.2 输出编码

UTF-8 捕获不等于原生程序输出 UTF-8。locale 变量不保证改变其代码页;同一调用、甚至同一流可以混合编码。没有替换字符也不能证明转码正确。

实验只支持显式已知编码。未知同流混编码不能普遍可靠解码;损坏后的字符串不能普遍还原原始字节。

2.3 源码字面量猜测

legacy codePaths 无法识别 /c/users 是路径还是路由数据,也不能可靠处理所有动态表达式。它的默认值和既有兼容机制没有在本提案中移除。

显式 helper 是完整值接口,不是“更聪明的全程序重写器”。处理路径状业务数据时建议关闭 codePaths;普通工具路径参数翻译不因此关闭。

2.4 真正 Windows confinement

本提案没有修复 OS 围栏。匹配研究纠正了旧泛化:现代 MSYS cygheap 使用 VirtualAlloc,signal pipe 使用显式 SD;实际 Core 已补 TokenDefaultDacl。不能据此声称“再补默认 DACL 就解决”或“所有未来方案都无解”。

IPC/Token/AppContainer/VM 路线仍需隔离环境的真实正负权限验证;这些 OS 隔离机制不属于本提案的实现范围。

3. 原则与体验变化

项目 旧行为或既有原则 当前实验
Windows 受限自有 Bash 无围栏执行并标注 unconfined RO/WW/缺失策略在执行前拒绝
默认 Shell Git for Windows Bash 保持;原生入口是显式补充,不是隐式 fallback
root PowerShell/provider route B 不替换 保持
原生参数 通过 Bash/MSYS,可能转换 typed native 入口只转换标明的路径
Node 路径 字面量尽力重写 可显式转换运行时完整值;legacy 默认未改
编码 原有 UTF-8 捕获边界 新入口逐流显式编码,默认 utf8/replace
设置/界面 现有 Config/UI experimentalNative volatile 布尔,默认 true,同卡实时编辑
同装 dsh-ops 的受限会话 本插件 bash fail-closed;ops_bash 只发 full-access 不是零命令工具:ops_* 在场时补位逻辑不遮蔽 pwsh(inlineNeeds 的 hidePwsh 短路,宿主 pwsh 故事保留),官方执行器带真围栏可直接跑命令;bash 要回来需切 danger-full-access 或关 experimentalNative(后者同时放开 ops_bash)

运行时开关: 设置 → 插件 → dsh-gitbash-shell →「实验原生执行 / fail-closed」,权威值是 gitbash-shell 行 Config 的 experimentalNative,默认 true(包括旧配置缺键)。开启时受限/未确定 Windows Bash 拒绝,两个 companions 在能力可用且不冲突时注册。关闭时实时注销两个工具(旧 SDK 引用也拒绝),Bash 恢复旧版明确标注 enforcement: 'unconfined' 的受限执行并一次性日志告知;未确定策略保持旧版宿主委派。关闭不提供真实围栏,shell 文件写入限制不执行;官方文件工具策略始终独立。

变更作用于现有会话后续调用,无需重启,不终止已开始的后台 producer。native 在准备入口、异步准备后、执行入口及最终 spawn 重读开关;已关闭则不得开始新进程。重新开启恢复工具注册与拒绝机制。posixPaths、codePaths、subagentDialect 独立,不改变安全开关。拒绝错误说明设置关闭路径及用户在会话访问模式控件选择 danger-full-access 的路径,Agent 不得自行调整。

21 份词典均已补齐开关本地化,保留工具名、UNCONFINED 和 danger-full-access 的事实,维护者可继续审阅译文。

4. Agent 应如何选择

意图 选择 禁止的理解
Shell 脚本、管道、重定向、globbing、POSIX utilities bash 不能把权限拒绝当作改用另一个执行入口的许可
Windows .exe 精确 literal argv,或已知逐流编码 可见的 gitbash_native 不是 shell source,也不是通用脚本包装器
完整 MSYS 路径交给原生 Node fs/path 可见的 gitbash_to_native_path 不转换路由、搜索数据、command/code;不授文件权限
真正 PowerShell cmdlet/服务/WMI 可见且开关允许的 pwsh 不调用隐藏名称、不把 PowerShell 嵌进 Bash 绕行
权限/访问拒绝 停止并说明 不自动换模式、解释器、文件工具或 Node I/O
显示/解码失败 核对 producer exit 与输出事实 不盲目重复有副作用的命令

路由生成在提示组装按实际工具面生成,不只看开关意图。自有提示块可替换、幂等;重组后不残留失效建议。方言/子代理方言关闭不关闭安全选路指引。

PTC 中直调 schema 可只有 run_code:该描述解释如何选择已提供 SDK binding,具体 native/path binding 的描述进入 tools:sdk。没有把 SDK 声明误当成可直调工具,也不编造缺失名称。

已验证提示送达,不等于已验证 LLM 必然正确决策。 当前没有真实模型自主选工具评测。

5. 架构:不建立第二套进程系统

agent-owned tool scope
  ├─ bash → private GitBashSandboxExecutor → existing Core lifecycle/provider
  ├─ gitbash_to_native_path → fresh shared translator → native_path(无I/O)
  └─ gitbash_native
       ├─ 每调用解析真实 standing policy / 严格请求校验
       ├─ prepared capability(WeakMap;不是可伪造的 policy DTO)
       ├─ bounded preparation / trusted artifact owner
       └─ per-operation scope(属于 agent,隔离 shell + subprocess)
            └─ actual LocalBashExecutor.executeArgv
                 └─ private guarded provider facade
                      └─ actual managed provider + per-stream output adapter

对应:执行器、工具/Jobs/DTO、输出适配。

不改 root 服务条目,不另造 child_process runner/Jobs registry,不覆盖 private spawnSpec。新模块不静态导入宿主 peer;由既有 host resolution 通道注入真实模块。

6. 权限与拒绝

6.1 自有 Bash

策略门要求 Windows spec 明确为 danger-full-access;其他/缺失策略拒绝。工具层预检查位于工作目录准备、环境收集和 Jobs admission/promotion之前。

实际 host SandboxUnavailableError 能解析时保留结构化 SANDBOX_UNAVAILABLE;直接/旧调用者缺导出也必须拒绝,不能因此运行。非 Windows 的受限路径仍继承父后端。

6.2 Native

不以部署 defaultMode 代替逐调用策略;准备、执行、目录 callback 前后、最终 spawn seam 重验真实 standing policy。Prepared request 只能由同一个 executor 产生,复制或跨 executor 不构成能力授权。

这只是本地 Windows danger-only 入口,不是 native restricted-token adapter;不支持模型传入 env、sandbox_permissions 或自动 escalation。

6.3 边界

官方文件工具有独立 policy;helper 转换不扩大权限。minimal 持久 PTY、侧栏交互终端和其他插件执行器不因本门控获得围栏。历史 unconfined 渲染仍兼容旧记录,不授权新调用降级。

7. 接口

7.1 gitbash_to_native_path

输入 { msys_path: string },成功值 { native_path: string }。复用共享 translator 与 fresh mount facts;无 fs I/O、存在性判断或 env seeding。

Windows-native/cwd-relative 值声明后可 passthrough;未知 POSIX mount、缺映射、空值、NUL、URL明确拒绝。msys_path/native_path避开旧参数/结果的自动路径字段翻译,避免转换前被改写或成功值回流。

PTC 程序示例,假设 inputPath 是已经取得的完整路径值:

const resolved = await tools.gitbash_to_native_path({ msys_path: inputPath });
const fs = await import('node:fs/promises');
return await fs.readFile(resolved.native_path, 'utf8');

这不是绕过文件拒绝的方式;已发生拒绝必须停止。

7.2 gitbash_native

字段 契约
description 必填、非空、NUL-free
executable 必填 {kind:'path',value},可解析绝对 .exe;无 bare command
argv 必填 typed 数组;literal 原值,path 显式转换/规范化;允许空 literal
cwd 可选绝对 typed path;默认 agent workspace
entrypoint native 默认;已知解释器需显式 interpreter
stdoutEncoding/stderrEncoding utf8 默认,或 gbk/utf16le/raw;不支持 auto
errors replace 默认,strict opt-in
timeoutMs 正有限数,默认120000ms,上限600000ms
run_in_background 仅能力允许时声明;与显式 timeoutMs 同时给出会拒绝

Native typed path 不支持相对值、变量/home展开;需要时先通过显式 helper取得可用绝对值。Windows 启动字段/path argv规范化反斜杠;literal /all、/c 等不经过 MSYS。

拒绝未知字段、model env、path-list env、隐式脚本、.cmd/.bat。当前限制4096个argv及保守Windows command-line预算。已知解释器名称检查是防误门,不是二进制鉴定;重命名/custom exe可有自己的语言。

Exact argv 指验证过的 Core/CRT/Node 语义,不承诺任意 cmd/非CRT parser 的 quoting。

8. 编码与输出事实

只有已知 collect disposition {maxBytes,spill?:{maxBytes}} 转 raw pipe;未知/其他 disposition按原 provider契约委托。每 operation immutable config,stdout/stderr独立 decoder,只在 ingest解码。

  • UTF8默认宽容替换,保留BOM;strict显式。
  • Decoder能力在spawn前探测;unknown同流mixed选raw。
  • 原字节产物与normalized UTF8产物分开;raw无可靠文本承诺。
  • Reader为独立、非消费normalized UTF8 byte cursor;不是原编码byte游标,也不是Core Jobs全局游标。
  • handle.done保留真实provider outcome/error身份;decode/storage问题只记facts,不伪造命令未执行。
  • OutputCollector只使用公开push/snapshot/seal;不访问其私有spill字段。
字段 解释
sourceComplete 是否收到自然EOF;不能单独证明程序未被中止
complete 管线完整性;不承诺tail包含全文
lossy/reliableText 与尾缓存、解码、存储等损失合读,不是编码自动鉴定
aborted 取消/主动terminate/owner终止事实
artifact.complete/capReached/error 对该产物自身完整性、预算、存储错误判断
rawBytes/rawCursor 原流字节计数/游标
decodedUtf8Bytes/decodedCursor normalized UTF8计数/游标

Foreground DTO使用closed schemas;去undefined投影不放任unknown字段。无facts/投影失败是显式分支,不通过宽schema吞错。后台最终exit/facts进入现有Jobs文本source,不声称扩展Core Jobs结构化API。

9. 生命周期与预算

准备阶段workspace/scope/plugin mount/artifact callback受同一取消/有界期限控制,剩余预算交Core;后台/onExpiry:none只限制准备,已handoff producer不会被准备timer杀死。

operation-owned AbortController统一caller cancel、explicit kill、ownerdispose;先记录cause再terminate。正常settlement后释放scope不能反向污染已完成facts。

输出end/error/close/abort/provider failure分别收尾;默认250ms有界drain,不无限等后代持有管道。不保证所有输出在短drain窗口内到达,未完整必须如实标注。

默认两流raw+decoded总磁盘8MiB、自有payload16MiB;含保守tail/copy/scratch预留。不是OS/RSS、provider buffer、caller副本或跨调用硬quota。

trusted owner在真实policy/校验后创建自有临时目录,不从model cwd建产物目录。Adapter不创建目录、chmod、删除或授权;文件有限wx创建。完成产物保留供晚reader读取,无自动purge承诺。晚callback结果不续spawn,不武断删除可能仍被引用的目录;归trusted retention owner。

10. Jobs 与动态装配

复用registry.start/wait/read/kill/remove、processJob/processSources和owner/controller admission。Scope属于agent,不属于tool registration fiber;后台/promotion后卸载工具不提前销毁运行进程。

没有controller时明确拒绝,不以“admission失败后再运行前台”冒二次副作用风险。没有Jobs时为前台kill deadline;有Jobs时可timeout promotion。该差异需在正式用户体验验收中检查。

Windows own-bash agent scope挂两个companions,各自按 agent 创建注册模块。初始挂载、开关更新和 native Jobs 刷新共用注册入口:先注销自身注册,再检查当前 agent 的工具所有权;已有外部全局或同 agent 同名工具就让位。实际 Core 的 knownNames 包含隐藏工具,旧宿主回退 schemas 检查;检查失败也让位。外部所有者移除后,下次刷新可恢复。注册异常只记录日志,不阻断另一个 companion 的更新。两工具必须确认 apply 已执行;scope 就绪与实际注册成功分别报告,关闭或让位时不会报告注册成功。Bash/native 共用可选目录读取,有服务走官方 ensure(错误不降级),无服务走旧 policy.workspaceRoot ?? session.header.cwd 接缝。缺native executor/OutputCollector公开能力不撤bash/path。新工具不加入minimal持久终端通道,不改变root PowerShell、market patch或preset id。

11. 已发生的反证与修正

  1. 初版ownerdispose/direct kill虽quiet且无LATE,却错报completed/aborted:false/artifact.complete:true。独立固定sentinel反证后,operation cause与adapter terminate共同修正;正常cleanup反向用例确保不污染成功结果。
  2. trusted artifact callback初版可无限await;abort/deadline时0spawn但不返回。现准备阶段有界race,晚callback不恢复执行,保留资源责任明确。
  3. 初版facts空宽schema现closed DTO;跨模块termination枚举/三参callback曾不同步,已对齐并真实Core负向校验。
  4. 集成发现显式证据env未配置、路径夹具硬编码盘符/安装bootstrap;改test-only目录预载、动态盘符、宿主自身bootstrap,真实Node fs复跑通过。没有放宽产品断言掩盖失败。

详情见验证文档。失败观察用例退出0只表示复现成功,不能算修复通过。

12. 合并讨论 / 未覆盖

  • 接受 fail-closed,新增默认 true 的 volatile 开关,关闭恢复旧行为。
  • Controller 缺失保持明确拒绝,不静默改前台重复执行。
  • Artifact ownership/quota/retention 由插件层自管;跨调用 quota/purge 尚未实现,不宣称已验收。
  • 长期跟踪(不阻塞本 PR):Core 将来开放 native typed argv、逐流 encoding、closed DTO 等对应公开 API 时,遵循官方优先纪律整体切换并退役插件私有实现。
  • 同步上游:前置 PR #24 已合并;实验已 rebase 到上游 v0.39.4 的 main(v0.39.4 起 fastctxTools 默认 OFF、新增 ops_* 互操作面),继承正式 v0.39.4 的兼容与激活验证;单装工具面在 fastctxTools OFF 下 companion 注册检测不受影响(tests/runtime-preview.mjs「companions mount on the single-install face with fastctxTools OFF」锁死设计文档 §10 语义)。
  • 拆分评估:建议两步 review:① Bash fail-closed + 行 Config/UI/拒绝引导/回退;② native/path、逐流输出与可见性路由。唯一开关在第一步建立,第二步复用同一字段。当前保留完整 Draft/RFC,尚未另开子 PR。
  • 转正式的四项门槛:真实 Agent 自主选路、生产 GUI(非 preview)、维护者 Windows 真机全量验证、非 CRT 解释器矩阵抽测。四项齐后才谈 ready for review → release。
  • 真实Agent选工具评测、生产GUI/full apply、会话replay尚未验收。
  • 真restricted-token/ACL/IPC/VM正负权限、PTY/SSH、任意非CRT/解释器quoting尚未验收。
  • 真实disk exhaustion、吞吐/RSS峰值、跨任务DOS/自动purge尚未验收。
  • 若未来Core提供受限native adapter,应如何探测启用而非偷换mode?

当前结论:接口机制与确定性隔离用例可讨论;不能据此宣布普遍乱码解决、Windows沙箱恢复或正式发布就绪。