@agentick/sandbox-local 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -0
- package/dist/executor/base.d.ts +15 -0
- package/dist/executor/base.d.ts.map +1 -0
- package/dist/executor/base.js +20 -0
- package/dist/executor/base.js.map +1 -0
- package/dist/executor/darwin.d.ts +16 -0
- package/dist/executor/darwin.d.ts.map +1 -0
- package/dist/executor/darwin.js +44 -0
- package/dist/executor/darwin.js.map +1 -0
- package/dist/executor/linux.d.ts +22 -0
- package/dist/executor/linux.d.ts.map +1 -0
- package/dist/executor/linux.js +50 -0
- package/dist/executor/linux.js.map +1 -0
- package/dist/executor/select.d.ts +12 -0
- package/dist/executor/select.d.ts.map +1 -0
- package/dist/executor/select.js +23 -0
- package/dist/executor/select.js.map +1 -0
- package/dist/executor/types.d.ts +29 -0
- package/dist/executor/types.d.ts.map +1 -0
- package/dist/executor/types.js +4 -0
- package/dist/executor/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/linux/bwrap.d.ts +11 -0
- package/dist/linux/bwrap.d.ts.map +1 -0
- package/dist/linux/bwrap.js +46 -0
- package/dist/linux/bwrap.js.map +1 -0
- package/dist/linux/cgroup.d.ts +27 -0
- package/dist/linux/cgroup.d.ts.map +1 -0
- package/dist/linux/cgroup.js +80 -0
- package/dist/linux/cgroup.js.map +1 -0
- package/dist/linux/unshare.d.ts +11 -0
- package/dist/linux/unshare.d.ts.map +1 -0
- package/dist/linux/unshare.js +22 -0
- package/dist/linux/unshare.js.map +1 -0
- package/dist/local-sandbox.d.ts +42 -0
- package/dist/local-sandbox.d.ts.map +1 -0
- package/dist/local-sandbox.js +235 -0
- package/dist/local-sandbox.js.map +1 -0
- package/dist/network/ca.d.ts +38 -0
- package/dist/network/ca.d.ts.map +1 -0
- package/dist/network/ca.js +143 -0
- package/dist/network/ca.js.map +1 -0
- package/dist/network/proxy.d.ts +46 -0
- package/dist/network/proxy.d.ts.map +1 -0
- package/dist/network/proxy.js +144 -0
- package/dist/network/proxy.js.map +1 -0
- package/dist/network/rules.d.ts +23 -0
- package/dist/network/rules.d.ts.map +1 -0
- package/dist/network/rules.js +64 -0
- package/dist/network/rules.js.map +1 -0
- package/dist/paths.d.ts +29 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +129 -0
- package/dist/paths.js.map +1 -0
- package/dist/platform/detect.d.ts +17 -0
- package/dist/platform/detect.d.ts.map +1 -0
- package/dist/platform/detect.js +114 -0
- package/dist/platform/detect.js.map +1 -0
- package/dist/platform/types.d.ts +16 -0
- package/dist/platform/types.d.ts.map +1 -0
- package/dist/platform/types.js +4 -0
- package/dist/platform/types.js.map +1 -0
- package/dist/provider.d.ts +33 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +137 -0
- package/dist/provider.js.map +1 -0
- package/dist/resources.d.ts +30 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +94 -0
- package/dist/resources.js.map +1 -0
- package/dist/seatbelt/profile.d.ts +30 -0
- package/dist/seatbelt/profile.d.ts.map +1 -0
- package/dist/seatbelt/profile.js +106 -0
- package/dist/seatbelt/profile.js.map +1 -0
- package/dist/testing.d.ts +22 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +39 -0
- package/dist/testing.js.map +1 -0
- package/dist/workspace.d.ts +30 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +68 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +64 -0
- package/src/index.ts +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# @agentick/sandbox-local
|
|
2
|
+
|
|
3
|
+
Local sandbox provider for Agentick. Executes commands on the host machine with OS-level security rails.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { localProvider } from "@agentick/sandbox-local";
|
|
9
|
+
|
|
10
|
+
const provider = localProvider();
|
|
11
|
+
const sandbox = await provider.create({ workspace: true });
|
|
12
|
+
|
|
13
|
+
const result = await sandbox.exec("echo hello");
|
|
14
|
+
console.log(result.stdout); // "hello\n"
|
|
15
|
+
|
|
16
|
+
await sandbox.writeFile("test.txt", "content");
|
|
17
|
+
const content = await sandbox.readFile("test.txt");
|
|
18
|
+
|
|
19
|
+
await sandbox.destroy();
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Sandbox Strategies
|
|
23
|
+
|
|
24
|
+
The provider automatically selects the best available isolation strategy:
|
|
25
|
+
|
|
26
|
+
| Strategy | Platform | Isolation |
|
|
27
|
+
| ---------- | -------- | ------------------------------------------------------------- |
|
|
28
|
+
| `seatbelt` | macOS | Apple Sandbox (`sandbox-exec`) with SBPL profiles |
|
|
29
|
+
| `bwrap` | Linux | Bubblewrap with namespace isolation |
|
|
30
|
+
| `unshare` | Linux | `unshare` with user namespaces |
|
|
31
|
+
| `none` | Any | No OS sandboxing (workspace isolation + path validation only) |
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// Auto-detect (default)
|
|
35
|
+
const provider = localProvider();
|
|
36
|
+
|
|
37
|
+
// Force a specific strategy
|
|
38
|
+
const provider = localProvider({ strategy: "seatbelt" });
|
|
39
|
+
const provider = localProvider({ strategy: "none" }); // For testing
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Platform Detection
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { detectCapabilities } from "@agentick/sandbox-local";
|
|
46
|
+
|
|
47
|
+
const caps = await detectCapabilities();
|
|
48
|
+
// {
|
|
49
|
+
// platform: "darwin",
|
|
50
|
+
// arch: "arm64",
|
|
51
|
+
// hasSandboxExec: true,
|
|
52
|
+
// recommended: "seatbelt",
|
|
53
|
+
// ...
|
|
54
|
+
// }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Network Rules
|
|
58
|
+
|
|
59
|
+
Control sandbox network access with fine-grained rules.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const sandbox = await provider.create({
|
|
63
|
+
workspace: true,
|
|
64
|
+
permissions: {
|
|
65
|
+
net: [
|
|
66
|
+
{ action: "allow", domain: "api.github.com" },
|
|
67
|
+
{ action: "allow", domain: "*.npmjs.org" },
|
|
68
|
+
{ action: "deny", domain: "*.evil.com" },
|
|
69
|
+
{ action: "allow", port: 443, methods: ["GET"] },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Rules are evaluated in order. First match wins. Default action is **deny**.
|
|
76
|
+
|
|
77
|
+
When `NetworkRule[]` is provided, a transparent HTTP proxy is started. HTTPS connections are filtered at the CONNECT level (domain allow/block without TLS termination).
|
|
78
|
+
|
|
79
|
+
## Permissions
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const sandbox = await provider.create({
|
|
83
|
+
workspace: true,
|
|
84
|
+
permissions: {
|
|
85
|
+
fs: true, // Filesystem access (default: true)
|
|
86
|
+
net: false, // Network access (default: false)
|
|
87
|
+
childProcess: true, // Fork processes (default: true)
|
|
88
|
+
inheritEnv: false, // Inherit host env vars (default: false)
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Mounts
|
|
94
|
+
|
|
95
|
+
Map host directories into the sandbox.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
const sandbox = await provider.create({
|
|
99
|
+
workspace: true,
|
|
100
|
+
mounts: [
|
|
101
|
+
{ host: "/data/shared", sandbox: "/mnt/shared", mode: "ro" },
|
|
102
|
+
{ host: "/data/output", sandbox: "/mnt/output", mode: "rw" },
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Resource Limits
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const sandbox = await provider.create({
|
|
111
|
+
workspace: true,
|
|
112
|
+
limits: {
|
|
113
|
+
memory: 512 * 1024 * 1024, // 512MB
|
|
114
|
+
cpu: 0.5, // Half a core
|
|
115
|
+
timeout: 30000, // 30s global timeout
|
|
116
|
+
disk: 100 * 1024 * 1024, // 100MB workspace
|
|
117
|
+
maxProcesses: 10,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Resource limits use cgroups v2 on Linux. On macOS, timeout and disk limits are enforced; memory/CPU are advisory.
|
|
123
|
+
|
|
124
|
+
## Streaming Output
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const result = await sandbox.exec("npm install", {
|
|
128
|
+
onOutput: (chunk) => {
|
|
129
|
+
process.stdout.write(`[${chunk.stream}] ${chunk.data}`);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## With Agentick Components
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { Sandbox, Shell, ReadFile, WriteFile } from "@agentick/sandbox";
|
|
138
|
+
import { localProvider } from "@agentick/sandbox-local";
|
|
139
|
+
|
|
140
|
+
const MyAgent = () => (
|
|
141
|
+
<Sandbox provider={localProvider()} workspace={true}>
|
|
142
|
+
<Shell />
|
|
143
|
+
<ReadFile />
|
|
144
|
+
<WriteFile />
|
|
145
|
+
</Sandbox>
|
|
146
|
+
);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Testing
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { createTestProvider, isDarwin } from "@agentick/sandbox-local/testing";
|
|
153
|
+
|
|
154
|
+
const provider = createTestProvider(); // strategy: "none"
|
|
155
|
+
const sandbox = await provider.create({ workspace: true });
|
|
156
|
+
|
|
157
|
+
// Platform-gated tests
|
|
158
|
+
describe.skipIf(!isDarwin)("seatbelt tests", () => { ... });
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Security Model
|
|
162
|
+
|
|
163
|
+
**Safe by default.** The sandbox denies access to sensitive resources unless explicitly allowed.
|
|
164
|
+
|
|
165
|
+
### macOS Seatbelt (reads)
|
|
166
|
+
|
|
167
|
+
Sandboxed processes can read system libraries and executables (required for bash/node), but **cannot** read:
|
|
168
|
+
|
|
169
|
+
| Denied Path | Contains |
|
|
170
|
+
| ------------------------- | ------------------------------------------------------------------ |
|
|
171
|
+
| `/Users` | Home directories — SSH keys, `.env`, browser profiles, credentials |
|
|
172
|
+
| `/private/var/root` | Root's home directory |
|
|
173
|
+
| `/Volumes` | Mounted drives, encrypted volumes, network shares |
|
|
174
|
+
| `/Network` | Network-mounted resources |
|
|
175
|
+
| `/Library/Keychains` | System-level keychains and certificates |
|
|
176
|
+
| `/private/var/db/dslocal` | Local directory service (user account data) |
|
|
177
|
+
|
|
178
|
+
The workspace and any configured mounts are re-allowed via SBPL specificity rules (more-specific subpath allows override broader denies).
|
|
179
|
+
|
|
180
|
+
### Write restrictions
|
|
181
|
+
|
|
182
|
+
All strategies restrict writes to:
|
|
183
|
+
|
|
184
|
+
- The workspace directory
|
|
185
|
+
- Configured read-write mounts
|
|
186
|
+
- `/tmp` and `/dev`
|
|
187
|
+
|
|
188
|
+
### Additional protections
|
|
189
|
+
|
|
190
|
+
| Threat | Mitigation |
|
|
191
|
+
| ------------------- | -------------------------------------------------------------- |
|
|
192
|
+
| Path traversal | `realpath()` + bounds check |
|
|
193
|
+
| Symlink escape | Follow symlinks before validation |
|
|
194
|
+
| Null byte injection | Reject null bytes in all paths |
|
|
195
|
+
| Output OOM | 10MB cap per stream |
|
|
196
|
+
| Env var injection | Blocklist for `LD_PRELOAD`, `DYLD_*` |
|
|
197
|
+
| Process orphans | Kill process group (`detached` + `-pid`), SIGTERM then SIGKILL |
|
|
198
|
+
| Zombie sandbox | `destroyed` flag prevents use-after-destroy |
|
|
199
|
+
| Disk bomb | Polling monitor kills processes on exceed |
|
|
200
|
+
|
|
201
|
+
### Platform requirements
|
|
202
|
+
|
|
203
|
+
**macOS**: `/usr/bin/sandbox-exec` (ships with macOS, no install needed).
|
|
204
|
+
|
|
205
|
+
**Linux**: One of:
|
|
206
|
+
|
|
207
|
+
- `bwrap` (bubblewrap) — install via `apt install bubblewrap` or equivalent
|
|
208
|
+
- `unshare` with unprivileged user namespaces enabled (`sysctl kernel.unprivileged_userns_clone=1`)
|
|
209
|
+
- cgroups v2 for memory/CPU/process limits (writable `/sys/fs/cgroup`)
|
|
210
|
+
|
|
211
|
+
**All platforms**: Falls back to `strategy: "none"` (workspace isolation + path validation only, no OS-level sandboxing) when no sandbox tooling is available.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base (unsandboxed) executor.
|
|
3
|
+
*
|
|
4
|
+
* Plain child_process.spawn — no OS-level sandboxing.
|
|
5
|
+
* Still benefits from workspace isolation, path validation, and timeout enforcement
|
|
6
|
+
* provided by LocalSandbox.
|
|
7
|
+
*/
|
|
8
|
+
import type { ChildProcess } from "node:child_process";
|
|
9
|
+
import type { CommandExecutor, SpawnOptions } from "./types";
|
|
10
|
+
import type { SandboxStrategy } from "../platform/types";
|
|
11
|
+
export declare class BaseExecutor implements CommandExecutor {
|
|
12
|
+
readonly strategy: SandboxStrategy;
|
|
13
|
+
spawn(command: string, options: SpawnOptions): ChildProcess;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/executor/base.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,qBAAa,YAAa,YAAW,eAAe;IAClD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAU;IAE5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY;CAQ5D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base (unsandboxed) executor.
|
|
3
|
+
*
|
|
4
|
+
* Plain child_process.spawn — no OS-level sandboxing.
|
|
5
|
+
* Still benefits from workspace isolation, path validation, and timeout enforcement
|
|
6
|
+
* provided by LocalSandbox.
|
|
7
|
+
*/
|
|
8
|
+
import { spawn } from "node:child_process";
|
|
9
|
+
export class BaseExecutor {
|
|
10
|
+
strategy = "none";
|
|
11
|
+
spawn(command, options) {
|
|
12
|
+
return spawn("sh", ["-c", command], {
|
|
13
|
+
cwd: options.cwd,
|
|
14
|
+
env: options.env,
|
|
15
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
16
|
+
detached: true,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/executor/base.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAK3C,MAAM,OAAO,YAAY;IACd,QAAQ,GAAoB,MAAM,CAAC;IAE5C,KAAK,CAAC,OAAe,EAAE,OAAqB;QAC1C,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;YAClC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* macOS Seatbelt Executor
|
|
3
|
+
*
|
|
4
|
+
* Generates a seatbelt profile from SpawnOptions, writes it to a temp file,
|
|
5
|
+
* and spawns the command under sandbox-exec.
|
|
6
|
+
*/
|
|
7
|
+
import type { ChildProcess } from "node:child_process";
|
|
8
|
+
import type { CommandExecutor, SpawnOptions } from "./types";
|
|
9
|
+
import type { SandboxStrategy } from "../platform/types";
|
|
10
|
+
export declare class DarwinExecutor implements CommandExecutor {
|
|
11
|
+
readonly strategy: SandboxStrategy;
|
|
12
|
+
private readonly profileDir;
|
|
13
|
+
constructor();
|
|
14
|
+
spawn(command: string, options: SpawnOptions): ChildProcess;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=darwin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"darwin.d.ts","sourceRoot":"","sources":["../../src/executor/darwin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,qBAAa,cAAe,YAAW,eAAe;IACpD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAc;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;;IAQpC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY;CAyB5D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* macOS Seatbelt Executor
|
|
3
|
+
*
|
|
4
|
+
* Generates a seatbelt profile from SpawnOptions, writes it to a temp file,
|
|
5
|
+
* and spawns the command under sandbox-exec.
|
|
6
|
+
*/
|
|
7
|
+
import { spawn } from "node:child_process";
|
|
8
|
+
import { writeFileSync, unlinkSync, mkdirSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { randomBytes } from "node:crypto";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { compileSeatbeltProfile } from "../seatbelt/profile";
|
|
13
|
+
export class DarwinExecutor {
|
|
14
|
+
strategy = "seatbelt";
|
|
15
|
+
profileDir;
|
|
16
|
+
constructor() {
|
|
17
|
+
// Per-instance temp dir for profile files
|
|
18
|
+
this.profileDir = join(tmpdir(), `agentick-seatbelt-${randomBytes(6).toString("hex")}`);
|
|
19
|
+
mkdirSync(this.profileDir, { recursive: true, mode: 0o700 });
|
|
20
|
+
}
|
|
21
|
+
spawn(command, options) {
|
|
22
|
+
const profile = compileSeatbeltProfile(options);
|
|
23
|
+
// Write profile to temp file with restricted permissions
|
|
24
|
+
const profilePath = join(this.profileDir, `profile-${randomBytes(4).toString("hex")}.sb`);
|
|
25
|
+
writeFileSync(profilePath, profile, { mode: 0o600 });
|
|
26
|
+
const child = spawn("sandbox-exec", ["-f", profilePath, "/bin/bash", "-c", command], {
|
|
27
|
+
cwd: options.cwd,
|
|
28
|
+
env: options.env,
|
|
29
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
30
|
+
detached: true,
|
|
31
|
+
});
|
|
32
|
+
// Clean up profile after process starts
|
|
33
|
+
child.on("exit", () => {
|
|
34
|
+
try {
|
|
35
|
+
unlinkSync(profilePath);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Best-effort cleanup
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return child;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=darwin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"darwin.js","sourceRoot":"","sources":["../../src/executor/darwin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,OAAO,cAAc;IAChB,QAAQ,GAAoB,UAAU,CAAC;IAC/B,UAAU,CAAS;IAEpC;QACE,0CAA0C;QAC1C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,qBAAqB,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxF,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAAqB;QAC1C,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAEhD,yDAAyD;QACzD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1F,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAErD,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;YACnF,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,wCAAwC;QACxC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACpB,IAAI,CAAC;gBACH,UAAU,CAAC,WAAW,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,sBAAsB;YACxB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linux Executor (bubblewrap / unshare)
|
|
3
|
+
*
|
|
4
|
+
* Spawns commands under bwrap or unshare for namespace-based isolation.
|
|
5
|
+
*/
|
|
6
|
+
import type { ChildProcess } from "node:child_process";
|
|
7
|
+
import type { CommandExecutor, SpawnOptions } from "./types";
|
|
8
|
+
import type { SandboxStrategy } from "../platform/types";
|
|
9
|
+
import type { CgroupManager } from "../linux/cgroup";
|
|
10
|
+
export declare class BwrapExecutor implements CommandExecutor {
|
|
11
|
+
readonly strategy: SandboxStrategy;
|
|
12
|
+
private cgroup?;
|
|
13
|
+
constructor(cgroup?: CgroupManager);
|
|
14
|
+
spawn(command: string, options: SpawnOptions): ChildProcess;
|
|
15
|
+
}
|
|
16
|
+
export declare class UnshareExecutor implements CommandExecutor {
|
|
17
|
+
readonly strategy: SandboxStrategy;
|
|
18
|
+
private cgroup?;
|
|
19
|
+
constructor(cgroup?: CgroupManager);
|
|
20
|
+
spawn(command: string, options: SpawnOptions): ChildProcess;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=linux.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linux.d.ts","sourceRoot":"","sources":["../../src/executor/linux.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,qBAAa,aAAc,YAAW,eAAe;IACnD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAW;IAC7C,OAAO,CAAC,MAAM,CAAC,CAAgB;gBAEnB,MAAM,CAAC,EAAE,aAAa;IAIlC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY;CAgB5D;AAED,qBAAa,eAAgB,YAAW,eAAe;IACrD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAa;IAC/C,OAAO,CAAC,MAAM,CAAC,CAAgB;gBAEnB,MAAM,CAAC,EAAE,aAAa;IAIlC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY;CAiB5D"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linux Executor (bubblewrap / unshare)
|
|
3
|
+
*
|
|
4
|
+
* Spawns commands under bwrap or unshare for namespace-based isolation.
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import { buildBwrapArgs } from "../linux/bwrap";
|
|
8
|
+
import { buildUnshareArgs } from "../linux/unshare";
|
|
9
|
+
export class BwrapExecutor {
|
|
10
|
+
strategy = "bwrap";
|
|
11
|
+
cgroup;
|
|
12
|
+
constructor(cgroup) {
|
|
13
|
+
this.cgroup = cgroup;
|
|
14
|
+
}
|
|
15
|
+
spawn(command, options) {
|
|
16
|
+
const args = buildBwrapArgs(options);
|
|
17
|
+
args.push("sh", "-c", command);
|
|
18
|
+
const child = spawn("bwrap", args, {
|
|
19
|
+
env: options.env,
|
|
20
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
21
|
+
detached: true,
|
|
22
|
+
});
|
|
23
|
+
if (this.cgroup && child.pid) {
|
|
24
|
+
this.cgroup.addProcess(child.pid).catch(() => { });
|
|
25
|
+
}
|
|
26
|
+
return child;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export class UnshareExecutor {
|
|
30
|
+
strategy = "unshare";
|
|
31
|
+
cgroup;
|
|
32
|
+
constructor(cgroup) {
|
|
33
|
+
this.cgroup = cgroup;
|
|
34
|
+
}
|
|
35
|
+
spawn(command, options) {
|
|
36
|
+
const args = buildUnshareArgs(options);
|
|
37
|
+
args.push("sh", "-c", command);
|
|
38
|
+
const child = spawn("unshare", args, {
|
|
39
|
+
cwd: options.cwd,
|
|
40
|
+
env: options.env,
|
|
41
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
42
|
+
detached: true,
|
|
43
|
+
});
|
|
44
|
+
if (this.cgroup && child.pid) {
|
|
45
|
+
this.cgroup.addProcess(child.pid).catch(() => { });
|
|
46
|
+
}
|
|
47
|
+
return child;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=linux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linux.js","sourceRoot":"","sources":["../../src/executor/linux.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAI3C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,OAAO,aAAa;IACf,QAAQ,GAAoB,OAAO,CAAC;IACrC,MAAM,CAAiB;IAE/B,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAAqB;QAC1C,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAE/B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED,MAAM,OAAO,eAAe;IACjB,QAAQ,GAAoB,SAAS,CAAC;IACvC,MAAM,CAAiB;IAE/B,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAAqB;QAC1C,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAE/B,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Executor factory — select executor based on platform capabilities.
|
|
3
|
+
*/
|
|
4
|
+
import type { SandboxStrategy } from "../platform/types";
|
|
5
|
+
import type { CommandExecutor } from "./types";
|
|
6
|
+
import type { CgroupManager } from "../linux/cgroup";
|
|
7
|
+
/**
|
|
8
|
+
* Create a CommandExecutor for the given strategy.
|
|
9
|
+
* Optionally accepts a CgroupManager for Linux executors.
|
|
10
|
+
*/
|
|
11
|
+
export declare function selectExecutor(strategy: SandboxStrategy, cgroup?: CgroupManager): CommandExecutor;
|
|
12
|
+
//# sourceMappingURL=select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/executor/select.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,eAAe,CAWjG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Executor factory — select executor based on platform capabilities.
|
|
3
|
+
*/
|
|
4
|
+
import { BaseExecutor } from "./base";
|
|
5
|
+
import { DarwinExecutor } from "./darwin";
|
|
6
|
+
import { BwrapExecutor, UnshareExecutor } from "./linux";
|
|
7
|
+
/**
|
|
8
|
+
* Create a CommandExecutor for the given strategy.
|
|
9
|
+
* Optionally accepts a CgroupManager for Linux executors.
|
|
10
|
+
*/
|
|
11
|
+
export function selectExecutor(strategy, cgroup) {
|
|
12
|
+
switch (strategy) {
|
|
13
|
+
case "seatbelt":
|
|
14
|
+
return new DarwinExecutor();
|
|
15
|
+
case "bwrap":
|
|
16
|
+
return new BwrapExecutor(cgroup);
|
|
17
|
+
case "unshare":
|
|
18
|
+
return new UnshareExecutor(cgroup);
|
|
19
|
+
case "none":
|
|
20
|
+
return new BaseExecutor();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/executor/select.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAGzD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAyB,EAAE,MAAsB;IAC9E,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,IAAI,cAAc,EAAE,CAAC;QAC9B,KAAK,OAAO;YACV,OAAO,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;QACnC,KAAK,SAAS;YACZ,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;QACrC,KAAK,MAAM;YACT,OAAO,IAAI,YAAY,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command executor types.
|
|
3
|
+
*/
|
|
4
|
+
import type { ChildProcess } from "node:child_process";
|
|
5
|
+
import type { SandboxStrategy } from "../platform/types";
|
|
6
|
+
import type { NetworkRule } from "@agentick/sandbox";
|
|
7
|
+
export interface CommandExecutor {
|
|
8
|
+
readonly strategy: SandboxStrategy;
|
|
9
|
+
spawn(command: string, options: SpawnOptions): ChildProcess;
|
|
10
|
+
}
|
|
11
|
+
export interface SpawnOptions {
|
|
12
|
+
cwd: string;
|
|
13
|
+
env: Record<string, string>;
|
|
14
|
+
workspacePath: string;
|
|
15
|
+
mounts: ResolvedMount[];
|
|
16
|
+
permissions: ResolvedPermissions;
|
|
17
|
+
}
|
|
18
|
+
export interface ResolvedPermissions {
|
|
19
|
+
readPaths: string[];
|
|
20
|
+
writePaths: string[];
|
|
21
|
+
network: boolean | NetworkRule[];
|
|
22
|
+
childProcess: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface ResolvedMount {
|
|
25
|
+
hostPath: string;
|
|
26
|
+
sandboxPath: string;
|
|
27
|
+
mode: "ro" | "rw";
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/executor/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY,CAAC;CAC7D;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,WAAW,EAAE,mBAAmB,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,OAAO,GAAG,WAAW,EAAE,CAAC;IACjC,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/executor/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agentick/sandbox-local — Local sandbox provider
|
|
3
|
+
*
|
|
4
|
+
* OS-level process isolation using macOS seatbelt and Linux bubblewrap/unshare.
|
|
5
|
+
*/
|
|
6
|
+
export { localProvider } from "./provider";
|
|
7
|
+
export type { LocalProviderConfig } from "./provider";
|
|
8
|
+
export { detectCapabilities } from "./platform/detect";
|
|
9
|
+
export type { PlatformCapabilities, SandboxStrategy } from "./platform/types";
|
|
10
|
+
export { NetworkProxyServer } from "./network/proxy";
|
|
11
|
+
export type { ProxyServerConfig } from "./network/proxy";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAG9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agentick/sandbox-local — Local sandbox provider
|
|
3
|
+
*
|
|
4
|
+
* OS-level process isolation using macOS seatbelt and Linux bubblewrap/unshare.
|
|
5
|
+
*/
|
|
6
|
+
// ── Provider ────────────────────────────────────────────────────────────────
|
|
7
|
+
export { localProvider } from "./provider";
|
|
8
|
+
// ── Platform Detection ──────────────────────────────────────────────────────
|
|
9
|
+
export { detectCapabilities } from "./platform/detect";
|
|
10
|
+
// ── Network Proxy ───────────────────────────────────────────────────────────
|
|
11
|
+
export { NetworkProxyServer } from "./network/proxy";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,+EAA+E;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,+EAA+E;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,+EAA+E;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bubblewrap argument builder.
|
|
3
|
+
*
|
|
4
|
+
* Constructs the bwrap command-line arguments from SpawnOptions.
|
|
5
|
+
*/
|
|
6
|
+
import type { SpawnOptions } from "../executor/types";
|
|
7
|
+
/**
|
|
8
|
+
* Build bubblewrap argument array for a given set of spawn options.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildBwrapArgs(options: SpawnOptions): string[];
|
|
11
|
+
//# sourceMappingURL=bwrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bwrap.d.ts","sourceRoot":"","sources":["../../src/linux/bwrap.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKtD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,EAAE,CA0C9D"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bubblewrap argument builder.
|
|
3
|
+
*
|
|
4
|
+
* Constructs the bwrap command-line arguments from SpawnOptions.
|
|
5
|
+
*/
|
|
6
|
+
/** System directories to mount read-only into the sandbox. */
|
|
7
|
+
const SYSTEM_RO_BINDS = ["/usr", "/lib", "/lib64", "/bin", "/sbin", "/etc"];
|
|
8
|
+
/**
|
|
9
|
+
* Build bubblewrap argument array for a given set of spawn options.
|
|
10
|
+
*/
|
|
11
|
+
export function buildBwrapArgs(options) {
|
|
12
|
+
const args = [];
|
|
13
|
+
// Namespace isolation
|
|
14
|
+
args.push("--unshare-all");
|
|
15
|
+
// Re-share network if allowed
|
|
16
|
+
const net = options.permissions.network;
|
|
17
|
+
if (net === true || (Array.isArray(net) && net.length > 0)) {
|
|
18
|
+
args.push("--share-net");
|
|
19
|
+
}
|
|
20
|
+
// System directories (read-only)
|
|
21
|
+
for (const dir of SYSTEM_RO_BINDS) {
|
|
22
|
+
args.push("--ro-bind", dir, dir);
|
|
23
|
+
}
|
|
24
|
+
// Proc, dev, tmp
|
|
25
|
+
args.push("--proc", "/proc");
|
|
26
|
+
args.push("--dev", "/dev");
|
|
27
|
+
args.push("--tmpfs", "/tmp");
|
|
28
|
+
// Workspace (read-write)
|
|
29
|
+
args.push("--bind", options.workspacePath, options.workspacePath);
|
|
30
|
+
// User mounts
|
|
31
|
+
for (const mount of options.mounts) {
|
|
32
|
+
if (mount.mode === "ro") {
|
|
33
|
+
args.push("--ro-bind", mount.hostPath, mount.sandboxPath);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
args.push("--bind", mount.hostPath, mount.sandboxPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Safety
|
|
40
|
+
args.push("--die-with-parent");
|
|
41
|
+
args.push("--new-session");
|
|
42
|
+
// Working directory
|
|
43
|
+
args.push("--chdir", options.cwd);
|
|
44
|
+
return args;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=bwrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bwrap.js","sourceRoot":"","sources":["../../src/linux/bwrap.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,8DAA8D;AAC9D,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAE5E;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAqB;IAClD,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,sBAAsB;IACtB,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAE3B,8BAA8B;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;IACxC,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3B,CAAC;IAED,iCAAiC;IACjC,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,iBAAiB;IACjB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAE7B,yBAAyB;IACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAElE,cAAc;IACd,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,SAAS;IACT,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAC/B,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAE3B,oBAAoB;IACpB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAElC,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cgroups v2 Resource Limit Manager
|
|
3
|
+
*
|
|
4
|
+
* Creates a cgroup under /sys/fs/cgroup/ for enforcing memory, CPU, and
|
|
5
|
+
* process limits. Degrades gracefully if the cgroup directory is not writable.
|
|
6
|
+
*/
|
|
7
|
+
import type { ResourceLimits } from "@agentick/sandbox";
|
|
8
|
+
export declare class CgroupManager {
|
|
9
|
+
private readonly id;
|
|
10
|
+
private readonly cgroupPath;
|
|
11
|
+
private created;
|
|
12
|
+
constructor(id: string);
|
|
13
|
+
/**
|
|
14
|
+
* Create the cgroup directory and apply resource limits.
|
|
15
|
+
* No-op if cgroups v2 is not available or not writable.
|
|
16
|
+
*/
|
|
17
|
+
create(limits: ResourceLimits): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Add a process to this cgroup.
|
|
20
|
+
*/
|
|
21
|
+
addProcess(pid: number): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Destroy the cgroup directory.
|
|
24
|
+
*/
|
|
25
|
+
destroy(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=cgroup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cgroup.d.ts","sourceRoot":"","sources":["../../src/linux/cgroup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIxD,qBAAa,aAAa;IAIZ,OAAO,CAAC,QAAQ,CAAC,EAAE;IAH/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,OAAO,CAAS;gBAEK,EAAE,EAAE,MAAM;IAIvC;;;OAGG;IACG,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCnD;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAU/B"}
|