How SandboxManager Selects the Platform Backend for Sandboxing in Apache Maka
SandboxManager uses a three-step decision process—checking if sandboxing is required, selecting a platform-matched backend, and verifying availability—to determine which sandbox backend to use for executing commands securely.
The Apache Maka runtime includes a robust sandboxing system that isolates untrusted code execution. At its core, the SandboxManager class orchestrates backend selection based on caller preferences, permission profiles, and the underlying operating system. This article explains the complete selection mechanism as implemented in the source code.
Step 1: Determine If Sandboxing Is Required
Before selecting any backend, SandboxManager evaluates whether sandboxing is actually necessary. This logic lives in shouldSandbox, located in packages/runtime/src/sandbox/sandbox-manager.ts (lines 42–50).
The method accepts two inputs:
preference: A caller-provided enum with values'auto','require', or'forbid'profile: A permission profile describing file-system and network restrictions
The decision tree works as follows:
| Preference | Behavior |
|---|---|
forbid |
Never sandbox; returns false immediately |
require |
Always sandbox; returns true immediately |
auto |
Delegates to profileRequiresSandbox(profile) |
For auto mode, the system sandboxes when the profile indicates a managed profile with restricted file-system or network access. Here's the implementation:
// sandbox-manager.ts: lines 42-50
if (preference === 'forbid') return false;
if (preference === 'require') return true;
return profileRequiresSandbox(profile);
This early exit prevents unnecessary backend selection work when sandboxing is explicitly disabled or when unrestricted permissions make isolation redundant.
Step 2: Select the Initial Backend Based on Platform
When shouldSandbox returns true, selectInitial chooses a backend matching the current platform. The platform is determined from process.platform or an optional caller override.
The selection logic in packages/runtime/src/sandbox/sandbox-manager.ts maps each supported OS to a specific backend type:
macOS Selection (Lines 68–78, 80–88)
For darwin platforms, the manager requires the macos-seatbelt backend:
// sandbox-manager.ts: lines 68-78
case 'darwin': {
if (this.backends.has('macos-seatbelt')) {
return {
ok: true,
sandboxType: 'macos-seatbelt',
platform: 'darwin',
};
}
// Fall through to unsupported_platform error (lines 80-88)
}
If macos-seatbelt isn't registered in this.backends, the manager returns a failure with reason: 'unsupported_platform'.
Linux Selection (Lines 91–101, 103–111)
For linux platforms, the manager selects the linux backend:
// sandbox-manager.ts: lines 91-101
case 'linux': {
if (this.backends.has('linux')) {
return {
ok: true,
sandboxType: 'linux',
platform: 'linux',
};
}
// Fall through to unsupported_platform error (lines 103-111)
}
Windows Selection (Lines 114–124, 126–134)
For win32 platforms, the manager selects the windows backend:
// sandbox-manager.ts: lines 114-124
case 'win32': {
if (this.backends.has('windows')) {
return {
ok: true,
sandboxType: 'windows',
platform: 'win32',
};
}
// Fall through to unsupported_platform error (lines 126-134)
}
Unsupported Platforms
Any platform not matching darwin, linux, or win32 triggers an immediate unsupported_platform failure.
Step 3: Verify Backend Availability and Capability
After selectInitial returns a candidate backend, the manager performs additional validation before actual use. This verification happens in canEnforce or during the subsequent transform call (lines 48–55).
The checks include:
- Backend presence: The selected backend exists in
this.backends - Platform availability: Optional
isAvailable(platform)returnstrue - Profile enforcement: Optional
canEnforceProfile(profile)returnstrue
// sandbox-manager.ts: lines 48-55
const backend = this.backends.get(selection.sandboxType);
if (!backend) return false;
if (!(backend.isAvailable?.(selected.platform) ?? true)) return false;
return backend.canEnforceProfile?.(input.profile) ?? true;
Failures at this stage produce backend_not_available or unsupported_platform errors, giving callers precise diagnostic information.
Practical Example: Registering and Selecting a Backend
Here's a complete workflow demonstrating backend registration and selection:
import { SandboxManager } from '@maka/runtime/src/sandbox/sandbox-manager.js';
import { LinuxBubblewrapBackend } from '@maka/runtime/src/sandbox/linux-sandbox.js';
// Register a Linux backend
const manager = new SandboxManager([
new LinuxBubblewrapBackend({
capability: { available: true, bwrapPath: '/usr/bin/bwrap' },
}),
]);
// Prepare a restricted permission profile (e.g., workspace-write)
import { createWorkspaceWritePermissionProfile } from '@maka/core/permission-profile';
const profile = createWorkspaceWritePermissionProfile();
// Ask the manager to pick a backend for the current platform (Linux here)
const selection = manager.selectInitial({ profile, platform: 'linux' });
if (selection.ok) {
console.log('Chosen backend:', selection.sandboxType); // → "linux"
} else {
console.error('Failed to select backend:', selection.reason);
}
Once selected, transform commands for sandboxed execution:
// Transform a command using the selected backend
const result = manager.transform({
command: {
program: '/bin/ls',
args: ['-l', '/tmp'],
cwd: '/repo',
profile,
pathContext: { workspaceRoots: ['/repo'], slashTmp: '/tmp' },
},
platform: 'linux',
});
if (result.ok) {
console.log('Exec argv:', result.exec.argv);
} else {
console.error('Transform error:', result.reason);
}
Key Files in the Sandbox Selection Architecture
| File | Role |
|---|---|
packages/runtime/src/sandbox/sandbox-manager.ts |
Core logic for sandbox selection, enforcement checks, and transformation |
packages/runtime/src/sandbox/types.ts |
Type definitions (SandboxType, SandboxSelectionInput, SandboxBackend) |
packages/runtime/src/__tests__/sandbox-manager.test.ts |
Unit tests illustrating selection rules for all platforms |
packages/runtime/src/sandbox/linux-sandbox.ts |
Example Linux backend (LinuxBubblewrapBackend) |
packages/runtime/src/sandbox/sandbox-denial.ts |
Helper for representing denied sandbox scenarios |
Summary
- Requirement check:
shouldSandboxuses preference (auto/require/forbid) and profile restrictions to decide if sandboxing is needed - Platform matching:
selectInitialmapsdarwin→macos-seatbelt,linux→linux,win32→windows - Registration dependency: Each backend must be registered in the
SandboxManagerconstructor viathis.backends - Runtime verification:
isAvailableandcanEnforceProfilevalidate the backend can actually enforce the requested profile - Clear failure modes: The system returns structured errors (
unsupported_platform,backend_not_available) for debugging
Frequently Asked Questions
What happens if the required backend isn't registered?
The manager returns a failure result with reason: 'unsupported_platform' and ok: false. This occurs in selectInitial when this.backends.has(sandboxType) returns false for the detected platform (lines 80–88, 103–111, and 126–134).
Can I force sandboxing even for unrestricted profiles?
Yes. Pass preference: 'require' to shouldSandbox. This bypasses the profileRequiresSandbox check and always returns true, causing the manager to proceed with backend selection regardless of profile permissions.
How does the manager handle unknown platforms?
Any platform string not matching darwin, linux, or win32 falls through to a default case that returns unsupported_platform. The manager does not attempt to guess or polyfill backends for unsupported operating systems.
What is the difference between selectInitial and transform?
selectInitial performs platform-based backend selection and returns a SandboxSelectionResult. transform takes that selection and produces the actual command-line arguments needed to run a specific program inside the sandbox, including all isolation flags and bind mounts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →