Repository navigation
fix: 安全审计加固 / Harden the permission gate and runner - #1
Open
hezhongtang wants to merge 4 commits into
Open
hezhongtang wants to merge 4 commits into
hezhongtang wants to merge 4 commits into
Conversation
外部安全审计 D4、D9-③ 在代码与 mock 上核实属实后的修复。 D4:runner 是从宿主代理里起的,环境里常有 ANTHROPIC_API_KEY、GITHUB_TOKEN 一类 凭据;zcode 子进程原样继承,执行端的 Bash 一条 env 就全看见,配上联网工具就能外发。 拉起子进程时按固定名单剔掉(不做白名单:HOME、PATH 漏一个就坏功能),不论它来自 本进程环境还是调用方的 opts.env——doctor 与闲时自检是把 process.env 整份传进来的, 只剔继承来的那一份会漏。没带过去的名字在 stderr 说一行,只有名字。 D9-③:去重表从不清理,对端一旦复用 requestId,上一回合缓存的放行会原样答给新请求, 处理器(闸门)根本不跑。mock 复现:第二回合换了命令、同一个 requestId,旧实现直接 回 allow。现在 Session.send 开头清掉已出结果的条目。没有 requestId 的退路键从 「方法|会话」改成「方法 + 参数全文」:同会话里第二个无 requestId 的审批请求不再并进 第一个、拿到它的放行;重发的参数一字不差,仍落进同一键,处理器不会被重发反复叫起。 另:events.jsonl 与所在目录新建时只给当前用户(审计 D5 落在协议层的部分)。 mock 加三个剧本字段:reportEnv、serverRequests[].omitRequestId、permission.requestId。 用例 728 → 731。 Co-Authored-By: Claude Opus 5.5 <[email protected]>
外部安全审计 D9-① 核实属实:挂起回显把工具名、理由原样打到终端,执行端在里面夹一段 ANSI/OSC 转义就能清行、回车改写人正在看的那行审批、改窗口标题。回复原文、流式行、 文件名摘要、zcode 报错原文同样是执行端可控的文本,打印点有几十处。 逐处过滤迟早漏一处,所以在入口把 stdout / stderr 的写出口包一层:C0(换行、制表除外)、 DEL、C1(8 位的 CSI/OSC,JSON.stringify 不转义它们)、双向排版控制符,一律换成字面的 \uXXXX——内容不丢,人能看出这里被塞了东西。\r\n 收成 \n,落单的 \r 照样转义。 --json 的含义不变:这些字符只会出现在 JSON 字符串里,\uXXXX 在那里是合法转义, 解析回来还是原字符。runner.log 走的是同一个入口,一并中和。 拦不了的:模型回复里自己写一行「send: done」。回复原文按原样分行打印是定下来的做法。 用例 731 → 736(纯函数与写出口包装;走真实 CLI 的两条随下一个提交进 run.test)。 Co-Authored-By: Claude Opus 5.5 <[email protected]>
外部安全审计 D1、D2、D3 及 D5、D6、D8、D9-②、D9-④ 逐条在代码与本机上核实后的修复。 每条先补失败用例再改;新加的检查失败方向都是转人工,没有哪条 ask 路径被改成自动放行。 D1(越界红线可绕):原先 path.resolve 之后再 realpathSync,<执行副本>/link/../x 先被 词法折叠成看着在界内的路径,实际写入落在链接目标的上一级——Node 的 realpathSync 自己 也是先折叠。改成从根逐段解析(符号链接就地展开,.. 退到真实父目录,末段的悬空链接也 跟),原串与词法归一后的串各算一遍,任一越界即命中。成环、把文件当目录穿这类判不了 落点的,以及写类工具(含 3.14.4 的保留名 ApplyPatch)拿不出可判路径的,不再当界内放过。 D2(执行端能自己批自己):执行端与 runner 是同一个用户,写 answer.json、跑 zcode-executor approve,文件权限与属主校验都挡不住。新增机械红线 self-modify-approval: 操作指向本工具的数据目录或调本工具的 CLI,直接转人工,不交给模型判。审计说「匹配数据 目录前缀不会误伤」在这里不成立——默认的执行副本就在 <数据目录>/worktrees 下——所以放行 worktrees/ 与本会话的 cwd,CLI 只认名字后面跟子命令。只认直白写法;拼变量、先写脚本 再跑认不出来,同一个用户之下没有根治(decisions D23)。 D3(任务单可事后改写):审批把任务单当「用户说过的话」,却在每次审批时现读执行副本里 那份执行端改得动的文件。入队时留快照(runs/<id>/tasks/<sha256>.md),审批只按事件里的 taskSha256 读快照并核对哈希;没有快照的旧事件不再作依据(只会更常转人工)。闲时投递 先取号后入队,所以在取号之前先留一份,任务单读不了不白用一次号。 其余:runs/ 树 0700、落盘 0600,pending.json 按值抹掉 runner 手里的密钥(D5;不做 启发式脱敏,人要靠原文决定放不放);原子写的临时名加随机段并排他创建(D9-②); 审批探针的 git 关掉 fsmonitor、钩子、外部 diff、textconv,并把仓库配置里的 filter 驱动逐个置空(D6;filter 这条审计没提,是核实时在 git 2.54.0 上实测出来的); 快筛只认独立成词且唯一的 Y,「They are…」里的 y 不再算放行(D8)。 没改的与理由见 decisions D23:慢判提示词不套启发式脱敏(D7)、Write 正文仍进快筛 (D8 后半)。 用例 736 → 765。 Co-Authored-By: Claude Opus 5.5 <[email protected]>
同步已落地的安全加固行为、术语与验收数量。按本机 ZCode 3.14.4 的源码核对联网工具的注册与屏蔽,明确工具禁用和系统断网的边界,避免把局部加固写成完整隔离。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
中文
符号链接后跟
..时,原来的路径检查先做词法折叠,可能把实际落在执行副本之外的操作判成界内。模型审批又会读取执行端可修改的任务单原文件,使审批依据能在投递后改变。本 PR 按安全审计加固这些路径,并保护闸门的状态和应答通道。改动
..,同时检查原路径与词法归一路径;写类工具没有可判路径或解析失败时转人工。直接触碰本工具管控面、调用本工具 CLI 的 Bash/js 操作也转人工,保留默认worktrees/与本会话执行副本的例外。runs/树使用 0700、文件使用 0600;挂起内容按已知密钥值脱敏;原子写使用随机临时名和排他创建。--deny,明确禁用工具的联网边界。模型审批仍只产出“放行”或“转人工”;人工拒绝路径与仅允许一次的合同保持不变。
验证
npm test,765/765 通过,包括文档版本同步检查。使用 mock,不消耗 ZCode 额度。git diff --check通过。main(5c728fe)的git merge-tree检查无冲突。已知边界
执行端与 runner 仍是同一个系统用户。自保检查只识别直白写法,不提供系统级隔离。
--deny "WebFetch WebSearch"只移除指定联网工具,Bash、js 和 MCP 工具仍可能联网。硬链接越界与子模块自身的 git filter 配置等限制已记录在 D23,未在本 PR 扩大处理范围。联合参与
本次工作由 Opus5.5、GPT-Sol-6.1、GLM5.3 联合参与修复。
English
When a symbolic link is followed by
.., the previous path check normalized the path before resolving links and could classify an operation outside the worktree as inside it. Model review also read the mutable task file, allowing its authorization basis to change after a send. This PR hardens these paths following the security audit and protects the gate's state and answer channel.Changes
..component by component, checking both the original and normalized paths. Missing write targets and resolution failures escalate to a human. Direct Bash/js references to the control plane or executor CLI also escalate, with exceptions for the defaultworktrees/root and the current session's worktree.--deny, documenting the network-access boundary.Model review continues to return only allow or ask. Human denial and the allow-once contract remain unchanged.
Validation
npm test, 765/765 passing, including the documentation-version check. All tests use mocks and spend no ZCode tokens.git diff --checkpassed.git merge-treefound no conflicts with upstreammainat5c728fe.Known boundaries
The executor and runner still share an OS user. Gate protection recognizes plain spellings and does not provide OS isolation.
--deny "WebFetch WebSearch"removes the named tools; Bash, js and MCP tools may still access the network. Hard-link escapes and git filter configuration inside submodules remain documented limitations in D23.Joint participation
This work was jointly carried out by Opus5.5, GPT-Sol-6.1, and GLM5.3.