Skip to content

fix(pi): bridge 重载后恢复一次性启动 env 的 bash 隔离 home - #3089

Merged
MagicLizi merged 3 commits into
mainfrom
cindy/earnest-leakey
Aug 21, 2026
Merged

fix(pi): bridge 重载后恢复一次性启动 env 的 bash 隔离 home#3089
MagicLizi merged 3 commits into
mainfrom
cindy/earnest-leakey

Conversation

@DavidShenXD

Copy link
Copy Markdown
Collaborator

这次改了什么

摘要

修复 #3070:Pi 会话中途所有 bash 永久失败,报 Cindy isolated Pi package home is unavailable

根因:cindy-bridge 首次加载时读取 host 注入的 CINDY_PI_BASH_PACKAGE_HOME 后立即从 process.env 删除(#2771 引入的防御,防止进程内代码改写)。但 Pi 进程内扩展重载会重新执行 bridge 文件:第二次加载读不到已被删除的 env,闭包里的 bashPackageHome 变成 undefined,此后每次 bash 都在 isolatedBashEnvironment 处 fail-closed。

修法:新增 takeOneShotEnv 统一存取一次性启动 env——首次加载读删并 stash 进 globalThis(扩展重载与首次加载共享同一 realm),重载实例从 stash 取回 host 注入的原始值。stash 已有记录而 env 又出现值时,视为进程内代码事后写入,忽略并再次删除(不信任可改写的 env 面,保留原防御)。CINDY_PI_PACKAGE_MANAGEMENT token 同法处理,重载后 cindy_pi_extension 工具不再静默消失。stash 也拿不到时仍返回 undefined,下游保持原 fail-closed,不猜外来 runtime 的路径。

#3072 的关系:修同一问题,但 #3072 直接不删 env,把专用变量永久留在 process.env 里,进程内代码(含用户可装的第三方 Pi 扩展)可改写且重载的 bridge 会静默信任改写值;本 PR 保留删除防御,值经不可由 env 改写的 stash 传递,并补齐回归测试。

变更类型

  • fix 缺陷修复

范围

  • 关联 Issue / 需求:Pi 会话中途所有本地 bash 失败:isolated Pi package home is unavailable #3070
  • 本 PR 包含:cindy-bridge-source.ts 新增 takeOneShotEnv(stash 存取一次性启动 env)并让 bashPackageHome / piPackageManagementToken 走该路径;cindyBridgeSource.test.ts 补回归测试
  • 明确不包含:隔离目录丢失后的自动重建、host 侧 spawn env 逻辑改动、SECRET_ENV_NAMES 剥离面调整
  • 用户可见变化:Pi 会话中途 bridge 重载后 bash 不再永久失败,cindy_pi_extension 工具重载后仍可用
  • 是否存在 breaking change:无

UI 变化

不涉及:仅 Pi 进程内扩展逻辑,无任何 UI 路径改动。

怎么验证的

自动验证

pnpm --filter @cindy/maker-core run --if-present typecheck
结果:通过

pnpm test:unit:related
结果:packages/maker-core unit PASS(含新增回归用例,15 tests | 4 skipped);
     packages/orca-workflow / lizi-mcps PASS;apps/desktop 全量见下

pnpm --filter desktop exec vitest run <desktop unit 门禁范围>
结果:2040/2041 文件通过。唯一失败为
     pi-package-store-security.test.ts 的 symlink 用例,本机 Windows
     组策略禁止无特权创建 symlink(裸测 fs.symlinkSync 即 EPERM),
     在干净 main 上同样失败、CI(Windows/Linux)上通过,与本次改动无关。

pnpm check:dco
结果:1 commit 通过 DCO 校验

新增回归测试覆盖:同一进程内 double-load 仍取回原始值;首次加载后向 env 写入攻击值不影响重载(取 stash 而非 env);非 Cindy 初始化的进程返回 undefined 保持 fail-closed;多键互不干扰;入口结构断言(裸 delete 只存在于 helper 内)。

手工验证

在隔离沙盒 dev(--isolated=@worktree,CN 区,commit 05264ab + 本修复)实测:开 Pi 会话跑 git --version 正常;关闭会话后重新打开(resume)再跑 git --version,正常返回——修复前该路径报 Cindy isolated Pi package home is unavailable 且同会话内重试永久失败。

未执行的验证

真实 Pi 进程内扩展重载(非 resume 路径)无稳定本地复现手段,由上述 resume 路径 + 单测的 double-load 用例覆盖同一机理(重载与首次加载共享 realm,env 已被首次加载删除)。

风险

风险分类

  • 无已知风险
  • SQLite / migration
  • system prompt
  • 权限 / 安全 / 用户数据
  • 存量插件兼容(批准状态 / 指纹 / manifest 校验 / 安装布局 / 包格式)
  • 原生层 / fingerprint / OTA
  • 跨平台差异
  • 其他:

影响与回滚

影响范围:Pi bash 隔离与 Pi 扩展管理工具的一次性 env 生命周期。安全面上,值存于 globalThis 与闭包同为进程内存,不比原实现(值留在首次加载闭包里)多暴露;bash 子进程 spawn 边界照旧剥离该变量(SECRET_ENV_NAMES 不变)。事后写入 env 的值一律不信任,保留并强化了原 delete 防御。远端会话:bridge 源码字节进入 CINDY_PI_EXTENSION_BUNDLE_HASH,字节变化本就要求 daemon restart,不影响 attach 语义。

移动端冷更分析:本次改动不触及 apps/mobile 任何 fingerprint 输入(app.json / app.config.js / eas.json / package.json / plugins / modules),仅改 packages/maker-core 的 Pi 扩展源码,不触发冷更。

回滚 / 降级方式:revert 本 PR 即恢复旧行为(bridge 加载后删除 env、重载后 bash fail-closed)。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s,见 DCO
  • UI 改动已在「UI 变化」注明引用的设计规范章节(不涉及 UI 则跳过)
  • 未提交凭证、令牌或授权文件
  • 已补充必要文档(无需文档变更:行为对用户透明,代码注释已写清机理)
  • 已确认测试结果或说明未执行原因

#3070:cindy-bridge 首次加载时读取 CINDY_PI_BASH_PACKAGE_HOME 后即从
process.env 删除;Pi 进程内扩展重载会重新执行 bridge 文件,第二次加载
读不到已删除的 env,bashPackageHome 变 undefined,此后每次 bash 都在
isolatedBashEnvironment 处 fail-closed,报 Cindy isolated Pi package
home is unavailable。

改为 takeOneShotEnv 统一存取:首次加载读删并 stash 进 globalThis
(重载与首次加载共享同一 realm),重载实例从 stash 取回 host 注入的
原始值;stash 已有记录而 env 又出现值时视为进程内代码事后写入,忽略
并再次删除。CINDY_PI_PACKAGE_MANAGEMENT token 同法处理,重载后
cindy_pi_extension 工具不再静默消失。stash 拿不到时仍返回 undefined
保持原 fail-closed,不猜外来 runtime 的路径。

Signed-off-by: DavidShen <david@xd.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a233478bfb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/maker-core/src/agents/pi/cindy-bridge-source.ts Outdated
@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown

Greptile Summary

本 PR 修复 Pi bridge 重载后丢失一次性 bash 隔离 home 的问题,同时避免将包管理 bearer token 暴露到全局 stash。

  • 通过不可写、不可配置的 globalThis 属性保存 bash package home,并在重载时结合 PI_CODING_AGENT_DIR 派生值进行校验
  • 保持一次性环境变量读后删除及验证失败时 fail-closed 的行为
  • 增加重载恢复、环境变量篡改、全局属性形态和非 Cindy 初始化场景的回归测试

Confidence Score: 5/5

当前未发现仍需阻止合并的故障,原线程报告的 stash 事后篡改问题已修复,PR 看起来可以安全合并。

当前没有遗留的阻塞性故障。

Important Files Changed

Filename Overview
packages/maker-core/src/agents/pi/cindy-bridge-source.ts 新增不可变的跨重载 bash package home stash、派生路径复核和 fail-closed 处理;此前报告的全局 stash 事后篡改路径已被封闭。
packages/maker-core/src/agents/pi/tests/cindyBridgeSource.test.ts 新增覆盖首次加载、重载恢复、env 篡改、canary 失配、恶意属性形态及缺失初始化的回归测试。

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[首次加载 bridge] --> B[读取并删除 CINDY_PI_BASH_PACKAGE_HOME]
  B --> C[以 non-writable / non-configurable 属性写入 globalThis]
  C --> D[使用隔离 home 启动 bash]
  E[bridge 重载] --> F[读取并校验 stash descriptor]
  F --> G[由 PI_CODING_AGENT_DIR 派生预期路径]
  G --> H{stash 与派生路径一致?}
  H -->|是| D
  H -->|否| I[返回 undefined 并 fail-closed]
Loading

Reviews (6): Last reviewed commit: "fix(pi): bash 隔离 home stash 防篡改并经 PI_COD..." | Re-trigger Greptile

review P1:CINDY_PI_PACKAGE_MANAGEMENT 是 host 签发的 bearer token,
而本进程内会加载用户安装的第三方托管扩展,它们与 bridge 共享
globalThis —— 把 token stash 进 globalThis 等于暴露给任意托管代码,
比留在首次加载闭包里更宽。

token 恢复原语义:读一次即删、仅闭包持有,重载后 cindy_pi_extension
工具退场(bash 直装仍被拦,新会话可再拿到工具,可接受)。
bash-package-home 是路径而非凭证,且本就经 PI_CODING_AGENT_DIR 进
每个 bash 子进程 env,保留 stash 不新增暴露面。

Signed-off-by: DavidShen <david@xd.com>
@DavidShenXD

Copy link
Copy Markdown
Collaborator Author

反馈已处理

已处理:

  • chatgpt-codex-connector 的 P1「Keep the package-management bearer out of globalThis」:核验后确认成立——CINDY_PI_PACKAGE_MANAGEMENT 是 host 签发的 bearer token,同进程加载的第三方托管扩展与 bridge 共享 globalThis,stash 进去等于把凭证暴露给任意托管代码。已在 discussion_r3819491448 回复并 resolve。

变更:

  • cindy-bridge-source.ts:token 恢复原语义(入口读一次即 delete process.env[...]、仅闭包持有,不进 stash);CINDY_PI_BASH_PACKAGE_HOME(路径而非凭证)保留 stash,Pi 会话中途所有本地 bash 失败:isolated Pi package home is unavailable #3070 修复语义不变;注释写明「只 stash 路径,不 stash 凭证」的边界。
  • cindyBridgeSource.test.ts:回归用例改名并新增断言——token 走裸读删且 delete 在入口函数内、helper 区段与入口均不出现 takeOneShotEnv(PI_PACKAGE_MANAGEMENT_ENV)
  • commit 5c4bf4b86,已 push。

验证:

  • pnpm --filter @cindy/maker-core run --if-present typecheck:通过。
  • pnpm vitest run src/agents/pi/__tests__/cindyBridgeSource.test.ts:15 tests | 4 skipped 全通过。
  • pnpm test:unit:related:maker-core / orca-workflow / lizi-mcps 全 PASS;apps/desktop 唯一失败仍是本机 Windows 组策略禁止无特权 symlink 的存量问题(pi-package-store-security symlink 用例,干净 main 同样失败、CI 通过,与本改动无关)。
  • pnpm check:dco:2 commits 全部通过。

备注:

  • 重载后 cindy_pi_extension 工具会退场(回到本 PR 之前的行为)——bash 直装仍被静态拦截,新开会话即可再拿到工具;如需「重载后工具仍在」,需另做 bridge 私有的 reload-stable 通道,不在本 PR 范围。
  • CI 状态未等待,以 Actions 页面为准。

Comment thread packages/maker-core/src/agents/pi/cindy-bridge-source.ts Outdated
@DavidShenXD
DavidShenXD marked this pull request as draft August 20, 2026 07:41
@DavidShenXD
DavidShenXD marked this pull request as ready for review August 20, 2026 07:46
@DavidShenXD
DavidShenXD marked this pull request as draft August 20, 2026 07:49
greptile P1:plain object stash 可被同进程的第三方托管扩展改写 ——
bridge 重载后会信任被污染的值,把攻击者目录当 PI_CODING_AGENT_DIR 传给
bash 与子代理。

修法:
- stash 改为 defineProperty(writable:false, configurable:false),语言
  层面封死事后改写/替换/删除;读取校验属性形态,可写可配置的属性
  (含攻击者抢跑预置的)一律不信任。
- 重载取值加双重验证:stash 必须等于 path.posix.join(PI_CODING_AGENT_DIR,
  'bash-package-home') —— 与 host 侧 joinRemotePosixPath 派生式逐字一致。
  事后改写 PI_CODING_AGENT_DIR 会让二者失配 → fail-closed(该 env 常驻
  可写,顺带变成 canary)。
- env 值在 stash 建立后再次出现一律删除并忽略;验证失败或 stash 缺失
  返回 undefined,下游 isolatedBashEnvironment 保持原 fail-closed。

Signed-off-by: DavidShen <david@xd.com>
@DavidShenXD

Copy link
Copy Markdown
Collaborator Author

反馈已处理

已处理:

  • Greptile Review 失败对应的 P1 行评「全局 stash 可篡改隔离路径」:核验成立——plain object stash 可被同进程的第三方托管扩展改写,重载后 bridge 会信任被污染值并把攻击者目录当 PI_CODING_AGENT_DIR 传给 bash 与子代理。已在 discussion_r3819689541 回复并 resolve。

变更:

  • cindy-bridge-source.ts(commit 578e392d8):stash 改为 Object.defineProperty(writable: false, configurable: false) 防篡改属性,读取校验属性形态(可写/可配置的一律不信任);重载取值加双重验证——stash 必须等于 path.posix.join(PI_CODING_AGENT_DIR, 'bash-package-home')(与 host 侧派生式逐字一致),失配 fail-closed;env 事后写入仍删除并忽略。
  • cindyBridgeSource.test.ts:回归用例扩展——重载取回、env 事后写入忽略、PI_CODING_AGENT_DIR 被改写后 fail-closed、攻击者形态 plain stash 不被信任、非 Cindy 进程 fail-closed、stash 属性形态断言。

验证:

  • pnpm vitest run src/agents/pi/__tests__/cindyBridgeSource.test.ts:15 tests | 4 skipped 全通过。
  • pnpm --filter @cindy/maker-core run --if-present typecheck:通过。
  • pnpm test:unit:related:maker-core / orca-workflow / lizi-mcps 全 PASS;apps/desktop 唯一失败仍是本机 Windows 组策略禁止无特权 symlink 的存量问题(pi-package-store-security symlink 用例,干净 main 同样失败、CI 通过,与本改动无关)。
  • pnpm check:dco:3 commits 全部通过。
  • 已 push 到 PR head 分支。

备注:

  • Greptile 本轮 re-review 由新 push(578e392d8)自动触发,结果以 Actions 页面为准。

@DavidShenXD
DavidShenXD marked this pull request as ready for review August 20, 2026 08:16
@DavidShenXD
DavidShenXD marked this pull request as draft August 20, 2026 08:23
@DavidShenXD
DavidShenXD marked this pull request as ready for review August 20, 2026 08:24
@DavidShenXD
DavidShenXD marked this pull request as draft August 20, 2026 08:36
@DavidShenXD
DavidShenXD marked this pull request as ready for review August 20, 2026 08:39
@MagicLizi MagicLizi added the touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) label Aug 20, 2026

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查通过:bridge 重载后 bash 隔离 home 经防篡改 stash 恢复,token 不进 stash;回归覆盖重载路径。CI 全绿。review-only 本轮不合并。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bash 隔离 home 用防篡改 stash 抗扩展重载,token 仍只进闭包。测试覆盖重载、canary 失配和 hostile stash。没有 P0/P1。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查通过,没有 P0/P1。bridge 重载后 bash 隔离 home 经 stash 与 PI_CODING_AGENT_DIR 双重验证才放行;包管理 token 不进 globalThis。CI 全绿。review-only 本轮不合并。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查通过:无 P0/P1。bridge 重载后 bash 隔离 home 的 stash/派生与 Host spawnEnv 一致,token 仍仅闭包持有;review-only 本轮不合并。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查通过:bash 隔离 home 用防篡改 stash + canary 抗扩展重绑,token 不进 globalThis。review-only,未合并。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查通过,无 P0/P1。bridge 重载后 bash 隔离 home 走密封 stash,缺路径仍 fail-closed。review-only 本轮不合并。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

独立审查无 P0/P1;CI 全绿。review-only 本轮不合并。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review passed: fix correctly stashes and re-derives bash package home on bridge reload. Security invariants preserved (SECRET_ENV_NAMES still strips sensitive values). Fail-closed behavior maintained when paths unavailable. Tests cover the key scenarios.

@MagicLizi
MagicLizi merged commit 8116c39 into main Aug 21, 2026
22 checks passed
@MagicLizi
MagicLizi deleted the cindy/earnest-leakey branch August 21, 2026 01:40
pull Bot pushed a commit to ppvia/cindy that referenced this pull request Aug 21, 2026
) (makecindy#3165)

* fix(pi): 修复 subagent bash 因父 bridge 删除 env 而 fail-closed (makecindy#3132)

父 bridge 在初始化时消费并从 process.env 删除 CINDY_PI_BASH_PACKAGE_HOME;
subagent 子进程通过 Object.assign({}, process.env) 构造 childEnv 时已
拿不到该变量,导致子进程里的 bridge 无法解析 bash 隔离 home,抛出
"Cindy isolated Pi package home is unavailable",subagent 内 bash 100% 必现。

修复两处:

1. cindy-bridge resolveBashPackageHome:env 与 stash 均不可用时(正是
   subagent 子进程路径),从 PI_CODING_AGENT_DIR 派生
   path.posix.join(configHome, 'bash-package-home');非绝对路径仍
   fail-closed。公式与 makecindy#3089 stash 校验一致。

2. cindy-subagent runTask:spawn 前,configHome 为绝对路径时写回
   childEnv[CINDY_PI_BASH_PACKAGE_HOME] = join(configHome, 'bash-package-home'),
   让子 bridge 首次加载时能读到该变量(子 bridge 仍会在加载时删除它)。

不把 subagent 白名单改成含 bash(产品:仍是只读)。

Signed-off-by: Dash <dashhuang@gmail.com>

* test(pi): 补 subagent childEnv 执行级测试(响应 greptile P2 makecindy#3165)

结构断言只检查源码文本顺序,无法防止 isAbsolute 分支或变量
绑定的控制流回归。新增 loadSubagentChildEnvHelper 以 runInNewContext
执行真实 childEnv 构造逻辑,断言:
- 绝对路径时 CINDY_PI_BASH_PACKAGE_HOME 被正确设置
- 相对路径 fail-closed(不设置)
- MCP bridge / remote MCP secret 仍被剥离

Signed-off-by: Dash <dashhuang@gmail.com>

* fix(pi): 子进程 bash-package-home 改用 path.posix.join(响应 Codex P1 makecindy#3165)

bridge derivedBashPackageHome 与 stash 校验都用 path.posix.join;
子进程 childEnv 写回若用 path.join(Windows 上产生反斜杠),
子 bridge reload 时 stash 与 posix 派生值不匹配 → fail-closed。
改为 path.posix.join 保持一致。测试断言随之更新。

Signed-off-by: Dash <dashhuang@gmail.com>

---------

Signed-off-by: Dash <dashhuang@gmail.com>
Battleplus pushed a commit to Battleplus/cindy that referenced this pull request Aug 21, 2026
* fix(pi): bridge 重载后一次性启动 env 经 globalThis stash 恢复

makecindy#3070:cindy-bridge 首次加载时读取 CINDY_PI_BASH_PACKAGE_HOME 后即从
process.env 删除;Pi 进程内扩展重载会重新执行 bridge 文件,第二次加载
读不到已删除的 env,bashPackageHome 变 undefined,此后每次 bash 都在
isolatedBashEnvironment 处 fail-closed,报 Cindy isolated Pi package
home is unavailable。

改为 takeOneShotEnv 统一存取:首次加载读删并 stash 进 globalThis
(重载与首次加载共享同一 realm),重载实例从 stash 取回 host 注入的
原始值;stash 已有记录而 env 又出现值时视为进程内代码事后写入,忽略
并再次删除。CINDY_PI_PACKAGE_MANAGEMENT token 同法处理,重载后
cindy_pi_extension 工具不再静默消失。stash 拿不到时仍返回 undefined
保持原 fail-closed,不猜外来 runtime 的路径。

Signed-off-by: DavidShen <david@xd.com>

* fix(pi): 包管理 token 不进 globalThis stash,保持仅闭包持有

review P1:CINDY_PI_PACKAGE_MANAGEMENT 是 host 签发的 bearer token,
而本进程内会加载用户安装的第三方托管扩展,它们与 bridge 共享
globalThis —— 把 token stash 进 globalThis 等于暴露给任意托管代码,
比留在首次加载闭包里更宽。

token 恢复原语义:读一次即删、仅闭包持有,重载后 cindy_pi_extension
工具退场(bash 直装仍被拦,新会话可再拿到工具,可接受)。
bash-package-home 是路径而非凭证,且本就经 PI_CODING_AGENT_DIR 进
每个 bash 子进程 env,保留 stash 不新增暴露面。

Signed-off-by: DavidShen <david@xd.com>

* fix(pi): bash 隔离 home stash 防篡改并经 PI_CODING_AGENT_DIR 双重验证

greptile P1:plain object stash 可被同进程的第三方托管扩展改写 ——
bridge 重载后会信任被污染的值,把攻击者目录当 PI_CODING_AGENT_DIR 传给
bash 与子代理。

修法:
- stash 改为 defineProperty(writable:false, configurable:false),语言
  层面封死事后改写/替换/删除;读取校验属性形态,可写可配置的属性
  (含攻击者抢跑预置的)一律不信任。
- 重载取值加双重验证:stash 必须等于 path.posix.join(PI_CODING_AGENT_DIR,
  'bash-package-home') —— 与 host 侧 joinRemotePosixPath 派生式逐字一致。
  事后改写 PI_CODING_AGENT_DIR 会让二者失配 → fail-closed(该 env 常驻
  可写,顺带变成 canary)。
- env 值在 stash 建立后再次出现一律删除并忽略;验证失败或 stash 缺失
  返回 undefined,下游 isolatedBashEnvironment 保持原 fail-closed。

Signed-off-by: DavidShen <david@xd.com>

---------

Signed-off-by: DavidShen <david@xd.com>
Battleplus pushed a commit to Battleplus/cindy that referenced this pull request Aug 21, 2026
) (makecindy#3165)

* fix(pi): 修复 subagent bash 因父 bridge 删除 env 而 fail-closed (makecindy#3132)

父 bridge 在初始化时消费并从 process.env 删除 CINDY_PI_BASH_PACKAGE_HOME;
subagent 子进程通过 Object.assign({}, process.env) 构造 childEnv 时已
拿不到该变量,导致子进程里的 bridge 无法解析 bash 隔离 home,抛出
"Cindy isolated Pi package home is unavailable",subagent 内 bash 100% 必现。

修复两处:

1. cindy-bridge resolveBashPackageHome:env 与 stash 均不可用时(正是
   subagent 子进程路径),从 PI_CODING_AGENT_DIR 派生
   path.posix.join(configHome, 'bash-package-home');非绝对路径仍
   fail-closed。公式与 makecindy#3089 stash 校验一致。

2. cindy-subagent runTask:spawn 前,configHome 为绝对路径时写回
   childEnv[CINDY_PI_BASH_PACKAGE_HOME] = join(configHome, 'bash-package-home'),
   让子 bridge 首次加载时能读到该变量(子 bridge 仍会在加载时删除它)。

不把 subagent 白名单改成含 bash(产品:仍是只读)。

Signed-off-by: Dash <dashhuang@gmail.com>

* test(pi): 补 subagent childEnv 执行级测试(响应 greptile P2 makecindy#3165)

结构断言只检查源码文本顺序,无法防止 isAbsolute 分支或变量
绑定的控制流回归。新增 loadSubagentChildEnvHelper 以 runInNewContext
执行真实 childEnv 构造逻辑,断言:
- 绝对路径时 CINDY_PI_BASH_PACKAGE_HOME 被正确设置
- 相对路径 fail-closed(不设置)
- MCP bridge / remote MCP secret 仍被剥离

Signed-off-by: Dash <dashhuang@gmail.com>

* fix(pi): 子进程 bash-package-home 改用 path.posix.join(响应 Codex P1 makecindy#3165)

bridge derivedBashPackageHome 与 stash 校验都用 path.posix.join;
子进程 childEnv 写回若用 path.join(Windows 上产生反斜杠),
子 bridge reload 时 stash 与 posix 派生值不匹配 → fail-closed。
改为 path.posix.join 保持一致。测试断言随之更新。

Signed-off-by: Dash <dashhuang@gmail.com>

---------

Signed-off-by: Dash <dashhuang@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants