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

Open
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction
Open

fix(windows): let Glob skip nested junctions#3952
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction

Conversation

@HuYellow

@HuYellowHuYellow commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • bind one explicit nonFollowingReadRoot to the Windows broker manifest digest and expose it only for read-only recursive Glob operations
  • decompose that root into bounded grants for physical directories, excluding nested reparse entries and their targets while keeping raw recursive reads, writes, hard links, and a reparse-point root fail-closed
  • use a non-following Windows Glob walker that preserves Node matching, dotfile, ordering, and limit semantics, including omitting the junction entry itself from broad **/* results
  • align the English and Chinese Windows sandbox RFCs, focused tests, packaged evidence, and dependency notices with the specialized policy

Fixes#3938

The specialized-policy implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling. Their commit authorship and Generated-by trailers are preserved in this branch; the unrelated dependency-only commit was not copied. The final lockfile instead keeps the newer audit fixes already merged to main.

Verification

  • npm run build:test
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run windows:inventory
  • npm audit --registry=https://registry.npmjs.org --audit-level=high (0 vulnerabilities)
  • npm Desktop/CLI third-party notice checks and Windows Cargo notice check
  • cargo fmt --manifest-path experiments/windows-sandbox/launcher/Cargo.toml -- --check
  • cargo test --locked --manifest-path experiments/windows-sandbox/launcher/Cargo.toml (62 passed)
  • release-mode Windows broker build
  • AppContainer smoke and packaged adversarial matrix
  • focused Runtime policy/manifest/walker tests (24 passed)
  • node --test packages/runtime/dist/__tests__/filesystem-worker-windows-smoke.test.js (5 passed)
  • full verify:windows-x64 on a locally generated package, including packaged dependency closure, broker/stdio/ACL recovery, 64-launch soak, adversarial matrix, real packaged Electron worker Glob, node-pty/ConPTY, renderer, installer and ZIP hashes

The local machine has no Visual Studio C++ Build Tools, so the verification package used the already installed patched node-pty binaries (npmRebuild=false) and the exact local Electron 43.4.1 distribution instead of rebuilding native dependencies. The normal package path is left to CI. check:release reached one unrelated standalone-launcher WSL path failure after all dependency-notice and release-closure checks passed; check:asf-source is locally blocked by unavailable file-symlink privileges and gzip.

Security review focus

  • nonFollowingReadRoot is validated as a declared recursive read root, rejects every writable launch, and is included in the launch digest.
  • Raw recursive roots retain their previous whole-tree reparse rejection, so the packaged adversarial matrix remains valid.
  • The broker grants only physical directories. Reparse entries and targets receive no ledger entry or ACE.
  • Planning fails closed above 4,096 grants, 100,000 inspected entries, or 256 directory levels.
  • The worker independently excludes Windows reparse Dirents before matching or traversal, including broad **/* patterns.

AI use

Select exactly one:

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

Tool(s) and scope: OpenAI Codex implemented and integrated the specialized Windows ACL policy, non-following Glob traversal, documentation, regression coverage, conflict resolution, and local verification. Affected commits retain the required Generated-by: OpenAI Codex trailers.

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

@Astro-Han

Copy link
Copy Markdown
Contributor

I reviewed this PR at exact head 949df79d846042ba0ea037cdc115baf9f47384cf (base 2d10b52, merge-base 38f0a275, 4 files +176−16).

Spec: GO — no P0–P3

  • Root reparse points are still unconditionally rejected; recursive write still rejects the whole tree; recursive read now terminates at a nested reparse boundary (acl_ledger.rs:443-477).
  • The Windows ACL path correctly uses icacls /L /T so it does not follow the target; the real junction ACL test proves the target and its descendants do not receive the synthetic SID and verifies cleanup.
  • The filesystem-worker Windows smoke covers both ordinary main.go enumeration and the junction-descendant pattern returning empty.
  • No implemented-but-wrong / missing / scope-creep finding within bug(windows): Glob fails when an approved tree contains a nested junction #3938; the existing hard-link scan→grant race is not introduced by this diff.

Standards: NO-GO — 1 hard P1 + 1 judgment-only P3

  • P1 — governing security contract and release evidence are not in sync with the new strategy.acl_ledger.rs:443-477 now accepts a nested reparse boundary for recursive read, but docs/architecture/windows-sandbox-rfc-v1.md still requires “recursive reparse-point rejection before ACL mutation” in several places and defines the packaged recursive-junction admission refusal as W1/release evidence. adversarial-matrix-smoke.ps1:208-216 also still requires the same nested-junction read request to fail closed as before. As a result the exact-head package run 32993195237 fails directly: launcher exits 0, matrix reports Junction alias admission did not fail closed. Fix by either formally revising the RFC and the machine-readable matrix to a read traversal-boundary contract (keep root/write rejection, prove target denial with a real child) or restoring the recursive rejection.
  • Judgment-only P3:skip_nested_reparse_points: bool with bare false/true encodes a security policy as a boolean; a named enum would reduce inversion risk.

Other checks: git diff --check passes. windows_recovery and windows_sandbox_w0_protocol are green; package is red for the reason above (directly related), test is red due to an unrelated Desktop prompt-rail E2E (66 pass / 1 fail / 1 skip). OPEN / MERGEABLE / REVIEW_REQUIRED, no reviews/comments, head did not drift.

What I did not check: full local test suite beyond the focused checks noted.

Gate: exact head has no P0–P2, but the P1 standards finding and the failing required package/test checks must be closed (update RFC + adversarial-matrix-smoke.ps1 to match the new read-boundary contract, or restore rejection) before merge.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@github-actionsgithub-actionsBot added the effort/M Under 500 readable lines label Aug 27, 2026
…s-glob-junction
# Conflicts:
#	package-lock.json
Generated-by: OpenAI Codex
@HuYellowHuYellow changed the title fix(windows): skip nested junctions for read ACL grantsfix(windows): let Glob skip nested junctionsAug 27, 2026
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Addressed at head 82c8766b7.

  • P1: replaced the global recursive-read relaxation with a digest-bound nonFollowingReadRoot available only to read-only recursive Glob. Raw recursive reads and writes still reject nested reparse points, so the original packaged adversarial admission check remains valid.
  • Synchronized the English/Chinese RFCs, Windows sandbox README, Runtime smoke coverage, and packaged verifier. The verifier now proves broad **/* omits the junction entry and descendants while ordinary files remain visible.
  • P3: removed the skip_nested_reparse_points: bool entirely. The policy is represented by an optional canonical root and validated at the client, profile, manifest protocol, digest, and broker admission boundaries.
  • Added fail-closed planner limits for grants, inspected entries, and depth, plus hard-link/root/policy-tamper coverage.

Local results include Rust 62/62, Windows worker smoke 5/5, AppContainer smoke, raw packaged adversarial matrix, and full verify:windows-x64 including the packaged Electron worker, 64-launch soak, node-pty/ConPTY, renderer, installer, and ZIP checks.

The specialized implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling with authorship preserved. The branch is also merged with current main; the final lockfile keeps brace-expansion 5.0.9, and both generated notices are synchronized.

@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up: all current checks are green at 82c8766. The CI test job passed in 16m45s, and the Windows release package job passed in 17m28s, including Package the Windows installer and ZIP, Verify the Windows release, packaged adversarial evidence, upgrade/autoupdate, and rollback checks.

@github-actionsgithub-actionsBot added effort/XL Over 1000 readable lines and removed effort/M Under 500 readable lines labels Aug 27, 2026

@Astro-HanAstro-Han 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.

The non-following direction matches #3938, but three exact-head boundary gaps remain. Exact head is 82c8766 and current merge state is MERGEABLE/BLOCKED. Review analysis was assisted by Codex and an independent @Reviewer agent. Astro-Han verified the client→broker composition, Windows walker replacement window, normal large-tree path, and severity before publication and owns this review.

Comment threadpackages/runtime/src/filesystem-worker/client.ts Outdated
Comment threadpackages/runtime/src/filesystem-worker/operations.ts
Comment threadexperiments/windows-sandbox/launcher/src/acl_ledger.rs
Bind the unfollowed root identity, revalidate directory reads, and bound ACL planning by Glob traversal depth and directory work.
Generated-by: OpenAI Codex
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up complete at da2612040.

  • Addressed and resolved all three Aug 30 review threads: root-junction identity, cached-Dirent replacement, and >100k/root-only admission.
  • Synchronized the English/Chinese RFC, experiment README, broker protocol/digest, Runtime tests, W0 smoke, and packaged verifier.
  • All current checks are green, including Rust 64/64 + real broker worker smoke, heavy, test, Windows package, recovery, audit, and cross-platform CLI validation.

The branch remains mergeable. main advanced by five unrelated Desktop/Runtime Host/CLI/Storage commits while CI ran; none touches the Windows worker/broker paths changed here. Ready for maintainer review.

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

Labels

effort/XLOver 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(windows): Glob fails when an approved tree contains a nested junction

3 participants

@HuYellow@Astro-Han@sunrioa
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

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

Open
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction
Open

fix(windows): let Glob skip nested junctions#3952
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction

Conversation

@HuYellow

@HuYellowHuYellow commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • bind one explicit nonFollowingReadRoot to the Windows broker manifest digest and expose it only for read-only recursive Glob operations
  • decompose that root into bounded grants for physical directories, excluding nested reparse entries and their targets while keeping raw recursive reads, writes, hard links, and a reparse-point root fail-closed
  • use a non-following Windows Glob walker that preserves Node matching, dotfile, ordering, and limit semantics, including omitting the junction entry itself from broad **/* results
  • align the English and Chinese Windows sandbox RFCs, focused tests, packaged evidence, and dependency notices with the specialized policy

Fixes#3938

The specialized-policy implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling. Their commit authorship and Generated-by trailers are preserved in this branch; the unrelated dependency-only commit was not copied. The final lockfile instead keeps the newer audit fixes already merged to main.

Verification

  • npm run build:test
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run windows:inventory
  • npm audit --registry=https://registry.npmjs.org --audit-level=high (0 vulnerabilities)
  • npm Desktop/CLI third-party notice checks and Windows Cargo notice check
  • cargo fmt --manifest-path experiments/windows-sandbox/launcher/Cargo.toml -- --check
  • cargo test --locked --manifest-path experiments/windows-sandbox/launcher/Cargo.toml (62 passed)
  • release-mode Windows broker build
  • AppContainer smoke and packaged adversarial matrix
  • focused Runtime policy/manifest/walker tests (24 passed)
  • node --test packages/runtime/dist/__tests__/filesystem-worker-windows-smoke.test.js (5 passed)
  • full verify:windows-x64 on a locally generated package, including packaged dependency closure, broker/stdio/ACL recovery, 64-launch soak, adversarial matrix, real packaged Electron worker Glob, node-pty/ConPTY, renderer, installer and ZIP hashes

The local machine has no Visual Studio C++ Build Tools, so the verification package used the already installed patched node-pty binaries (npmRebuild=false) and the exact local Electron 43.4.1 distribution instead of rebuilding native dependencies. The normal package path is left to CI. check:release reached one unrelated standalone-launcher WSL path failure after all dependency-notice and release-closure checks passed; check:asf-source is locally blocked by unavailable file-symlink privileges and gzip.

Security review focus

  • nonFollowingReadRoot is validated as a declared recursive read root, rejects every writable launch, and is included in the launch digest.
  • Raw recursive roots retain their previous whole-tree reparse rejection, so the packaged adversarial matrix remains valid.
  • The broker grants only physical directories. Reparse entries and targets receive no ledger entry or ACE.
  • Planning fails closed above 4,096 grants, 100,000 inspected entries, or 256 directory levels.
  • The worker independently excludes Windows reparse Dirents before matching or traversal, including broad **/* patterns.

AI use

Select exactly one:

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

Tool(s) and scope: OpenAI Codex implemented and integrated the specialized Windows ACL policy, non-following Glob traversal, documentation, regression coverage, conflict resolution, and local verification. Affected commits retain the required Generated-by: OpenAI Codex trailers.

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

@Astro-Han

Copy link
Copy Markdown
Contributor

I reviewed this PR at exact head 949df79d846042ba0ea037cdc115baf9f47384cf (base 2d10b52, merge-base 38f0a275, 4 files +176−16).

Spec: GO — no P0–P3

  • Root reparse points are still unconditionally rejected; recursive write still rejects the whole tree; recursive read now terminates at a nested reparse boundary (acl_ledger.rs:443-477).
  • The Windows ACL path correctly uses icacls /L /T so it does not follow the target; the real junction ACL test proves the target and its descendants do not receive the synthetic SID and verifies cleanup.
  • The filesystem-worker Windows smoke covers both ordinary main.go enumeration and the junction-descendant pattern returning empty.
  • No implemented-but-wrong / missing / scope-creep finding within bug(windows): Glob fails when an approved tree contains a nested junction #3938; the existing hard-link scan→grant race is not introduced by this diff.

Standards: NO-GO — 1 hard P1 + 1 judgment-only P3

  • P1 — governing security contract and release evidence are not in sync with the new strategy.acl_ledger.rs:443-477 now accepts a nested reparse boundary for recursive read, but docs/architecture/windows-sandbox-rfc-v1.md still requires “recursive reparse-point rejection before ACL mutation” in several places and defines the packaged recursive-junction admission refusal as W1/release evidence. adversarial-matrix-smoke.ps1:208-216 also still requires the same nested-junction read request to fail closed as before. As a result the exact-head package run 32993195237 fails directly: launcher exits 0, matrix reports Junction alias admission did not fail closed. Fix by either formally revising the RFC and the machine-readable matrix to a read traversal-boundary contract (keep root/write rejection, prove target denial with a real child) or restoring the recursive rejection.
  • Judgment-only P3:skip_nested_reparse_points: bool with bare false/true encodes a security policy as a boolean; a named enum would reduce inversion risk.

Other checks: git diff --check passes. windows_recovery and windows_sandbox_w0_protocol are green; package is red for the reason above (directly related), test is red due to an unrelated Desktop prompt-rail E2E (66 pass / 1 fail / 1 skip). OPEN / MERGEABLE / REVIEW_REQUIRED, no reviews/comments, head did not drift.

What I did not check: full local test suite beyond the focused checks noted.

Gate: exact head has no P0–P2, but the P1 standards finding and the failing required package/test checks must be closed (update RFC + adversarial-matrix-smoke.ps1 to match the new read-boundary contract, or restore rejection) before merge.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@github-actionsgithub-actionsBot added the effort/M Under 500 readable lines label Aug 27, 2026
…s-glob-junction
# Conflicts:
#	package-lock.json
Generated-by: OpenAI Codex
@HuYellowHuYellow changed the title fix(windows): skip nested junctions for read ACL grantsfix(windows): let Glob skip nested junctionsAug 27, 2026
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Addressed at head 82c8766b7.

  • P1: replaced the global recursive-read relaxation with a digest-bound nonFollowingReadRoot available only to read-only recursive Glob. Raw recursive reads and writes still reject nested reparse points, so the original packaged adversarial admission check remains valid.
  • Synchronized the English/Chinese RFCs, Windows sandbox README, Runtime smoke coverage, and packaged verifier. The verifier now proves broad **/* omits the junction entry and descendants while ordinary files remain visible.
  • P3: removed the skip_nested_reparse_points: bool entirely. The policy is represented by an optional canonical root and validated at the client, profile, manifest protocol, digest, and broker admission boundaries.
  • Added fail-closed planner limits for grants, inspected entries, and depth, plus hard-link/root/policy-tamper coverage.

Local results include Rust 62/62, Windows worker smoke 5/5, AppContainer smoke, raw packaged adversarial matrix, and full verify:windows-x64 including the packaged Electron worker, 64-launch soak, node-pty/ConPTY, renderer, installer, and ZIP checks.

The specialized implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling with authorship preserved. The branch is also merged with current main; the final lockfile keeps brace-expansion 5.0.9, and both generated notices are synchronized.

@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up: all current checks are green at 82c8766. The CI test job passed in 16m45s, and the Windows release package job passed in 17m28s, including Package the Windows installer and ZIP, Verify the Windows release, packaged adversarial evidence, upgrade/autoupdate, and rollback checks.

@github-actionsgithub-actionsBot added effort/XL Over 1000 readable lines and removed effort/M Under 500 readable lines labels Aug 27, 2026

@Astro-HanAstro-Han 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.

The non-following direction matches #3938, but three exact-head boundary gaps remain. Exact head is 82c8766 and current merge state is MERGEABLE/BLOCKED. Review analysis was assisted by Codex and an independent @Reviewer agent. Astro-Han verified the client→broker composition, Windows walker replacement window, normal large-tree path, and severity before publication and owns this review.

Comment threadpackages/runtime/src/filesystem-worker/client.ts Outdated
Comment threadpackages/runtime/src/filesystem-worker/operations.ts
Comment threadexperiments/windows-sandbox/launcher/src/acl_ledger.rs
Bind the unfollowed root identity, revalidate directory reads, and bound ACL planning by Glob traversal depth and directory work.
Generated-by: OpenAI Codex
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up complete at da2612040.

  • Addressed and resolved all three Aug 30 review threads: root-junction identity, cached-Dirent replacement, and >100k/root-only admission.
  • Synchronized the English/Chinese RFC, experiment README, broker protocol/digest, Runtime tests, W0 smoke, and packaged verifier.
  • All current checks are green, including Rust 64/64 + real broker worker smoke, heavy, test, Windows package, recovery, audit, and cross-platform CLI validation.

The branch remains mergeable. main advanced by five unrelated Desktop/Runtime Host/CLI/Storage commits while CI ran; none touches the Windows worker/broker paths changed here. Ready for maintainer review.

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

Labels

effort/XLOver 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(windows): Glob fails when an approved tree contains a nested junction

3 participants

@HuYellow@Astro-Han@sunrioa
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Open
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction
Open

fix(windows): let Glob skip nested junctions#3952
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction

Conversation

@HuYellow

@HuYellowHuYellow commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • bind one explicit nonFollowingReadRoot to the Windows broker manifest digest and expose it only for read-only recursive Glob operations
  • decompose that root into bounded grants for physical directories, excluding nested reparse entries and their targets while keeping raw recursive reads, writes, hard links, and a reparse-point root fail-closed
  • use a non-following Windows Glob walker that preserves Node matching, dotfile, ordering, and limit semantics, including omitting the junction entry itself from broad **/* results
  • align the English and Chinese Windows sandbox RFCs, focused tests, packaged evidence, and dependency notices with the specialized policy

Fixes#3938

The specialized-policy implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling. Their commit authorship and Generated-by trailers are preserved in this branch; the unrelated dependency-only commit was not copied. The final lockfile instead keeps the newer audit fixes already merged to main.

Verification

  • npm run build:test
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run windows:inventory
  • npm audit --registry=https://registry.npmjs.org --audit-level=high (0 vulnerabilities)
  • npm Desktop/CLI third-party notice checks and Windows Cargo notice check
  • cargo fmt --manifest-path experiments/windows-sandbox/launcher/Cargo.toml -- --check
  • cargo test --locked --manifest-path experiments/windows-sandbox/launcher/Cargo.toml (62 passed)
  • release-mode Windows broker build
  • AppContainer smoke and packaged adversarial matrix
  • focused Runtime policy/manifest/walker tests (24 passed)
  • node --test packages/runtime/dist/__tests__/filesystem-worker-windows-smoke.test.js (5 passed)
  • full verify:windows-x64 on a locally generated package, including packaged dependency closure, broker/stdio/ACL recovery, 64-launch soak, adversarial matrix, real packaged Electron worker Glob, node-pty/ConPTY, renderer, installer and ZIP hashes

The local machine has no Visual Studio C++ Build Tools, so the verification package used the already installed patched node-pty binaries (npmRebuild=false) and the exact local Electron 43.4.1 distribution instead of rebuilding native dependencies. The normal package path is left to CI. check:release reached one unrelated standalone-launcher WSL path failure after all dependency-notice and release-closure checks passed; check:asf-source is locally blocked by unavailable file-symlink privileges and gzip.

Security review focus

  • nonFollowingReadRoot is validated as a declared recursive read root, rejects every writable launch, and is included in the launch digest.
  • Raw recursive roots retain their previous whole-tree reparse rejection, so the packaged adversarial matrix remains valid.
  • The broker grants only physical directories. Reparse entries and targets receive no ledger entry or ACE.
  • Planning fails closed above 4,096 grants, 100,000 inspected entries, or 256 directory levels.
  • The worker independently excludes Windows reparse Dirents before matching or traversal, including broad **/* patterns.

AI use

Select exactly one:

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

Tool(s) and scope: OpenAI Codex implemented and integrated the specialized Windows ACL policy, non-following Glob traversal, documentation, regression coverage, conflict resolution, and local verification. Affected commits retain the required Generated-by: OpenAI Codex trailers.

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

@Astro-Han

Copy link
Copy Markdown
Contributor

I reviewed this PR at exact head 949df79d846042ba0ea037cdc115baf9f47384cf (base 2d10b52, merge-base 38f0a275, 4 files +176−16).

Spec: GO — no P0–P3

  • Root reparse points are still unconditionally rejected; recursive write still rejects the whole tree; recursive read now terminates at a nested reparse boundary (acl_ledger.rs:443-477).
  • The Windows ACL path correctly uses icacls /L /T so it does not follow the target; the real junction ACL test proves the target and its descendants do not receive the synthetic SID and verifies cleanup.
  • The filesystem-worker Windows smoke covers both ordinary main.go enumeration and the junction-descendant pattern returning empty.
  • No implemented-but-wrong / missing / scope-creep finding within bug(windows): Glob fails when an approved tree contains a nested junction #3938; the existing hard-link scan→grant race is not introduced by this diff.

Standards: NO-GO — 1 hard P1 + 1 judgment-only P3

  • P1 — governing security contract and release evidence are not in sync with the new strategy.acl_ledger.rs:443-477 now accepts a nested reparse boundary for recursive read, but docs/architecture/windows-sandbox-rfc-v1.md still requires “recursive reparse-point rejection before ACL mutation” in several places and defines the packaged recursive-junction admission refusal as W1/release evidence. adversarial-matrix-smoke.ps1:208-216 also still requires the same nested-junction read request to fail closed as before. As a result the exact-head package run 32993195237 fails directly: launcher exits 0, matrix reports Junction alias admission did not fail closed. Fix by either formally revising the RFC and the machine-readable matrix to a read traversal-boundary contract (keep root/write rejection, prove target denial with a real child) or restoring the recursive rejection.
  • Judgment-only P3:skip_nested_reparse_points: bool with bare false/true encodes a security policy as a boolean; a named enum would reduce inversion risk.

Other checks: git diff --check passes. windows_recovery and windows_sandbox_w0_protocol are green; package is red for the reason above (directly related), test is red due to an unrelated Desktop prompt-rail E2E (66 pass / 1 fail / 1 skip). OPEN / MERGEABLE / REVIEW_REQUIRED, no reviews/comments, head did not drift.

What I did not check: full local test suite beyond the focused checks noted.

Gate: exact head has no P0–P2, but the P1 standards finding and the failing required package/test checks must be closed (update RFC + adversarial-matrix-smoke.ps1 to match the new read-boundary contract, or restore rejection) before merge.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@github-actionsgithub-actionsBot added the effort/M Under 500 readable lines label Aug 27, 2026
…s-glob-junction
# Conflicts:
#	package-lock.json
Generated-by: OpenAI Codex
@HuYellowHuYellow changed the title fix(windows): skip nested junctions for read ACL grantsfix(windows): let Glob skip nested junctionsAug 27, 2026
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Addressed at head 82c8766b7.

  • P1: replaced the global recursive-read relaxation with a digest-bound nonFollowingReadRoot available only to read-only recursive Glob. Raw recursive reads and writes still reject nested reparse points, so the original packaged adversarial admission check remains valid.
  • Synchronized the English/Chinese RFCs, Windows sandbox README, Runtime smoke coverage, and packaged verifier. The verifier now proves broad **/* omits the junction entry and descendants while ordinary files remain visible.
  • P3: removed the skip_nested_reparse_points: bool entirely. The policy is represented by an optional canonical root and validated at the client, profile, manifest protocol, digest, and broker admission boundaries.
  • Added fail-closed planner limits for grants, inspected entries, and depth, plus hard-link/root/policy-tamper coverage.

Local results include Rust 62/62, Windows worker smoke 5/5, AppContainer smoke, raw packaged adversarial matrix, and full verify:windows-x64 including the packaged Electron worker, 64-launch soak, node-pty/ConPTY, renderer, installer, and ZIP checks.

The specialized implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling with authorship preserved. The branch is also merged with current main; the final lockfile keeps brace-expansion 5.0.9, and both generated notices are synchronized.

@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up: all current checks are green at 82c8766. The CI test job passed in 16m45s, and the Windows release package job passed in 17m28s, including Package the Windows installer and ZIP, Verify the Windows release, packaged adversarial evidence, upgrade/autoupdate, and rollback checks.

@github-actionsgithub-actionsBot added effort/XL Over 1000 readable lines and removed effort/M Under 500 readable lines labels Aug 27, 2026

@Astro-HanAstro-Han 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.

The non-following direction matches #3938, but three exact-head boundary gaps remain. Exact head is 82c8766 and current merge state is MERGEABLE/BLOCKED. Review analysis was assisted by Codex and an independent @Reviewer agent. Astro-Han verified the client→broker composition, Windows walker replacement window, normal large-tree path, and severity before publication and owns this review.

Comment threadpackages/runtime/src/filesystem-worker/client.ts Outdated
Comment threadpackages/runtime/src/filesystem-worker/operations.ts
Comment threadexperiments/windows-sandbox/launcher/src/acl_ledger.rs
Bind the unfollowed root identity, revalidate directory reads, and bound ACL planning by Glob traversal depth and directory work.
Generated-by: OpenAI Codex
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up complete at da2612040.

  • Addressed and resolved all three Aug 30 review threads: root-junction identity, cached-Dirent replacement, and >100k/root-only admission.
  • Synchronized the English/Chinese RFC, experiment README, broker protocol/digest, Runtime tests, W0 smoke, and packaged verifier.
  • All current checks are green, including Rust 64/64 + real broker worker smoke, heavy, test, Windows package, recovery, audit, and cross-platform CLI validation.

The branch remains mergeable. main advanced by five unrelated Desktop/Runtime Host/CLI/Storage commits while CI ran; none touches the Windows worker/broker paths changed here. Ready for maintainer review.

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

Labels

effort/XLOver 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(windows): Glob fails when an approved tree contains a nested junction

3 participants

@HuYellow@Astro-Han@sunrioa
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Open
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction
Open

fix(windows): let Glob skip nested junctions#3952
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction

Conversation

@HuYellow

@HuYellowHuYellow commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • bind one explicit nonFollowingReadRoot to the Windows broker manifest digest and expose it only for read-only recursive Glob operations
  • decompose that root into bounded grants for physical directories, excluding nested reparse entries and their targets while keeping raw recursive reads, writes, hard links, and a reparse-point root fail-closed
  • use a non-following Windows Glob walker that preserves Node matching, dotfile, ordering, and limit semantics, including omitting the junction entry itself from broad **/* results
  • align the English and Chinese Windows sandbox RFCs, focused tests, packaged evidence, and dependency notices with the specialized policy

Fixes#3938

The specialized-policy implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling. Their commit authorship and Generated-by trailers are preserved in this branch; the unrelated dependency-only commit was not copied. The final lockfile instead keeps the newer audit fixes already merged to main.

Verification

  • npm run build:test
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run windows:inventory
  • npm audit --registry=https://registry.npmjs.org --audit-level=high (0 vulnerabilities)
  • npm Desktop/CLI third-party notice checks and Windows Cargo notice check
  • cargo fmt --manifest-path experiments/windows-sandbox/launcher/Cargo.toml -- --check
  • cargo test --locked --manifest-path experiments/windows-sandbox/launcher/Cargo.toml (62 passed)
  • release-mode Windows broker build
  • AppContainer smoke and packaged adversarial matrix
  • focused Runtime policy/manifest/walker tests (24 passed)
  • node --test packages/runtime/dist/__tests__/filesystem-worker-windows-smoke.test.js (5 passed)
  • full verify:windows-x64 on a locally generated package, including packaged dependency closure, broker/stdio/ACL recovery, 64-launch soak, adversarial matrix, real packaged Electron worker Glob, node-pty/ConPTY, renderer, installer and ZIP hashes

The local machine has no Visual Studio C++ Build Tools, so the verification package used the already installed patched node-pty binaries (npmRebuild=false) and the exact local Electron 43.4.1 distribution instead of rebuilding native dependencies. The normal package path is left to CI. check:release reached one unrelated standalone-launcher WSL path failure after all dependency-notice and release-closure checks passed; check:asf-source is locally blocked by unavailable file-symlink privileges and gzip.

Security review focus

  • nonFollowingReadRoot is validated as a declared recursive read root, rejects every writable launch, and is included in the launch digest.
  • Raw recursive roots retain their previous whole-tree reparse rejection, so the packaged adversarial matrix remains valid.
  • The broker grants only physical directories. Reparse entries and targets receive no ledger entry or ACE.
  • Planning fails closed above 4,096 grants, 100,000 inspected entries, or 256 directory levels.
  • The worker independently excludes Windows reparse Dirents before matching or traversal, including broad **/* patterns.

AI use

Select exactly one:

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

Tool(s) and scope: OpenAI Codex implemented and integrated the specialized Windows ACL policy, non-following Glob traversal, documentation, regression coverage, conflict resolution, and local verification. Affected commits retain the required Generated-by: OpenAI Codex trailers.

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

@Astro-Han

Copy link
Copy Markdown
Contributor

I reviewed this PR at exact head 949df79d846042ba0ea037cdc115baf9f47384cf (base 2d10b52, merge-base 38f0a275, 4 files +176−16).

Spec: GO — no P0–P3

  • Root reparse points are still unconditionally rejected; recursive write still rejects the whole tree; recursive read now terminates at a nested reparse boundary (acl_ledger.rs:443-477).
  • The Windows ACL path correctly uses icacls /L /T so it does not follow the target; the real junction ACL test proves the target and its descendants do not receive the synthetic SID and verifies cleanup.
  • The filesystem-worker Windows smoke covers both ordinary main.go enumeration and the junction-descendant pattern returning empty.
  • No implemented-but-wrong / missing / scope-creep finding within bug(windows): Glob fails when an approved tree contains a nested junction #3938; the existing hard-link scan→grant race is not introduced by this diff.

Standards: NO-GO — 1 hard P1 + 1 judgment-only P3

  • P1 — governing security contract and release evidence are not in sync with the new strategy.acl_ledger.rs:443-477 now accepts a nested reparse boundary for recursive read, but docs/architecture/windows-sandbox-rfc-v1.md still requires “recursive reparse-point rejection before ACL mutation” in several places and defines the packaged recursive-junction admission refusal as W1/release evidence. adversarial-matrix-smoke.ps1:208-216 also still requires the same nested-junction read request to fail closed as before. As a result the exact-head package run 32993195237 fails directly: launcher exits 0, matrix reports Junction alias admission did not fail closed. Fix by either formally revising the RFC and the machine-readable matrix to a read traversal-boundary contract (keep root/write rejection, prove target denial with a real child) or restoring the recursive rejection.
  • Judgment-only P3:skip_nested_reparse_points: bool with bare false/true encodes a security policy as a boolean; a named enum would reduce inversion risk.

Other checks: git diff --check passes. windows_recovery and windows_sandbox_w0_protocol are green; package is red for the reason above (directly related), test is red due to an unrelated Desktop prompt-rail E2E (66 pass / 1 fail / 1 skip). OPEN / MERGEABLE / REVIEW_REQUIRED, no reviews/comments, head did not drift.

What I did not check: full local test suite beyond the focused checks noted.

Gate: exact head has no P0–P2, but the P1 standards finding and the failing required package/test checks must be closed (update RFC + adversarial-matrix-smoke.ps1 to match the new read-boundary contract, or restore rejection) before merge.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@github-actionsgithub-actionsBot added the effort/M Under 500 readable lines label Aug 27, 2026
…s-glob-junction
# Conflicts:
#	package-lock.json
Generated-by: OpenAI Codex
@HuYellowHuYellow changed the title fix(windows): skip nested junctions for read ACL grantsfix(windows): let Glob skip nested junctionsAug 27, 2026
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Addressed at head 82c8766b7.

  • P1: replaced the global recursive-read relaxation with a digest-bound nonFollowingReadRoot available only to read-only recursive Glob. Raw recursive reads and writes still reject nested reparse points, so the original packaged adversarial admission check remains valid.
  • Synchronized the English/Chinese RFCs, Windows sandbox README, Runtime smoke coverage, and packaged verifier. The verifier now proves broad **/* omits the junction entry and descendants while ordinary files remain visible.
  • P3: removed the skip_nested_reparse_points: bool entirely. The policy is represented by an optional canonical root and validated at the client, profile, manifest protocol, digest, and broker admission boundaries.
  • Added fail-closed planner limits for grants, inspected entries, and depth, plus hard-link/root/policy-tamper coverage.

Local results include Rust 62/62, Windows worker smoke 5/5, AppContainer smoke, raw packaged adversarial matrix, and full verify:windows-x64 including the packaged Electron worker, 64-launch soak, node-pty/ConPTY, renderer, installer, and ZIP checks.

The specialized implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling with authorship preserved. The branch is also merged with current main; the final lockfile keeps brace-expansion 5.0.9, and both generated notices are synchronized.

@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up: all current checks are green at 82c8766. The CI test job passed in 16m45s, and the Windows release package job passed in 17m28s, including Package the Windows installer and ZIP, Verify the Windows release, packaged adversarial evidence, upgrade/autoupdate, and rollback checks.

@github-actionsgithub-actionsBot added effort/XL Over 1000 readable lines and removed effort/M Under 500 readable lines labels Aug 27, 2026

@Astro-HanAstro-Han 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.

The non-following direction matches #3938, but three exact-head boundary gaps remain. Exact head is 82c8766 and current merge state is MERGEABLE/BLOCKED. Review analysis was assisted by Codex and an independent @Reviewer agent. Astro-Han verified the client→broker composition, Windows walker replacement window, normal large-tree path, and severity before publication and owns this review.

Comment threadpackages/runtime/src/filesystem-worker/client.ts Outdated
Comment threadpackages/runtime/src/filesystem-worker/operations.ts
Comment threadexperiments/windows-sandbox/launcher/src/acl_ledger.rs
Bind the unfollowed root identity, revalidate directory reads, and bound ACL planning by Glob traversal depth and directory work.
Generated-by: OpenAI Codex
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up complete at da2612040.

  • Addressed and resolved all three Aug 30 review threads: root-junction identity, cached-Dirent replacement, and >100k/root-only admission.
  • Synchronized the English/Chinese RFC, experiment README, broker protocol/digest, Runtime tests, W0 smoke, and packaged verifier.
  • All current checks are green, including Rust 64/64 + real broker worker smoke, heavy, test, Windows package, recovery, audit, and cross-platform CLI validation.

The branch remains mergeable. main advanced by five unrelated Desktop/Runtime Host/CLI/Storage commits while CI ran; none touches the Windows worker/broker paths changed here. Ready for maintainer review.

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

Labels

effort/XLOver 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(windows): Glob fails when an approved tree contains a nested junction

3 participants

@HuYellow@Astro-Han@sunrioa
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

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

Open
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction
Open

fix(windows): let Glob skip nested junctions#3952
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction

Conversation

@HuYellow

@HuYellowHuYellow commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • bind one explicit nonFollowingReadRoot to the Windows broker manifest digest and expose it only for read-only recursive Glob operations
  • decompose that root into bounded grants for physical directories, excluding nested reparse entries and their targets while keeping raw recursive reads, writes, hard links, and a reparse-point root fail-closed
  • use a non-following Windows Glob walker that preserves Node matching, dotfile, ordering, and limit semantics, including omitting the junction entry itself from broad **/* results
  • align the English and Chinese Windows sandbox RFCs, focused tests, packaged evidence, and dependency notices with the specialized policy

Fixes#3938

The specialized-policy implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling. Their commit authorship and Generated-by trailers are preserved in this branch; the unrelated dependency-only commit was not copied. The final lockfile instead keeps the newer audit fixes already merged to main.

Verification

  • npm run build:test
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run windows:inventory
  • npm audit --registry=https://registry.npmjs.org --audit-level=high (0 vulnerabilities)
  • npm Desktop/CLI third-party notice checks and Windows Cargo notice check
  • cargo fmt --manifest-path experiments/windows-sandbox/launcher/Cargo.toml -- --check
  • cargo test --locked --manifest-path experiments/windows-sandbox/launcher/Cargo.toml (62 passed)
  • release-mode Windows broker build
  • AppContainer smoke and packaged adversarial matrix
  • focused Runtime policy/manifest/walker tests (24 passed)
  • node --test packages/runtime/dist/__tests__/filesystem-worker-windows-smoke.test.js (5 passed)
  • full verify:windows-x64 on a locally generated package, including packaged dependency closure, broker/stdio/ACL recovery, 64-launch soak, adversarial matrix, real packaged Electron worker Glob, node-pty/ConPTY, renderer, installer and ZIP hashes

The local machine has no Visual Studio C++ Build Tools, so the verification package used the already installed patched node-pty binaries (npmRebuild=false) and the exact local Electron 43.4.1 distribution instead of rebuilding native dependencies. The normal package path is left to CI. check:release reached one unrelated standalone-launcher WSL path failure after all dependency-notice and release-closure checks passed; check:asf-source is locally blocked by unavailable file-symlink privileges and gzip.

Security review focus

  • nonFollowingReadRoot is validated as a declared recursive read root, rejects every writable launch, and is included in the launch digest.
  • Raw recursive roots retain their previous whole-tree reparse rejection, so the packaged adversarial matrix remains valid.
  • The broker grants only physical directories. Reparse entries and targets receive no ledger entry or ACE.
  • Planning fails closed above 4,096 grants, 100,000 inspected entries, or 256 directory levels.
  • The worker independently excludes Windows reparse Dirents before matching or traversal, including broad **/* patterns.

AI use

Select exactly one:

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

Tool(s) and scope: OpenAI Codex implemented and integrated the specialized Windows ACL policy, non-following Glob traversal, documentation, regression coverage, conflict resolution, and local verification. Affected commits retain the required Generated-by: OpenAI Codex trailers.

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

@Astro-Han

Copy link
Copy Markdown
Contributor

I reviewed this PR at exact head 949df79d846042ba0ea037cdc115baf9f47384cf (base 2d10b52, merge-base 38f0a275, 4 files +176−16).

Spec: GO — no P0–P3

  • Root reparse points are still unconditionally rejected; recursive write still rejects the whole tree; recursive read now terminates at a nested reparse boundary (acl_ledger.rs:443-477).
  • The Windows ACL path correctly uses icacls /L /T so it does not follow the target; the real junction ACL test proves the target and its descendants do not receive the synthetic SID and verifies cleanup.
  • The filesystem-worker Windows smoke covers both ordinary main.go enumeration and the junction-descendant pattern returning empty.
  • No implemented-but-wrong / missing / scope-creep finding within bug(windows): Glob fails when an approved tree contains a nested junction #3938; the existing hard-link scan→grant race is not introduced by this diff.

Standards: NO-GO — 1 hard P1 + 1 judgment-only P3

  • P1 — governing security contract and release evidence are not in sync with the new strategy.acl_ledger.rs:443-477 now accepts a nested reparse boundary for recursive read, but docs/architecture/windows-sandbox-rfc-v1.md still requires “recursive reparse-point rejection before ACL mutation” in several places and defines the packaged recursive-junction admission refusal as W1/release evidence. adversarial-matrix-smoke.ps1:208-216 also still requires the same nested-junction read request to fail closed as before. As a result the exact-head package run 32993195237 fails directly: launcher exits 0, matrix reports Junction alias admission did not fail closed. Fix by either formally revising the RFC and the machine-readable matrix to a read traversal-boundary contract (keep root/write rejection, prove target denial with a real child) or restoring the recursive rejection.
  • Judgment-only P3:skip_nested_reparse_points: bool with bare false/true encodes a security policy as a boolean; a named enum would reduce inversion risk.

Other checks: git diff --check passes. windows_recovery and windows_sandbox_w0_protocol are green; package is red for the reason above (directly related), test is red due to an unrelated Desktop prompt-rail E2E (66 pass / 1 fail / 1 skip). OPEN / MERGEABLE / REVIEW_REQUIRED, no reviews/comments, head did not drift.

What I did not check: full local test suite beyond the focused checks noted.

Gate: exact head has no P0–P2, but the P1 standards finding and the failing required package/test checks must be closed (update RFC + adversarial-matrix-smoke.ps1 to match the new read-boundary contract, or restore rejection) before merge.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@github-actionsgithub-actionsBot added the effort/M Under 500 readable lines label Aug 27, 2026
…s-glob-junction
# Conflicts:
#	package-lock.json
Generated-by: OpenAI Codex
@HuYellowHuYellow changed the title fix(windows): skip nested junctions for read ACL grantsfix(windows): let Glob skip nested junctionsAug 27, 2026
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Addressed at head 82c8766b7.

  • P1: replaced the global recursive-read relaxation with a digest-bound nonFollowingReadRoot available only to read-only recursive Glob. Raw recursive reads and writes still reject nested reparse points, so the original packaged adversarial admission check remains valid.
  • Synchronized the English/Chinese RFCs, Windows sandbox README, Runtime smoke coverage, and packaged verifier. The verifier now proves broad **/* omits the junction entry and descendants while ordinary files remain visible.
  • P3: removed the skip_nested_reparse_points: bool entirely. The policy is represented by an optional canonical root and validated at the client, profile, manifest protocol, digest, and broker admission boundaries.
  • Added fail-closed planner limits for grants, inspected entries, and depth, plus hard-link/root/policy-tamper coverage.

Local results include Rust 62/62, Windows worker smoke 5/5, AppContainer smoke, raw packaged adversarial matrix, and full verify:windows-x64 including the packaged Electron worker, 64-launch soak, node-pty/ConPTY, renderer, installer, and ZIP checks.

The specialized implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling with authorship preserved. The branch is also merged with current main; the final lockfile keeps brace-expansion 5.0.9, and both generated notices are synchronized.

@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up: all current checks are green at 82c8766. The CI test job passed in 16m45s, and the Windows release package job passed in 17m28s, including Package the Windows installer and ZIP, Verify the Windows release, packaged adversarial evidence, upgrade/autoupdate, and rollback checks.

@github-actionsgithub-actionsBot added effort/XL Over 1000 readable lines and removed effort/M Under 500 readable lines labels Aug 27, 2026

@Astro-HanAstro-Han 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.

The non-following direction matches #3938, but three exact-head boundary gaps remain. Exact head is 82c8766 and current merge state is MERGEABLE/BLOCKED. Review analysis was assisted by Codex and an independent @Reviewer agent. Astro-Han verified the client→broker composition, Windows walker replacement window, normal large-tree path, and severity before publication and owns this review.

Comment threadpackages/runtime/src/filesystem-worker/client.ts Outdated
Comment threadpackages/runtime/src/filesystem-worker/operations.ts
Comment threadexperiments/windows-sandbox/launcher/src/acl_ledger.rs
Bind the unfollowed root identity, revalidate directory reads, and bound ACL planning by Glob traversal depth and directory work.
Generated-by: OpenAI Codex
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up complete at da2612040.

  • Addressed and resolved all three Aug 30 review threads: root-junction identity, cached-Dirent replacement, and >100k/root-only admission.
  • Synchronized the English/Chinese RFC, experiment README, broker protocol/digest, Runtime tests, W0 smoke, and packaged verifier.
  • All current checks are green, including Rust 64/64 + real broker worker smoke, heavy, test, Windows package, recovery, audit, and cross-platform CLI validation.

The branch remains mergeable. main advanced by five unrelated Desktop/Runtime Host/CLI/Storage commits while CI ran; none touches the Windows worker/broker paths changed here. Ready for maintainer review.

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

Labels

effort/XLOver 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(windows): Glob fails when an approved tree contains a nested junction

3 participants

@HuYellow@Astro-Han@sunrioa
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Open
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction
Open

fix(windows): let Glob skip nested junctions#3952
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction

Conversation

@HuYellow

@HuYellowHuYellow commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • bind one explicit nonFollowingReadRoot to the Windows broker manifest digest and expose it only for read-only recursive Glob operations
  • decompose that root into bounded grants for physical directories, excluding nested reparse entries and their targets while keeping raw recursive reads, writes, hard links, and a reparse-point root fail-closed
  • use a non-following Windows Glob walker that preserves Node matching, dotfile, ordering, and limit semantics, including omitting the junction entry itself from broad **/* results
  • align the English and Chinese Windows sandbox RFCs, focused tests, packaged evidence, and dependency notices with the specialized policy

Fixes#3938

The specialized-policy implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling. Their commit authorship and Generated-by trailers are preserved in this branch; the unrelated dependency-only commit was not copied. The final lockfile instead keeps the newer audit fixes already merged to main.

Verification

  • npm run build:test
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run windows:inventory
  • npm audit --registry=https://registry.npmjs.org --audit-level=high (0 vulnerabilities)
  • npm Desktop/CLI third-party notice checks and Windows Cargo notice check
  • cargo fmt --manifest-path experiments/windows-sandbox/launcher/Cargo.toml -- --check
  • cargo test --locked --manifest-path experiments/windows-sandbox/launcher/Cargo.toml (62 passed)
  • release-mode Windows broker build
  • AppContainer smoke and packaged adversarial matrix
  • focused Runtime policy/manifest/walker tests (24 passed)
  • node --test packages/runtime/dist/__tests__/filesystem-worker-windows-smoke.test.js (5 passed)
  • full verify:windows-x64 on a locally generated package, including packaged dependency closure, broker/stdio/ACL recovery, 64-launch soak, adversarial matrix, real packaged Electron worker Glob, node-pty/ConPTY, renderer, installer and ZIP hashes

The local machine has no Visual Studio C++ Build Tools, so the verification package used the already installed patched node-pty binaries (npmRebuild=false) and the exact local Electron 43.4.1 distribution instead of rebuilding native dependencies. The normal package path is left to CI. check:release reached one unrelated standalone-launcher WSL path failure after all dependency-notice and release-closure checks passed; check:asf-source is locally blocked by unavailable file-symlink privileges and gzip.

Security review focus

  • nonFollowingReadRoot is validated as a declared recursive read root, rejects every writable launch, and is included in the launch digest.
  • Raw recursive roots retain their previous whole-tree reparse rejection, so the packaged adversarial matrix remains valid.
  • The broker grants only physical directories. Reparse entries and targets receive no ledger entry or ACE.
  • Planning fails closed above 4,096 grants, 100,000 inspected entries, or 256 directory levels.
  • The worker independently excludes Windows reparse Dirents before matching or traversal, including broad **/* patterns.

AI use

Select exactly one:

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

Tool(s) and scope: OpenAI Codex implemented and integrated the specialized Windows ACL policy, non-following Glob traversal, documentation, regression coverage, conflict resolution, and local verification. Affected commits retain the required Generated-by: OpenAI Codex trailers.

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

@Astro-Han

Copy link
Copy Markdown
Contributor

I reviewed this PR at exact head 949df79d846042ba0ea037cdc115baf9f47384cf (base 2d10b52, merge-base 38f0a275, 4 files +176−16).

Spec: GO — no P0–P3

  • Root reparse points are still unconditionally rejected; recursive write still rejects the whole tree; recursive read now terminates at a nested reparse boundary (acl_ledger.rs:443-477).
  • The Windows ACL path correctly uses icacls /L /T so it does not follow the target; the real junction ACL test proves the target and its descendants do not receive the synthetic SID and verifies cleanup.
  • The filesystem-worker Windows smoke covers both ordinary main.go enumeration and the junction-descendant pattern returning empty.
  • No implemented-but-wrong / missing / scope-creep finding within bug(windows): Glob fails when an approved tree contains a nested junction #3938; the existing hard-link scan→grant race is not introduced by this diff.

Standards: NO-GO — 1 hard P1 + 1 judgment-only P3

  • P1 — governing security contract and release evidence are not in sync with the new strategy.acl_ledger.rs:443-477 now accepts a nested reparse boundary for recursive read, but docs/architecture/windows-sandbox-rfc-v1.md still requires “recursive reparse-point rejection before ACL mutation” in several places and defines the packaged recursive-junction admission refusal as W1/release evidence. adversarial-matrix-smoke.ps1:208-216 also still requires the same nested-junction read request to fail closed as before. As a result the exact-head package run 32993195237 fails directly: launcher exits 0, matrix reports Junction alias admission did not fail closed. Fix by either formally revising the RFC and the machine-readable matrix to a read traversal-boundary contract (keep root/write rejection, prove target denial with a real child) or restoring the recursive rejection.
  • Judgment-only P3:skip_nested_reparse_points: bool with bare false/true encodes a security policy as a boolean; a named enum would reduce inversion risk.

Other checks: git diff --check passes. windows_recovery and windows_sandbox_w0_protocol are green; package is red for the reason above (directly related), test is red due to an unrelated Desktop prompt-rail E2E (66 pass / 1 fail / 1 skip). OPEN / MERGEABLE / REVIEW_REQUIRED, no reviews/comments, head did not drift.

What I did not check: full local test suite beyond the focused checks noted.

Gate: exact head has no P0–P2, but the P1 standards finding and the failing required package/test checks must be closed (update RFC + adversarial-matrix-smoke.ps1 to match the new read-boundary contract, or restore rejection) before merge.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@github-actionsgithub-actionsBot added the effort/M Under 500 readable lines label Aug 27, 2026
…s-glob-junction
# Conflicts:
#	package-lock.json
Generated-by: OpenAI Codex
@HuYellowHuYellow changed the title fix(windows): skip nested junctions for read ACL grantsfix(windows): let Glob skip nested junctionsAug 27, 2026
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Addressed at head 82c8766b7.

  • P1: replaced the global recursive-read relaxation with a digest-bound nonFollowingReadRoot available only to read-only recursive Glob. Raw recursive reads and writes still reject nested reparse points, so the original packaged adversarial admission check remains valid.
  • Synchronized the English/Chinese RFCs, Windows sandbox README, Runtime smoke coverage, and packaged verifier. The verifier now proves broad **/* omits the junction entry and descendants while ordinary files remain visible.
  • P3: removed the skip_nested_reparse_points: bool entirely. The policy is represented by an optional canonical root and validated at the client, profile, manifest protocol, digest, and broker admission boundaries.
  • Added fail-closed planner limits for grants, inspected entries, and depth, plus hard-link/root/policy-tamper coverage.

Local results include Rust 62/62, Windows worker smoke 5/5, AppContainer smoke, raw packaged adversarial matrix, and full verify:windows-x64 including the packaged Electron worker, 64-launch soak, node-pty/ConPTY, renderer, installer, and ZIP checks.

The specialized implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling with authorship preserved. The branch is also merged with current main; the final lockfile keeps brace-expansion 5.0.9, and both generated notices are synchronized.

@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up: all current checks are green at 82c8766. The CI test job passed in 16m45s, and the Windows release package job passed in 17m28s, including Package the Windows installer and ZIP, Verify the Windows release, packaged adversarial evidence, upgrade/autoupdate, and rollback checks.

@github-actionsgithub-actionsBot added effort/XL Over 1000 readable lines and removed effort/M Under 500 readable lines labels Aug 27, 2026

@Astro-HanAstro-Han 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.

The non-following direction matches #3938, but three exact-head boundary gaps remain. Exact head is 82c8766 and current merge state is MERGEABLE/BLOCKED. Review analysis was assisted by Codex and an independent @Reviewer agent. Astro-Han verified the client→broker composition, Windows walker replacement window, normal large-tree path, and severity before publication and owns this review.

Comment threadpackages/runtime/src/filesystem-worker/client.ts Outdated
Comment threadpackages/runtime/src/filesystem-worker/operations.ts
Comment threadexperiments/windows-sandbox/launcher/src/acl_ledger.rs
Bind the unfollowed root identity, revalidate directory reads, and bound ACL planning by Glob traversal depth and directory work.
Generated-by: OpenAI Codex
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up complete at da2612040.

  • Addressed and resolved all three Aug 30 review threads: root-junction identity, cached-Dirent replacement, and >100k/root-only admission.
  • Synchronized the English/Chinese RFC, experiment README, broker protocol/digest, Runtime tests, W0 smoke, and packaged verifier.
  • All current checks are green, including Rust 64/64 + real broker worker smoke, heavy, test, Windows package, recovery, audit, and cross-platform CLI validation.

The branch remains mergeable. main advanced by five unrelated Desktop/Runtime Host/CLI/Storage commits while CI ran; none touches the Windows worker/broker paths changed here. Ready for maintainer review.

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

Labels

effort/XLOver 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(windows): Glob fails when an approved tree contains a nested junction

3 participants

@HuYellow@Astro-Han@sunrioa
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Open
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction
Open

fix(windows): let Glob skip nested junctions#3952
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction

Conversation

@HuYellow

@HuYellowHuYellow commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • bind one explicit nonFollowingReadRoot to the Windows broker manifest digest and expose it only for read-only recursive Glob operations
  • decompose that root into bounded grants for physical directories, excluding nested reparse entries and their targets while keeping raw recursive reads, writes, hard links, and a reparse-point root fail-closed
  • use a non-following Windows Glob walker that preserves Node matching, dotfile, ordering, and limit semantics, including omitting the junction entry itself from broad **/* results
  • align the English and Chinese Windows sandbox RFCs, focused tests, packaged evidence, and dependency notices with the specialized policy

Fixes#3938

The specialized-policy implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling. Their commit authorship and Generated-by trailers are preserved in this branch; the unrelated dependency-only commit was not copied. The final lockfile instead keeps the newer audit fixes already merged to main.

Verification

  • npm run build:test
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run windows:inventory
  • npm audit --registry=https://registry.npmjs.org --audit-level=high (0 vulnerabilities)
  • npm Desktop/CLI third-party notice checks and Windows Cargo notice check
  • cargo fmt --manifest-path experiments/windows-sandbox/launcher/Cargo.toml -- --check
  • cargo test --locked --manifest-path experiments/windows-sandbox/launcher/Cargo.toml (62 passed)
  • release-mode Windows broker build
  • AppContainer smoke and packaged adversarial matrix
  • focused Runtime policy/manifest/walker tests (24 passed)
  • node --test packages/runtime/dist/__tests__/filesystem-worker-windows-smoke.test.js (5 passed)
  • full verify:windows-x64 on a locally generated package, including packaged dependency closure, broker/stdio/ACL recovery, 64-launch soak, adversarial matrix, real packaged Electron worker Glob, node-pty/ConPTY, renderer, installer and ZIP hashes

The local machine has no Visual Studio C++ Build Tools, so the verification package used the already installed patched node-pty binaries (npmRebuild=false) and the exact local Electron 43.4.1 distribution instead of rebuilding native dependencies. The normal package path is left to CI. check:release reached one unrelated standalone-launcher WSL path failure after all dependency-notice and release-closure checks passed; check:asf-source is locally blocked by unavailable file-symlink privileges and gzip.

Security review focus

  • nonFollowingReadRoot is validated as a declared recursive read root, rejects every writable launch, and is included in the launch digest.
  • Raw recursive roots retain their previous whole-tree reparse rejection, so the packaged adversarial matrix remains valid.
  • The broker grants only physical directories. Reparse entries and targets receive no ledger entry or ACE.
  • Planning fails closed above 4,096 grants, 100,000 inspected entries, or 256 directory levels.
  • The worker independently excludes Windows reparse Dirents before matching or traversal, including broad **/* patterns.

AI use

Select exactly one:

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

Tool(s) and scope: OpenAI Codex implemented and integrated the specialized Windows ACL policy, non-following Glob traversal, documentation, regression coverage, conflict resolution, and local verification. Affected commits retain the required Generated-by: OpenAI Codex trailers.

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

@Astro-Han

Copy link
Copy Markdown
Contributor

I reviewed this PR at exact head 949df79d846042ba0ea037cdc115baf9f47384cf (base 2d10b52, merge-base 38f0a275, 4 files +176−16).

Spec: GO — no P0–P3

  • Root reparse points are still unconditionally rejected; recursive write still rejects the whole tree; recursive read now terminates at a nested reparse boundary (acl_ledger.rs:443-477).
  • The Windows ACL path correctly uses icacls /L /T so it does not follow the target; the real junction ACL test proves the target and its descendants do not receive the synthetic SID and verifies cleanup.
  • The filesystem-worker Windows smoke covers both ordinary main.go enumeration and the junction-descendant pattern returning empty.
  • No implemented-but-wrong / missing / scope-creep finding within bug(windows): Glob fails when an approved tree contains a nested junction #3938; the existing hard-link scan→grant race is not introduced by this diff.

Standards: NO-GO — 1 hard P1 + 1 judgment-only P3

  • P1 — governing security contract and release evidence are not in sync with the new strategy.acl_ledger.rs:443-477 now accepts a nested reparse boundary for recursive read, but docs/architecture/windows-sandbox-rfc-v1.md still requires “recursive reparse-point rejection before ACL mutation” in several places and defines the packaged recursive-junction admission refusal as W1/release evidence. adversarial-matrix-smoke.ps1:208-216 also still requires the same nested-junction read request to fail closed as before. As a result the exact-head package run 32993195237 fails directly: launcher exits 0, matrix reports Junction alias admission did not fail closed. Fix by either formally revising the RFC and the machine-readable matrix to a read traversal-boundary contract (keep root/write rejection, prove target denial with a real child) or restoring the recursive rejection.
  • Judgment-only P3:skip_nested_reparse_points: bool with bare false/true encodes a security policy as a boolean; a named enum would reduce inversion risk.

Other checks: git diff --check passes. windows_recovery and windows_sandbox_w0_protocol are green; package is red for the reason above (directly related), test is red due to an unrelated Desktop prompt-rail E2E (66 pass / 1 fail / 1 skip). OPEN / MERGEABLE / REVIEW_REQUIRED, no reviews/comments, head did not drift.

What I did not check: full local test suite beyond the focused checks noted.

Gate: exact head has no P0–P2, but the P1 standards finding and the failing required package/test checks must be closed (update RFC + adversarial-matrix-smoke.ps1 to match the new read-boundary contract, or restore rejection) before merge.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@github-actionsgithub-actionsBot added the effort/M Under 500 readable lines label Aug 27, 2026
…s-glob-junction
# Conflicts:
#	package-lock.json
Generated-by: OpenAI Codex
@HuYellowHuYellow changed the title fix(windows): skip nested junctions for read ACL grantsfix(windows): let Glob skip nested junctionsAug 27, 2026
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Addressed at head 82c8766b7.

  • P1: replaced the global recursive-read relaxation with a digest-bound nonFollowingReadRoot available only to read-only recursive Glob. Raw recursive reads and writes still reject nested reparse points, so the original packaged adversarial admission check remains valid.
  • Synchronized the English/Chinese RFCs, Windows sandbox README, Runtime smoke coverage, and packaged verifier. The verifier now proves broad **/* omits the junction entry and descendants while ordinary files remain visible.
  • P3: removed the skip_nested_reparse_points: bool entirely. The policy is represented by an optional canonical root and validated at the client, profile, manifest protocol, digest, and broker admission boundaries.
  • Added fail-closed planner limits for grants, inspected entries, and depth, plus hard-link/root/policy-tamper coverage.

Local results include Rust 62/62, Windows worker smoke 5/5, AppContainer smoke, raw packaged adversarial matrix, and full verify:windows-x64 including the packaged Electron worker, 64-launch soak, node-pty/ConPTY, renderer, installer, and ZIP checks.

The specialized implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling with authorship preserved. The branch is also merged with current main; the final lockfile keeps brace-expansion 5.0.9, and both generated notices are synchronized.

@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up: all current checks are green at 82c8766. The CI test job passed in 16m45s, and the Windows release package job passed in 17m28s, including Package the Windows installer and ZIP, Verify the Windows release, packaged adversarial evidence, upgrade/autoupdate, and rollback checks.

@github-actionsgithub-actionsBot added effort/XL Over 1000 readable lines and removed effort/M Under 500 readable lines labels Aug 27, 2026

@Astro-HanAstro-Han 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.

The non-following direction matches #3938, but three exact-head boundary gaps remain. Exact head is 82c8766 and current merge state is MERGEABLE/BLOCKED. Review analysis was assisted by Codex and an independent @Reviewer agent. Astro-Han verified the client→broker composition, Windows walker replacement window, normal large-tree path, and severity before publication and owns this review.

Comment threadpackages/runtime/src/filesystem-worker/client.ts Outdated
Comment threadpackages/runtime/src/filesystem-worker/operations.ts
Comment threadexperiments/windows-sandbox/launcher/src/acl_ledger.rs
Bind the unfollowed root identity, revalidate directory reads, and bound ACL planning by Glob traversal depth and directory work.
Generated-by: OpenAI Codex
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up complete at da2612040.

  • Addressed and resolved all three Aug 30 review threads: root-junction identity, cached-Dirent replacement, and >100k/root-only admission.
  • Synchronized the English/Chinese RFC, experiment README, broker protocol/digest, Runtime tests, W0 smoke, and packaged verifier.
  • All current checks are green, including Rust 64/64 + real broker worker smoke, heavy, test, Windows package, recovery, audit, and cross-platform CLI validation.

The branch remains mergeable. main advanced by five unrelated Desktop/Runtime Host/CLI/Storage commits while CI ran; none touches the Windows worker/broker paths changed here. Ready for maintainer review.

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

Labels

effort/XLOver 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(windows): Glob fails when an approved tree contains a nested junction

3 participants

@HuYellow@Astro-Han@sunrioa
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

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

Open
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction
Open

fix(windows): let Glob skip nested junctions#3952
HuYellow wants to merge 12 commits into
apache:mainfrom
HuYellow:codex/fix-3938-windows-glob-junction

Conversation

@HuYellow

@HuYellowHuYellow commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • bind one explicit nonFollowingReadRoot to the Windows broker manifest digest and expose it only for read-only recursive Glob operations
  • decompose that root into bounded grants for physical directories, excluding nested reparse entries and their targets while keeping raw recursive reads, writes, hard links, and a reparse-point root fail-closed
  • use a non-following Windows Glob walker that preserves Node matching, dotfile, ordering, and limit semantics, including omitting the junction entry itself from broad **/* results
  • align the English and Chinese Windows sandbox RFCs, focused tests, packaged evidence, and dependency notices with the specialized policy

Fixes#3938

The specialized-policy implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling. Their commit authorship and Generated-by trailers are preserved in this branch; the unrelated dependency-only commit was not copied. The final lockfile instead keeps the newer audit fixes already merged to main.

Verification

  • npm run build:test
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • npm run windows:inventory
  • npm audit --registry=https://registry.npmjs.org --audit-level=high (0 vulnerabilities)
  • npm Desktop/CLI third-party notice checks and Windows Cargo notice check
  • cargo fmt --manifest-path experiments/windows-sandbox/launcher/Cargo.toml -- --check
  • cargo test --locked --manifest-path experiments/windows-sandbox/launcher/Cargo.toml (62 passed)
  • release-mode Windows broker build
  • AppContainer smoke and packaged adversarial matrix
  • focused Runtime policy/manifest/walker tests (24 passed)
  • node --test packages/runtime/dist/__tests__/filesystem-worker-windows-smoke.test.js (5 passed)
  • full verify:windows-x64 on a locally generated package, including packaged dependency closure, broker/stdio/ACL recovery, 64-launch soak, adversarial matrix, real packaged Electron worker Glob, node-pty/ConPTY, renderer, installer and ZIP hashes

The local machine has no Visual Studio C++ Build Tools, so the verification package used the already installed patched node-pty binaries (npmRebuild=false) and the exact local Electron 43.4.1 distribution instead of rebuilding native dependencies. The normal package path is left to CI. check:release reached one unrelated standalone-launcher WSL path failure after all dependency-notice and release-closure checks passed; check:asf-source is locally blocked by unavailable file-symlink privileges and gzip.

Security review focus

  • nonFollowingReadRoot is validated as a declared recursive read root, rejects every writable launch, and is included in the launch digest.
  • Raw recursive roots retain their previous whole-tree reparse rejection, so the packaged adversarial matrix remains valid.
  • The broker grants only physical directories. Reparse entries and targets receive no ledger entry or ACE.
  • Planning fails closed above 4,096 grants, 100,000 inspected entries, or 256 directory levels.
  • The worker independently excludes Windows reparse Dirents before matching or traversal, including broad **/* patterns.

AI use

Select exactly one:

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

Tool(s) and scope: OpenAI Codex implemented and integrated the specialized Windows ACL policy, non-following Glob traversal, documentation, regression coverage, conflict resolution, and local verification. Affected commits retain the required Generated-by: OpenAI Codex trailers.

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

@Astro-Han

Copy link
Copy Markdown
Contributor

I reviewed this PR at exact head 949df79d846042ba0ea037cdc115baf9f47384cf (base 2d10b52, merge-base 38f0a275, 4 files +176−16).

Spec: GO — no P0–P3

  • Root reparse points are still unconditionally rejected; recursive write still rejects the whole tree; recursive read now terminates at a nested reparse boundary (acl_ledger.rs:443-477).
  • The Windows ACL path correctly uses icacls /L /T so it does not follow the target; the real junction ACL test proves the target and its descendants do not receive the synthetic SID and verifies cleanup.
  • The filesystem-worker Windows smoke covers both ordinary main.go enumeration and the junction-descendant pattern returning empty.
  • No implemented-but-wrong / missing / scope-creep finding within bug(windows): Glob fails when an approved tree contains a nested junction #3938; the existing hard-link scan→grant race is not introduced by this diff.

Standards: NO-GO — 1 hard P1 + 1 judgment-only P3

  • P1 — governing security contract and release evidence are not in sync with the new strategy.acl_ledger.rs:443-477 now accepts a nested reparse boundary for recursive read, but docs/architecture/windows-sandbox-rfc-v1.md still requires “recursive reparse-point rejection before ACL mutation” in several places and defines the packaged recursive-junction admission refusal as W1/release evidence. adversarial-matrix-smoke.ps1:208-216 also still requires the same nested-junction read request to fail closed as before. As a result the exact-head package run 32993195237 fails directly: launcher exits 0, matrix reports Junction alias admission did not fail closed. Fix by either formally revising the RFC and the machine-readable matrix to a read traversal-boundary contract (keep root/write rejection, prove target denial with a real child) or restoring the recursive rejection.
  • Judgment-only P3:skip_nested_reparse_points: bool with bare false/true encodes a security policy as a boolean; a named enum would reduce inversion risk.

Other checks: git diff --check passes. windows_recovery and windows_sandbox_w0_protocol are green; package is red for the reason above (directly related), test is red due to an unrelated Desktop prompt-rail E2E (66 pass / 1 fail / 1 skip). OPEN / MERGEABLE / REVIEW_REQUIRED, no reviews/comments, head did not drift.

What I did not check: full local test suite beyond the focused checks noted.

Gate: exact head has no P0–P2, but the P1 standards finding and the failing required package/test checks must be closed (update RFC + adversarial-matrix-smoke.ps1 to match the new read-boundary contract, or restore rejection) before merge.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@github-actionsgithub-actionsBot added the effort/M Under 500 readable lines label Aug 27, 2026
…s-glob-junction
# Conflicts:
#	package-lock.json
Generated-by: OpenAI Codex
@HuYellowHuYellow changed the title fix(windows): skip nested junctions for read ACL grantsfix(windows): let Glob skip nested junctionsAug 27, 2026
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Addressed at head 82c8766b7.

  • P1: replaced the global recursive-read relaxation with a digest-bound nonFollowingReadRoot available only to read-only recursive Glob. Raw recursive reads and writes still reject nested reparse points, so the original packaged adversarial admission check remains valid.
  • Synchronized the English/Chinese RFCs, Windows sandbox README, Runtime smoke coverage, and packaged verifier. The verifier now proves broad **/* omits the junction entry and descendants while ordinary files remain visible.
  • P3: removed the skip_nested_reparse_points: bool entirely. The policy is represented by an optional canonical root and validated at the client, profile, manifest protocol, digest, and broker admission boundaries.
  • Added fail-closed planner limits for grants, inspected entries, and depth, plus hard-link/root/policy-tamper coverage.

Local results include Rust 62/62, Windows worker smoke 5/5, AppContainer smoke, raw packaged adversarial matrix, and full verify:windows-x64 including the packaged Electron worker, 64-launch soak, node-pty/ConPTY, renderer, installer, and ZIP checks.

The specialized implementation incorporates the three functional commits from #3955 by @sunrioa and @Ling with authorship preserved. The branch is also merged with current main; the final lockfile keeps brace-expansion 5.0.9, and both generated notices are synchronized.

@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up: all current checks are green at 82c8766. The CI test job passed in 16m45s, and the Windows release package job passed in 17m28s, including Package the Windows installer and ZIP, Verify the Windows release, packaged adversarial evidence, upgrade/autoupdate, and rollback checks.

@github-actionsgithub-actionsBot added effort/XL Over 1000 readable lines and removed effort/M Under 500 readable lines labels Aug 27, 2026

@Astro-HanAstro-Han 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.

The non-following direction matches #3938, but three exact-head boundary gaps remain. Exact head is 82c8766 and current merge state is MERGEABLE/BLOCKED. Review analysis was assisted by Codex and an independent @Reviewer agent. Astro-Han verified the client→broker composition, Windows walker replacement window, normal large-tree path, and severity before publication and owns this review.

Comment threadpackages/runtime/src/filesystem-worker/client.ts Outdated
Comment threadpackages/runtime/src/filesystem-worker/operations.ts
Comment threadexperiments/windows-sandbox/launcher/src/acl_ledger.rs
Bind the unfollowed root identity, revalidate directory reads, and bound ACL planning by Glob traversal depth and directory work.
Generated-by: OpenAI Codex
@HuYellow

Copy link
Copy Markdown
ContributorAuthor

Follow-up complete at da2612040.

  • Addressed and resolved all three Aug 30 review threads: root-junction identity, cached-Dirent replacement, and >100k/root-only admission.
  • Synchronized the English/Chinese RFC, experiment README, broker protocol/digest, Runtime tests, W0 smoke, and packaged verifier.
  • All current checks are green, including Rust 64/64 + real broker worker smoke, heavy, test, Windows package, recovery, audit, and cross-platform CLI validation.

The branch remains mergeable. main advanced by five unrelated Desktop/Runtime Host/CLI/Storage commits while CI ran; none touches the Windows worker/broker paths changed here. Ready for maintainer review.

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

Labels

effort/XLOver 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(windows): Glob fails when an approved tree contains a nested junction

3 participants

@HuYellow@Astro-Han@sunrioa