Skip to content

feat(runtime): add Linux filesystem worker and one-shot permissions - #1399

Merged
Astro-Han merged 16 commits into
apache:mainfrom
Mingqwqqaq:feat/linux-filesystem-worker
Jul 27, 2026
Merged

feat(runtime): add Linux filesystem worker and one-shot permissions#1399
Astro-Han merged 16 commits into
apache:mainfrom
Mingqwqqaq:feat/linux-filesystem-worker

Conversation

@Mingqwqqaq

Copy link
Copy Markdown
Contributor

Summary

  • enable the sandboxed filesystem worker for Linux in both CLI and Desktop, covering Read, Write, Edit, Glob, and Grep under the active PermissionProfile
  • enable Linux one-shot permission planning for file tools and Bash, including additional filesystem permissions and explicit require_escalated execution
  • pass bubblewrap seccomp descriptors into filesystem workers and mount the worker bundle, runtime, and trusted executables required inside the sandbox
  • support exact writes to missing files without granting the operation-scoped worker unrestricted access to sibling paths

Why

The Linux sandbox previously enforced command isolation, cwd canonicalization, realpath checks, and symlink containment, but the full filesystem-worker path and one-shot permission flow were gated to macOS. As a result, Linux hosts could not use the same operation-scoped file isolation or explicit one-call permission UX.

The worker also dropped Linux sandbox FD inputs, and bubblewrap did not receive all runtime resources needed to launch the worker and its trusted Grep helper.

Security model

For a missing exact write, bubblewrap exposes the containing directory only to the trusted single-operation worker. The worker request remains exact-path scoped, permission-hash bound, target-type checked, and symlink/realpath revalidated before the operation. The Linux smoke test verifies that the approved target succeeds while a sibling remains denied.

An otherwise-unmounted cwd is materialized as an empty directory rather than mounting its contents. Network-restricted workers retain a separate network namespace and deny socket(); local socketpair() remains available so Node can launch the trusted ripgrep child process.

Explicit unsandboxed execution remains opt-in, approval-bound, and tied to the exact command and cwd through the existing escalation grant validation.

User impact

Linux now has the same product wiring as macOS for sandboxed file tools and one-shot permission requests. Windows behavior remains unchanged and still rejects these platform-specific options.

Validation

  • npm run lint
  • npm run clean && npm run build:test
  • npm run typecheck
  • Windows focused regression suite: 25 passed
  • WSL2 + bubblewrap required Linux smoke suite: 8 passed
    • Read, Write, Edit, Glob, and Grep
    • exact outside file grant and sibling denial
    • protected metadata denial
    • seccomp network denial
    • Bash exact additional permission
    • explicit unsandboxed escalation

Known baseline

The repository-wide npm test command on this Windows checkout has three pre-existing script-test failures unrelated to this change: a duplicated C:\C:\... path in the provider-matrix test, a CUA provenance hash mismatch, and the headless fixture's fixed byte-count expectation. The clean build, full typecheck, focused regressions, and required Linux smoke suites above are green.

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

I found one blocking issue and will leave it inline.

  • [P2] packages/runtime/src/builtin-tools.ts:988 creates every missing exact-write target before the command starts, but preparedTargets is dropped when sandboxCommand returns. Cleanup runs only when sandbox transformation fails. A spawn failure, abort, nonzero exit, or command that never writes the target leaves an empty file behind. A failed one-shot request should not mutate the filesystem.
  • [P2] apps/desktop/src/main/tool-assembly.ts:219 and :290 remove the Edit filter even when filesystemWorker is undefined. On Windows, createBuiltinSandboxManager() returns undefined, so Desktop now exposes the generic-executor Edit tool despite this PR stating that Windows behavior is unchanged. The new source-regex test enforces filter removal but never checks the platform-specific tool surface. Keep Edit conditional on a worker, or cover and document the Windows behavior explicitly.

The inline exact-write race can redirect an approved write, so this revision needs changes before merge.

Comment thread packages/runtime/src/builtin-tools.ts Outdated
@likun666661

Copy link
Copy Markdown
Member

Overall, I think the layering here is clear and the Linux parity direction is sound: capability detection → CLI/Desktop wiring → one-shot permission planning → sandbox transformation → worker launch/resource mounts → operation-level revalidation. The synthetic cwd handling and seccomp-FD propagation are especially good additions.

I found two concrete product-level issues worth addressing:

  1. Missing exact-write placeholder lifecycle. sandboxCommand pre-creates missing exact-write targets, but preparedTargets is dropped once transformation succeeds. A spawn failure, abort, non-zero exit, or even a successful no-op command can therefore leave an empty file behind. It would be good for ownership of the prepared target to extend through command completion, with behavioral coverage for failure/abort/no-op cases. This may need a slightly different design because an intentionally written empty file must not be confused with an untouched placeholder.

  2. Windows Edit surface regression. Removing the Desktop Edit filter also affects the no-worker path. Since Windows has no builtin sandbox manager/worker, it now appears to expose the generic-executor Edit tool even though the PR says Windows behavior is unchanged. I would keep Edit conditional on filesystemWorker, and replace the source-regex contract with a platform/tool-surface behavior test.

There is also a theoretical pathname TOCTOU/symlink concern around missing exact writes. Under Maka's current single-user, trusted-host-process threat model, I would treat that as defense-in-depth rather than a merge blocker; an FD-pinned/atomic-open design would still be a useful future hardening step.

So overall: the architecture and decomposition look good; the main remaining work is tightening the lifecycle and platform-surface behavior rather than changing the overall approach.

…em-worker

# Conflicts:
#	apps/desktop/src/main/tool-assembly.ts
#	packages/runtime/src/__tests__/builtin-tools.test.ts

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

Reviewed at 29605d5d. The three earlier issues are fixed: the Bash missing-target handoff is inode-pinned, placeholder ownership now lasts through terminal completion, and Desktop keeps Edit behind the filesystem worker on both parent and child surfaces. CI is green, including the mandatory Linux sandbox smoke.

I left two P2 follow-ups inline. Neither is a blocker under the current merge policy and threat model. Please push back if either assumption is wrong; these should be evaluated, not accepted mechanically.

No P0/P1. Approving.

Comment thread packages/runtime/src/sandbox/linux-sandbox.ts
Comment thread packages/runtime/src/sandbox/linux-sandbox.ts
@Astro-Han
Astro-Han merged commit ade1e90 into apache:main Jul 27, 2026
3 checks passed
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.

3 participants