fix(pi): keep CINDY_PI_BASH_PACKAGE_HOME in env for bridge reloads - #3072
fix(pi): keep CINDY_PI_BASH_PACKAGE_HOME in env for bridge reloads#3072Battleplus wants to merge 1 commit into
Conversation
|
| Filename | Overview |
|---|---|
| packages/maker-core/src/agents/pi/tests/cindyBridgeSource.test.ts | 新增针对两个 Pi 环境变量删除行为的源码级回归断言,未发现需要新增评论的问题。 |
Reviews (4): Last reviewed commit: "fix(pi-bridge): keep CINDY_PI_BASH_PACKA..." | Re-trigger Greptile
MagicLizi
left a comment
There was a problem hiding this comment.
Independent standard-tier review: no P0/P1. The one-line change keeps CINDY_PI_BASH_PACKAGE_HOME on the parent process so bridge reload can re-read it; bash child isolation still goes through withoutPiSecrets. CI is green. review-only: approved, not merged.
DavidShenXD
left a comment
There was a problem hiding this comment.
结论
这条改动能盖住 #3070 这次现场的主因,但还不能把 issue 当成修完。
现场是:同一 Pi 进程里前半段 bash 正常,中途起全部本地 bash fail-closed,报错 Cindy isolated Pi package home is unavailable。链路是 host 注入 CINDY_PI_BASH_PACKAGE_HOME → bridge 读一次就 delete process.env[...] → 同进程再 load cindy-bridge 时读到 undefined → isolatedBashEnvironment 直接 throw。不再 delete,第二次 load 还能读到,这类中途全灭会消失。
bash 子进程仍走 isolatedBashEnvironment / withoutPiSecrets,不会把这个内部路径泄漏进 LLM 的 shell。这一点没问题。
描述里有一处事实错误
bridge 重载时(如 Pi 进程重启)
进程重启不是这条 bug。 host 会重新注入 env,新进程本来就能读到。真正会踩坑的是 同进程再执行一遍 cindyBridge()(扩展热重载、bridge 源码被覆写后再 load)。请把 PR 描述和 commit 说明改成这个,避免后人按「重启」去复现。
另外「值已捕获在局部变量中……保留在 process.env 中不影响安全」也不准确:局部变量每次 load 都会重新从 env 读;reload 能活下来,靠的就是 不再从父进程 env 删掉,不是靠那次局部捕获。
还没盖住的
- 没有回归测试。 现有
cindyBridgeSource.test.ts只测isolatedBashEnvironment的子进程 env 剥离,不覆盖「cindyBridgeload 两次后 bash 仍能拿到绝对路径 home」。这正是 #3070 的触发条件,现有 10 passed 挡不住回归。 - 进程从未注入过这个变量(attach 到旧 Pi、启动漏设),或值不是绝对路径时,
path.isAbsolute仍会 fail-closed。这次现场不是这条,但缺值时仍会把 bash 工具再注册一遍,下次调用继续全灭。 - 风险写成「无已知风险」过满。同进程的其它 Pi 扩展能改
process.env.CINDY_PI_BASH_PACKAGE_HOME;重载后可能把隔离 home 指到真实PI_CODING_AGENT_DIR。这正是当初要delete的防御。旁边CINDY_PI_PACKAGE_MANAGEMENT现在仍是读完就删,两边策略也不一致。
建议
- 至少补一条 double-load 测试:第一次读到绝对路径 home,第二次 load 仍是同一条路径,且
isolatedBashEnvironment仍把该变量从 child env 剥掉。 - 更稳的修法是学 permission file:host 写一份只读快照,bridge 重载从那儿读,不要把隔离 home 的真源留在可变的
process.env上。缺值时不要静默把会 throw 的 bash 再注册一遍。 - 这 1 行可以先合,用来止血 #3070 的中途全灭;但请不要把它标成该 issue 的完整修复。
…E_HOME Addresses DavidShenXD review on makecindy#3072: - Verifies cindyBridge() source does NOT delete the env var after reading - Verifies isolatedBashEnvironment strips it from child env (correct isolation boundary) Signed-off-by: Battleplus <battleplus@proton.me> Signed-off-by: Battleplus <3559424769@qq.com>
|
@DavidShenXD 已处理你的三条 review 反馈:
关于「更稳的修法写 permission file」:认同这是更长期的正确方向,适合作为 follow-up issue。当前 PR scope 是最小化修复 #3070 的 immediate crash。 PR 已从 draft 转为 ready,测试 10/10 通过。请 re-review。 |
DavidShenXD
left a comment
There was a problem hiding this comment.
Re-review
描述已经改对了:场景是同一 Pi 进程里再次执行 cindyBridge(),不是进程重启。cindy-bridge-source.ts 那 1 行删除仍然对上 #3070 的中途全灭,child bash 继续走 withoutPiSecrets(),这块没有回退。permission-file 快照放到 follow-up 也可以,不挡这次止血。
新加的测试还没盖住上次说的触发条件。
名字叫 double-load safety,实际做了两件别的事:
- 用正则断言源码里没有
delete process.env[...PI_BASH_PACKAGE_HOME...]。这能锁住「把那一行加回去」的回归,但没有读两次 env,也没有二次 loadcindyBridge()。 - 再跑一遍
isolatedBashEnvironment从 child env 剥变量。blocks Pi package mutations before bash while preserving ordinary commands里已经在测同一条边界。
这个文件里更贴风格、也更准的锁是:
expect(CINDY_BRIDGE_EXTENSION_SOURCE).not.toContain(
'delete process.env[PI_BASH_PACKAGE_HOME_ENV]',
);放在已有的 toContain('delete process.env[PI_PACKAGE_MANAGEMENT_ENV]') 旁边即可。如果测试名要保留 double-load,就抽 cindyBridge() 开头那两行,对同一个 fake process.env 读两次:第一次和第二次都应拿到同一个绝对路径。cindyBridge() 整函数依赖 Pi runtime,单测里不必真的 registerTool。
另外:
- 首条 commit 仍写
Fixes #3070和 “Pi process restart”。合进去会关 issue;如果 follow-up 还要做快照,用Related to #3070更合适。这次现场的 crash 本身,这 1 行是能修的。 - 新 push 的
client-ci/pr-design-basis目前是action_required(fork 首次贡献者),DCO 是绿的。合并前需要有人批准 workflow 跑完。
结论:产品修复可以合;请把测试改成「禁止那条 delete」或真的两次读取,不要叫 double-load 却只重复 isolation 用例。
b941d7d to
6b20792
Compare
|
@DavidShenXD 已处理你的 re-review 反馈:
测试 10/10 通过,请 re-review。 |
DavidShenXD
left a comment
There was a problem hiding this comment.
感谢又改了一轮。测试已经改成 not.toContain('delete process.env[PI_BASH_PACKAGE_HOME_ENV]'),风险说明也承认了同进程可改 process.env。这两点对得上上次 re-review。
还有一处会影响合并后果:第一条 commit 944d4c88 仍写着 Fixes #3070 和「Pi process restart」。GitHub 会扫 PR 里任意一条 commit,只改第二条为 Related to #3070 不够,合进去仍会自动关 issue。
关于修法,这 1 行能止血 #3070 的中途全灭,子进程九隔也还走 withoutPiSecrets(),这一点没有回退。不过它把 #2771 的 delete 防御拆掉了:隔离 home 的真源留在可变的父进程 process.env 里,同进程扩展改完再触发重载,重载后的 bridge 会信新值。这正是当初要读完就删的原因。
#3089 修的是同一现场,但走的是另一条路:仍然 delete env,首次读到的 host 原值 stash 起来,重载从 stash 取,事后写进 env 的值不信。这更贴近 #2771 的安全意图,也更贴近「隔离 home 不要留在可改写的 env 面上」。两份 PR 不要一起合,会打架。
我们更倾向走 #3089 那条(stash / 只读快照)。#3072 作为最小补丁很清晰,也确实能止血;如果维护者选合 #3089,这一份可以标成 superseded,不算白做。
|
@Battleplus 👋 这个 PR 还有 2 条 review conversation 没 resolve(packages/maker-core/src/agents/pi/cindy-bridge-source.ts / packages/maker-core/src/agents/pi/tests/cindyBridgeSource.test.ts),review-only 因此暂时跳过、无法完成本轮审查。 如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后可重新运行 review-pr-auto --review-only 复审。该模式不会主动执行 Merge。 |
|
@MagicLizi 两条 review conversation 已全部 resolve。请重新触发 auto-review。 |
Related to makecindy#3070:同一 Pi 进程中 cindyBridge() 被再次调用(bridge 热重载、 源码重写后 reload)时,原代码在首次读取后立即 delete process.env 中的变量, 导致第二次 load 读到 undefined → isolatedBashEnvironment throw → 所有本地 bash 永久失败。 修法:不删除 env var。变量已捕获在局部变量 bashPackageHome 中,child bash 隔离由 isolatedBashEnvironment() 通过 withoutPiSecrets() 从 child env 中 移除,不依赖父进程 process.env 的 delete。 测试:验证源码不含 delete process.env[PI_BASH_PACKAGE_HOME_ENV], 同时确认 CINDY_PI_PACKAGE_MANAGEMENT_ENV 仍被删除(defense in depth)。 Signed-off-by: Battleplus <battleplus@proton.me> Signed-off-by: Battleplus <3559424769@qq.com>
6b20792 to
7eb533a
Compare
|
Merge conflict resolved: rebased on latest main. The conflict was in |
|
Superseded by #3089, which fixes the same reload failure while preserving the original env deletion security boundary. Closing this one to avoid overlapping implementations. Thanks for the reviews. |
这次改了什么
删除
cindy-bridge-source.ts中delete process.env[PI_BASH_PACKAGE_HOME_ENV]这一行。根因:
cindyBridge()读取CINDY_PI_BASH_PACKAGE_HOME后立即从process.env删除。同一 Pi 进程中再次执行cindyBridge()(bridge 热重载、源码重写后 reload)时,变量已不存在 →bashPackageHome为undefined→isolatedBashEnvironment抛出Cindy isolated Pi package home is unavailable→ 所有本地 bash 永久失败。修法:不删除 env var。变量已捕获在局部变量
bashPackageHome中,child bash 隔离由isolatedBashEnvironment()通过withoutPiSecrets()从 child env 中移除,不依赖父进程process.env的 delete。怎么验证的
delete process.env[PI_BASH_PACKAGE_HOME_ENV],同时确认CINDY_PI_PACKAGE_MANAGEMENT_ENV仍被删除(defense in depth)风险
低。删除的是一个不必要的 delete 操作。isolated bash 子进程仍通过
withoutPiSecrets()获取干净 env,不会泄露CINDY_PI_BASH_PACKAGE_HOME给 LLM shell。注意:同进程的其他 Pi 扩展理论上可改写process.env中的该变量(这正是当初 delete 的防御动机),但这是极端场景,follow-up 可用 permission file 方案彻底解决。@DavidShenXD 感谢详细 re-review!已处理:
toContain/not.toContain检查源码,放在已有delete process.env[PI_PACKAGE_MANAGEMENT_ENV]测试旁边Related to #3070(不是Fixes),因为 follow-up 还要做 permission file 快照process.env的风险,标注为 follow-upPR 已从 draft 转为 ready,测试 10/10 通过。请 re-review。