Skip to content

Add native Windows sandbox helper / 添加原生 Windows 沙箱 helper#5937

Merged
SivanCola merged 10 commits into
esengine:main-v2from
SivanCola:feature/windows-native-sandbox
Jul 5, 2026
Merged

Add native Windows sandbox helper / 添加原生 Windows 沙箱 helper#5937
SivanCola merged 10 commits into
esengine:main-v2from
SivanCola:feature/windows-native-sandbox

Conversation

@SivanCola

@SivanCola SivanCola commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add native Windows sandbox support through a hidden Reasonix helper that delegates low-level isolation to github.com/SivanCola/windows-sandbox
  • initialize SivanCola/windows-sandbox as the reusable Go module for AppContainer read-only launches, low-integrity writable launches, temporary ACL grants/denies, per-command temp roots, DACL cleanup, and kill-on-close Job Objects
  • keep Reasonix-specific policy in this repo: payload encoding, sandbox.Spec conversion, helper routing, bash integration, docs, and focused adapter tests
  • add a Windows CI integration test that runs the Reasonix hidden helper through the external sandbox and verifies workspace writes are allowed while outside writes are denied
  • expand the external windows-sandbox Windows CI matrix to cover writable/read-only launches, forbid-read in both modes, network-disabled AppContainer, stdio/env/cwd/exit-code propagation, paths with spaces, child process cleanup, timeout handling, and ACL cleanup
  • fix a detailed-test finding in windows-sandbox: read-only AppContainer forbid-read now also adds a temporary deny ACE for the current user SID, so normal file ACLs cannot bypass the deny root

Cache-impact: none - changes do not alter provider-visible prompts, tool schemas, ordering, or request serialization; the builtin touch is test-only.
Cache-guard: REASONIX_RELEASE_CACHE_GUARD=1 go test -p 4 -timeout=3m ./... plus existing cache-impact CI check.

Verification

  • windows-sandbox: go test ./...
  • windows-sandbox: GOOS=windows GOARCH=amd64 go test -c . -o /tmp/windows-sandbox.test.exe
  • windows-sandbox GitHub Actions CI: success on 5d2d7ea7104bd458c2956a97abfea4b8036bf345
  • Reasonix: GOOS=windows GOARCH=amd64 go test -c ./internal/sandbox -o /tmp/reasonix-sandbox.test.exe
  • Reasonix: GOOS=windows GOARCH=amd64 go test -c ./internal/tool/builtin -o /tmp/reasonix-builtin.test.exe
  • Reasonix: GOOS=windows GOARCH=amd64 go test -c ./cmd/reasonix -o /tmp/reasonix.exe
  • Reasonix: go test -count=1 ./internal/sandbox ./internal/tool/builtin ./internal/proc ./internal/cli ./internal/doctor ./cmd/reasonix
  • Reasonix desktop: go test ./...
  • Reasonix: go vet ./...
  • Reasonix: go build ./...
  • Reasonix: go test -p 4 -timeout=3m ./...
  • Reasonix: git diff --check

@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development tui Terminal UI / CLI (internal/cli, internal/control) and removed v2 Go rewrite (1.x) — main-v2 branch, active development labels Jul 4, 2026
@SivanCola SivanCola force-pushed the feature/windows-native-sandbox branch 5 times, most recently from 5f027a8 to 95ff5bb Compare July 4, 2026 17:28
@github-actions github-actions Bot added skills Skill system (internal/skill, internal/tool) v2 Go rewrite (1.x) — main-v2 branch, active development labels Jul 4, 2026
@SivanCola SivanCola force-pushed the feature/windows-native-sandbox branch 20 times, most recently from 363620e to 83e737f Compare July 4, 2026 20:48
@SivanCola SivanCola force-pushed the feature/windows-native-sandbox branch 14 times, most recently from b89486a to 66f6053 Compare July 5, 2026 00:59
@github-actions github-actions Bot added the desktop Wails desktop app (desktop/**) label Jul 5, 2026
@SivanCola SivanCola marked this pull request as ready for review July 5, 2026 02:23
@SivanCola SivanCola requested a review from esengine as a code owner July 5, 2026 02:23
SivanCola added 7 commits July 5, 2026 14:44
Update the native Windows sandbox backend to the release that fixes the
mutation-based-isolation failure modes: recursive icacls timeout on large
workspaces, residual Low integrity labels after cleanup, concurrent runs
corrupting each other's ACL boundary, forbid_read deny residue after a crash,
forbid_read entries pointing at files being silently unprotected, and
PATH-resolved icacls/taskkill.

Correct the docs to match the actual Windows boundary: writable low-integrity
commands can still write the narrow set of locations Windows leaves writable to
any low-integrity process (e.g. AppData\LocalLow) in addition to the configured
roots, concurrent commands on a shared workspace are serialized, forbid_read
now covers files, and crash residue is swept by the next run.
Pick up the follow-up that pins the per-root lock to one OS thread, so a Go
goroutine migrating threads cannot release a Windows mutex from a non-owning
thread or re-enter it within the process. Cross-process serialization (each
sandboxed command is its own helper process) was already correct; this
tightens the within-process semantics the library's unit tests cover.
Picks up two upstream fixes: exe-dir contention coverage with the
close of the deny-residue window (2a86cf8, 0e09612), and the follow-up
that stops grantAppContainerExecutable from snapshotting, granting, or
recording crash-residue on system directories (1a3e77e) — previously a
crashed elevated run could leave a residue marker that made the next
run strip built-in package SIDs from System32 / Program Files ACLs.
@SivanCola SivanCola force-pushed the feature/windows-native-sandbox branch from e79ad5e to 39bfc0b Compare July 5, 2026 06:49
Picks up the follow-up (3058fd1) that re-checks the system-root
invariant at sweep time: the crash-residue marker lives in the user's
%TEMP% and is untrusted, so a legacy or planted line naming System32 /
Program Files could previously drive the next run's sweep to strip the
broad built-in package SIDs from a system directory's factory ACLs. The
sweep now refuses system paths independently of the recorder-side
filter.
SivanCola added 2 commits July 5, 2026 23:06
Picks up b79e9a5: the crash-residue marker is keyed by PID alone, so a
helper process that drew a crashed predecessor's PID used to skip the
stale marker in its run-start sweep (pid == self), append its own lines
into the same file, and then delete the whole file on exit — orphaning
the predecessor's forbid_read deny or tool-directory grant beyond any
future sweep's reach. The library now tracks marker ownership
in-process: cleanup only deletes a marker this process wrote, and an
unowned file at the run's own PID is consumed at run start as a dead
predecessor's residue. The filename stays <pid>.txt so older binaries
sharing the marker directory keep parsing PIDs correctly during
upgrade windows.
@SivanCola SivanCola merged commit 4065a62 into esengine:main-v2 Jul 5, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

desktop Wails desktop app (desktop/**) skills Skill system (internal/skill, internal/tool) tui Terminal UI / CLI (internal/cli, internal/control) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant