Skip to content

fix(windows): let W1 Glob skip nested junctions - #3955

Draft
sunrioa wants to merge 4 commits into
apache:mainfrom
sunrioa:codex/fix-windows-glob-junctions
Draft

fix(windows): let W1 Glob skip nested junctions#3955
sunrioa wants to merge 4 commits into
apache:mainfrom
sunrioa:codex/fix-windows-glob-junctions

Conversation

@sunrioa

@sunrioa sunrioa commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Let Windows W1 read-only recursive Glob enumerate ordinary files beside nested NTFS junctions without traversing the junctions.
  • Introduce a digest-bound nonFollowingReadRoot policy and partition the approved root into bounded physical-directory ACL grants. Nested reparse entries receive no grants, and their targets are not traversed or granted access through the link.
  • Use a non-following filesystem walker with regression coverage for Glob matching, hidden-file handling, traversal order, and bounded-result prefixes.
  • Update the English and Chinese Windows sandbox RFCs, unit/smoke tests, and packaged verification for this explicitly scoped exception.
  • Resolve brace-expansion to 5.0.9 and regenerate the Desktop and CLI third-party notices.

Refs #3938

Alternative to #3952. Default recursive-read admission remains unchanged; only explicitly marked, read-only W1 Glob plans use the new behavior. Junction entries themselves remain outside the ACL grant plan.

Security boundary

  • The non-following root must be a declared recursive read root, and the launch must contain no write grants. Both TypeScript policy compilation and the native broker validate these constraints.
  • The root admitted by the broker must be a physical directory. Reparse-point roots, files with multiple hard links, invalid policy combinations, and digest mismatches remain fail-closed.
  • Nested reparse entries are skipped by both ACL planning and filesystem enumeration. This does not revoke independent access to a target already authorized through its physical path.
  • ACL planning is bounded to 4,096 physical grants, 100,000 inspected entries, and 256 directory levels below the root.
  • The change reuses the existing ACL ledger lifecycle: grants are revoked after the Job is confirmed settled. If settlement is uncertain, recovery evidence is preserved and quarantined rather than claiming cleanup succeeded.
  • This does not add Windows Bash/PowerShell or Grep support, change Read/Write permissions, or introduce a non-Windows traversal implementation.

Verification

Current head and hosted verification

31f22927f922f84e9339bab2be0dde8e8ca1a70e

This commit only adds the missing Generated-by: OpenAI Codex trailer to the preceding commit. Its source tree is identical to cf968e3e10e5e9452f9171637198f454b92bb6a4; git diff between the two commits is empty.

Seven of the eight hosted workflows for the current head passed, including Release Windows check. Main CI failed in graceful Host shutdown stops and drains an active Turn before releasing ownership with authority_draining; subsequent Desktop E2E steps in that run were skipped. A passing main CI result for the current head is still pending.

All eight hosted workflows reviewed on the preceding, tree-identical commit cf968e3e10e5e9452f9171637198f454b92bb6a4 passed, including:

These earlier results are supporting evidence, not a substitute for passing CI on the current PR revision and merge base.

Local macOS verification

  • npm run lint, npm run format:check, npm run build, and npm run typecheck
  • Knip for apps/desktop and packages/ui
  • npm --workspace @maka/runtime test: 3,048 passed, 13 skipped, 0 failed
  • filesystem-worker suites: 64 passed, 0 failed
  • npm run check:release
  • npm run check:asf-source: 67 passed
  • Production dependency audit: 0 vulnerabilities
  • Shipped Desktop closure audit: 0 moderate-or-higher advisories across 320 packages
  • Registry verification: 872 verified signatures and 227 verified attestations

Earlier local Windows 11 x64 verification

The implementation was verified locally before the dependency-only follow-up:

  • Rust formatting and locked build
  • Rust unit tests: 62 passed
  • npm run build
  • filesystem-worker Windows junction smoke: 5 passed
  • AppContainer smoke
  • Packaged verification covering lifecycle recovery, 64-launch concurrency, the adversarial matrix, node-pty/ConPTY, and renderer recovery
  • Manual ordinary-file regression: Glob(main.go) returned ["main.go"]
  • Manual junction boundary check: Glob(node_modules/@sunrioa/rin-sdk/**/*) returned []

The local package:windows-x64 wrapper encountered a missing /bin/bash in an unrelated standalone launcher check. Packaging was completed with the same Electron Builder configuration, and the resulting artifact passed verify:windows-x64.

The dependency-only follow-up was not repackaged locally on Windows. Hosted Windows packaging and release verification have passed for the current head 31f22927f922f84e9339bab2be0dde8e8ca1a70e.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex analyzed the Windows ACL and filesystem-worker boundaries, implemented the policy, traversal, documentation, dependency, and regression-test changes, ran local verification, and reviewed the diff. I reviewed the implementation, Windows validation results, and PR text.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No
简体中文

摘要

  • 让 Windows W1 的只读递归 Glob 在目录树中存在嵌套 NTFS junction 时,仍能枚举旁边的普通文件,同时不遍历 junction。
  • 新增与授权摘要绑定的 nonFollowingReadRoot 策略,将批准的搜索根拆分为有界的物理目录 ACL 授权。嵌套 reparse 节点不获得授权,也不会通过链接遍历或授权其目标。
  • 使用不跟随链接的文件遍历器,并通过回归测试覆盖 Glob 匹配、隐藏文件处理、遍历顺序和受结果上限约束时的返回前缀。
  • 同步更新中英文 Windows sandbox RFC、单元/烟雾测试及打包验证,明确这一限定范围的例外行为。
  • 将锁文件中的 brace-expansion 更新为 5.0.9,并重新生成 Desktop 和 CLI 的第三方许可证清单。

关联 #3938

这是 #3952 的替代实现。默认的递归只读准入规则保持不变,只有显式标记的 W1 Glob 只读计划才采用新行为;junction 节点本身也不会进入 ACL 授权计划。

安全边界

  • 非跟随根必须是已经声明的递归只读根,执行计划中不能包含写权限。TypeScript 策略编译层和原生 Broker 都会校验这些限制。
  • Broker 接纳的根必须是物理目录。根本身为 reparse point、文件存在多个硬链接、策略组合无效或摘要不匹配时,仍会安全拒绝。
  • ACL 计划和文件枚举两层都会跳过嵌套 reparse 节点;这不会撤销目标通过物理路径独立获得的已有访问权限。
  • ACL 计划最多允许 4,096 条物理授权、检查 100,000 个目录项,以及根目录以下 256 层目录深度。
  • 继续使用现有 ACL 台账生命周期:确认 Job 已结束后撤销授权;如果无法确认进程已经完全结束,则保留并隔离恢复记录,而不是声称清理已经成功。
  • 本次不增加 Windows Bash/PowerShell 或 Grep 支持,不改变 Read/Write 权限,也不引入新的非 Windows 遍历实现。

验证

当前提交与远程验证

31f22927f922f84e9339bab2be0dde8e8ca1a70e

该提交仅为前一个提交补齐缺失的 Generated-by: OpenAI Codex 标记。源码树与 cf968e3e10e5e9452f9171637198f454b92bb6a4 完全相同,两个提交之间的 git diff 为空。

当前提交对应的 8 个远程工作流中有 7 个通过,包括 Windows 发布检查主 CIgraceful Host shutdown stops and drains an active Turn before releasing ownership 测试中因 authority_draining 失败,该次运行后续的 Desktop E2E 步骤被跳过。当前提交尚缺少通过的主 CI 结果。

此前源码树相同的提交 cf968e3e10e5e9452f9171637198f454b92bb6a4 中,已核对的 8 个远程工作流全部通过,包括:

这些此前的结果仅作为补充证据,不能替代当前 PR 修订及合并基线上的 CI 通过结果。

本地 macOS 验证

  • lint、格式检查、完整构建和类型检查
  • Desktop 与 UI 的 Knip 检查
  • Runtime 全量测试:3,048 通过、13 跳过、0 失败
  • filesystem-worker 测试:64 通过、0 失败
  • check:release
  • ASF 源码检查:67 通过
  • 生产依赖审计:0 个漏洞
  • Desktop 发布依赖闭包:320 个包中没有中等及以上级别公告
  • 注册表验证:872 个签名和 227 个证明验证成功

此前本地 Windows 11 x64 验证

在最后一次仅更新依赖的提交之前,已完成:

  • Rust 格式检查和锁定依赖构建
  • Rust 单元测试:62 通过
  • npm 构建
  • filesystem-worker Windows junction smoke:5 通过
  • AppContainer smoke
  • 打包产物验证:生命周期恢复、64 路并发、对抗性矩阵、node-pty/ConPTY 和渲染器恢复
  • 手工普通文件回归:Glob(main.go) 返回 ["main.go"]
  • 手工 junction 边界验证:Glob(node_modules/@sunrioa/rin-sdk/**/*) 返回 []

本地 package:windows-x64 包装脚本在无关的 standalone launcher 检查处遇到缺少 /bin/bash 的环境问题。随后使用同一 Electron Builder 配置完成打包,产物通过了 verify:windows-x64

仅更新依赖的提交没有在本机 Windows 重新打包;当前提交 31f22927f922f84e9339bab2be0dde8e8ca1a70e 已通过远程 Windows 打包和发布验证。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XL Over 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant