Skip to content

fix(launcher): protect Windows credentials and backup archives - #3

Draft
1932819331hy-debug wants to merge 4 commits into
review/launcher-private-files-base-20261019-2ee0from
fix/launcher-private-files-20261019-2ee0
Draft

1932819331hy-debug wants to merge 4 commits into
review/launcher-private-files-base-20261019-2ee0from
fix/launcher-private-files-20261019-2ee0

Conversation

@1932819331hy-debug

@1932819331hy-debug 1932819331hy-debug commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Problem and change

The Windows launcher used POSIX modes to protect provider-key directories and CLI-settings / Space-Memory backup archives. Those modes do not remove inherited Windows read grants. The patch creates and verifies protected Windows DACLs before writing new private data, while preserving POSIX behavior.

Current candidate: e9b52a5f04c5c2ad2215eda52e8f46fa762956c6, tree c68f0cf1210725a7f2f94e724760d5867671d39f, based on upstream adb96ac77531649bd335078aacaa0318ce1d20a2.

This two-parent merge combines the four-platform-tested launcher revision 607985bc909372ca0e6c4344b4be359df2577ec0 with the separately reviewed watchdog assertion correction, upstream #212, 47399bf2f3f1e405653394e8cdf3064b9b044201. Relative to the launcher parent, the entire repository changes by exactly that one test assertion. All 37 launcher paths, modes, and blobs remain identical; launcher subtree 1f6e6aee3a403e84451cb6e21eaac3b58dfbcbe0 is preserved.

Implementation

  • Create Windows private directories with their protected security descriptor at creation, granting only the current account, SYSTEM, and local Administrators.
  • Verify owner, inheritance protection, and exact SID grants. Reject directly writable or replaceable storage and reparse points before use.
  • Run the system Windows PowerShell executable through an absolute path. Supply paths as environment data to fixed scripts and use literal-path operations.
  • Export archives through protected staging; verify an explicit file DACL before streaming data and preserve it on a same-volume rename.
  • Inspect real Windows ACLs independently in tests, including a legacy-mode negative control, readable-parent success, writable-parent rejection, credential replacement, and final archive checks.
  • Preserve POSIX permission checks and supply explicit Linux metadata to the simulated Linux workspace-hint test.
  • Normalize the child Windows PowerShell module path, including case-variant inherited environment keys, to address the module-loading failure observed in the initial real Windows run.

Fresh validation on the current source tree

The hosted jobs use checkout 68dfb700d221ef2b477aa8a1bad310afcc70d291, with parents adb96ac… and e9b52a5…. Its complete tree exactly matches the published candidate's c68f0cf….

Launcher platform matrix: all four jobs pass.

Platform Complete launcher suite Related tests New permission tests
Windows / Node 24 184 pass, 0 fail, 2 existing skips 19/19 6/6
Windows / Node 22.23.0 184 pass, 0 fail, 2 existing skips 19/19 6/6
macOS / Node 22.23.0 186 pass, 0 fail, 0 skips 19/19 6/6
Ubuntu / Node 22.23.0 186 pass, 0 fail, 0 skips 19/19 6/6

All four also pass the launcher check, pack dry run, and CLI --version. The Windows skips are the original Linux-browser and macOS-Docker shell-fixture tests; no new permission test is skipped.

Source, dependencies, and SBOM: pass. The complete npm run test:public command succeeds, including watchdog 9/9, API 3036 passed / 15 existing skips, Web 3312 passed, and Worker 228 passed. The subsequent export verification succeeds with sourceCommit=68dfb700…, 4724 files, zero transformations. The npm audit, secret scan, configured blocking filesystem scan, and SBOM steps pass. CodeQL and all three image scans also pass in this Security run. These are successes under the existing scan configurations, not a statement that every possible finding is absent.

The container matrix also completed successfully: all six core, CLI, and browser jobs across linux/amd64 and linux/arm64 passed their Docker build/load and image-size budget steps. This verifies those builds and configured size limits; it does not establish runtime health, native ARM hardware behavior, or image publication (push: false).

Independent generated-candidate validation

The original export script was run from a clean checkout of e9b52a5…. Its independent output records that source commit, 4724 files, and zero transformations. Every exported file's source blob, SHA-256, length, and executable mode matches the source, including after build and pack.

That output independently passes the original commands npm ci, npm run check, npm run build, and npm run pack:dry-run -w run-spaceapp. Local versions are Node 22.23.3 / npm 11.9.0 / rg 15.2.0 / ffmpeg 6.1.1; hosted source tests use Node 22.23.0 / npm 10.9.8. The first local pack attempt selected an inherited read-only npm cache; normalizing the verification runner's cache environment made the same command pass. Its original failure log is retained. Repository code and workflows were unchanged.

The complete public suite was actually executed in the hosted Source job, and was not directly rerun in the independent output. Its identical exported code, test command, and dependency lock support reuse of that source-test evidence. The generated manifest, absence of .git, and 13 excluded documentation/configuration paths remain explicit context differences; the existing Git-only real-manifest test has a documented source/export distinction.

Remaining repository gates

Original Sanitized CI: failed at Verify export provenance. Its sole mismatch is apps/api/tests/room-watchdog.test.ts against the historical maintainer export manifest. Candidate creation and subsequent tests/check/build/pack did not execute in that job. The original manifest, producer, verifier, and workflow remain unchanged. Independent generated-candidate validation does not change that job's result.

Dependency review: failed before a dependency verdict. The pinned action emits its availability message for HTTP 403. The actual dependency-graph setting is not established. GitHub supports dependency graphs on forks, while its dependency-review compare API separately lists fork use as a 403 condition. Enabling a graph or submitting snapshots is not a demonstrated fix. The supported review path is the unchanged check in an eligible upstream PR context, with maintainer approval when required.

Scope and upstream coordination

The launcher patch changes nine files under packages/run-spaceapp; this validation branch additionally includes the one-line watchdog test correction. It remains separate from dev-stack PR #181, whose issue excludes launcher behavior changes.

SPACEAPP_HOME and higher ancestors must be controlled by the current account or administrators. Unsupported ACL enforcement fails closed. The helper does not establish isolation from those trusted principals or repair all previously exported files or existing open handles.

This is an existing public fork draft. No new upstream public launcher PR or private report has been submitted. Upstream SECURITY.md requests private reporting and coordinated disclosure. Existing public mode-assertion failures and this fork's prior publication do not establish maintainer approval to disclose the permission finding further.

Historical evidence

  • Initial launcher run: Linux/macOS pass; Windows fails to load the Windows PowerShell ACL module after inheriting PowerShell 7 paths through Node. Revision 607985bc… corrects the environment; its ACL script is unchanged. Microsoft documents this intermediate-process behavior.
  • Launcher parent 607985bc…: all four platform jobs pass on checkout e646ab6d…, tree 969879ac…, identical to that parent.
  • That parent's Sanitized run: provenance and launcher tests pass; the original watchdog latest-event assertion fails. The current merge integrates the separately reviewed persistence assertion. The old failed run retains its actual result.

AI-assisted implementation and independent review; this record distinguishes tested behavior, repository gates, and upstream acceptance.

Create private Windows directories with protected security descriptors before any private payload exists. Verify exact SID grants, reject writable or replaceable immediate parent/provider directories, use trusted system PowerShell and literal path data, and fail closed on unverified permissions.

Stage backup exports privately and preserve explicit file DACLs through same-volume rename. Keep POSIX 0700/0600 and replace Windows mode-only assertions with independent ACL checks and adversarial shared-directory controls. Make simulated Linux workspace permission hints use Linux metadata.

Separate launcher fix based on actual upstream adb96ac; not part of dev-stack PR oll4com#181. Final focused Linux Node 24 validation: 19/19. Windows hosted validation pending.
A launcher started through PowerShell 7 inherits module paths via Node that prevent Windows PowerShell 5.1 from loading Get-Acl. Remove inherited PSModulePath keys case-insensitively and initialize the ACL subprocess with its own system Modules path. Apply equivalent initialization to the independent ACL test reader.

Retain the ACL script byte-for-byte. Add environment-key/path assertions: old implementation fails the new case, and all 19 focused tests pass with both conflicting path spellings injected. Real Windows validation must rerun.
Integrate the one-line test correction from upstream PR oll4com#212 so full
sanitized CI can validate the Windows launcher candidate. The complete
packages/run-spaceapp subtree is unchanged from 607985b.

Reviewed tree: c68f0cf.
Fresh combined-head CI remains required.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant