@anthropic-ai/sandbox-runtime 0.0.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.
Files changed (62) hide show
  1. package/README.md +497 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +75 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/index.d.ts +4 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +4 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/sandbox/http-proxy.d.ts +7 -0
  11. package/dist/sandbox/http-proxy.d.ts.map +1 -0
  12. package/dist/sandbox/http-proxy.js +118 -0
  13. package/dist/sandbox/http-proxy.js.map +1 -0
  14. package/dist/sandbox/linux-sandbox-utils.d.ts +60 -0
  15. package/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -0
  16. package/dist/sandbox/linux-sandbox-utils.js +333 -0
  17. package/dist/sandbox/linux-sandbox-utils.js.map +1 -0
  18. package/dist/sandbox/macos-sandbox-utils.d.ts +53 -0
  19. package/dist/sandbox/macos-sandbox-utils.d.ts.map +1 -0
  20. package/dist/sandbox/macos-sandbox-utils.js +496 -0
  21. package/dist/sandbox/macos-sandbox-utils.js.map +1 -0
  22. package/dist/sandbox/sandbox-manager.d.ts +34 -0
  23. package/dist/sandbox/sandbox-manager.d.ts.map +1 -0
  24. package/dist/sandbox/sandbox-manager.js +655 -0
  25. package/dist/sandbox/sandbox-manager.js.map +1 -0
  26. package/dist/sandbox/sandbox-schemas.d.ts +93 -0
  27. package/dist/sandbox/sandbox-schemas.d.ts.map +1 -0
  28. package/dist/sandbox/sandbox-schemas.js +231 -0
  29. package/dist/sandbox/sandbox-schemas.js.map +1 -0
  30. package/dist/sandbox/sandbox-utils.d.ts +49 -0
  31. package/dist/sandbox/sandbox-utils.d.ts.map +1 -0
  32. package/dist/sandbox/sandbox-utils.js +345 -0
  33. package/dist/sandbox/sandbox-utils.js.map +1 -0
  34. package/dist/sandbox/sandbox-violation-store.d.ts +19 -0
  35. package/dist/sandbox/sandbox-violation-store.d.ts.map +1 -0
  36. package/dist/sandbox/sandbox-violation-store.js +54 -0
  37. package/dist/sandbox/sandbox-violation-store.js.map +1 -0
  38. package/dist/sandbox/socks-proxy.d.ts +13 -0
  39. package/dist/sandbox/socks-proxy.d.ts.map +1 -0
  40. package/dist/sandbox/socks-proxy.js +95 -0
  41. package/dist/sandbox/socks-proxy.js.map +1 -0
  42. package/dist/utils/debug.d.ts +7 -0
  43. package/dist/utils/debug.d.ts.map +1 -0
  44. package/dist/utils/debug.js +22 -0
  45. package/dist/utils/debug.js.map +1 -0
  46. package/dist/utils/exec.d.ts +13 -0
  47. package/dist/utils/exec.d.ts.map +1 -0
  48. package/dist/utils/exec.js +38 -0
  49. package/dist/utils/exec.js.map +1 -0
  50. package/dist/utils/platform.d.ts +6 -0
  51. package/dist/utils/platform.d.ts.map +1 -0
  52. package/dist/utils/platform.js +16 -0
  53. package/dist/utils/platform.js.map +1 -0
  54. package/dist/utils/ripgrep.d.ts +16 -0
  55. package/dist/utils/ripgrep.d.ts.map +1 -0
  56. package/dist/utils/ripgrep.js +57 -0
  57. package/dist/utils/ripgrep.js.map +1 -0
  58. package/dist/utils/settings.d.ts +147 -0
  59. package/dist/utils/settings.d.ts.map +1 -0
  60. package/dist/utils/settings.js +244 -0
  61. package/dist/utils/settings.js.map +1 -0
  62. package/package.json +72 -0
package/README.md ADDED
@@ -0,0 +1,497 @@
1
+ # Anthropic Sandbox Runtime (srt)
2
+
3
+ A lightweight sandboxing tool for enforcing filesystem and network restrictions on arbitrary processes at the OS level, without requiring a container.
4
+
5
+ `srt` uses native OS sandboxing primitives (`sandbox-exec` on macOS, `bubblewrap` on Linux) and proxy-based network filtering. It can be used to sandbox the behaviour of agents, local MCP servers, bash commands and arbitrary processes.
6
+
7
+ > **Beta Research Preview**
8
+ >
9
+ > The Sandbox Runtime is a research preview developed for [Claude Code](https://www.claude.com/product/claude-code) to enable safer AI agents. It's being made available as an early open source preview to help the broader ecosystem build more secure agentic systems. As this is an early research preview, APIs and configuration formats may evolve. We welcome feedback and contributions to make AI agents safer by default!
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @anthropic-ai/sandbox-runtime
15
+ ```
16
+
17
+ ## Basic Usage
18
+
19
+ ```bash
20
+ # Network restrictions
21
+ $ srt "curl anthropic.com"
22
+ Running: curl anthropic.com
23
+ <html>...</html> # Request succeeds
24
+
25
+ $ srt "curl example.com"
26
+ Running: curl example.com
27
+ Connection blocked by network allowlist # Request blocked
28
+
29
+ # Filesystem restrictions
30
+ $ srt "cat README.md"
31
+ Running: cat README.md
32
+ # Anthropic Sandb... # Current directory access allowed
33
+
34
+ $ srt "cat ~/.ssh/id_rsa"
35
+ Running: cat ~/.ssh/id_rsa
36
+ cat: /Users/ollie/.ssh/id_rsa: Operation not permitted # Specific file blocked
37
+ ```
38
+
39
+
40
+ ## Overview
41
+
42
+ This package provides a standalone sandbox implementation that can be used as both a CLI tool and a library. It's designed with a **secure-by-default** philosophy tailored for common developer use cases: processes start with minimal access, and you explicitly poke only the holes you need.
43
+
44
+ **Key capabilities:**
45
+
46
+ - **Network restrictions**: Control which hosts/domains can be accessed via HTTP/HTTPS and other protocols
47
+ - **Filesystem restrictions**: Control which files/directories can be read/written (defaulting to allowing writes to the current working directory)
48
+ - **Unix socket restrictions**: Control access to local IPC sockets
49
+ - **Violation monitoring**: On macOS, tap into the system's sandbox violation log store for real-time alerts
50
+
51
+ ### Example Use Case: Sandboxing MCP Servers
52
+
53
+ A key use case is sandboxing Model Context Protocol (MCP) servers to restrict their capabilities. For example, to sandbox the filesystem MCP server:
54
+
55
+ **Without sandboxing** (`.mcp.json`):
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "filesystem": {
60
+ "command": "npx",
61
+ "args": ["-y", "@modelcontextprotocol/server-filesystem"]
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ **With sandboxing** (`.mcp.json`):
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "filesystem": {
72
+ "command": "srt",
73
+ "args": ["npx", "-y", "@modelcontextprotocol/server-filesystem"]
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ Then configure restrictions in `~/.claude/settings.json`:
80
+ ```json
81
+ {
82
+ "permissions": {
83
+ "deny": [
84
+ "Edit(~/sensitive-folder)"
85
+ ]
86
+ }
87
+ }
88
+ ```
89
+
90
+ Now the MCP server will be blocked from writing to the denied path:
91
+ ```
92
+ > Write a file to ~/sensitive-folder
93
+ ✗ Error: EPERM: operation not permitted, open '/Users/ollie/sensitive-folder/test.txt'
94
+ ```
95
+
96
+ ## How It Works
97
+
98
+ The sandbox uses OS-level primitives to enforce restrictions that apply to the entire process tree:
99
+
100
+ - **macOS**: Uses `sandbox-exec` with dynamically generated [Seatbelt profiles](https://reverse.put.as/wp-content/uploads/2011/09/Apple-Sandbox-Guide-v1.0.pdf)
101
+ - **Linux**: Uses [bubblewrap](https://github.com/containers/bubblewrap) for containerization with network namespace isolation
102
+
103
+ ![0d1c612947c798aef48e6ab4beb7e8544da9d41a-4096x2305](https://github.com/user-attachments/assets/76c838a9-19ef-4d0b-90bb-cbe1917b3551)
104
+
105
+
106
+ ### Dual Isolation Model
107
+
108
+ Both filesystem and network isolation are required for effective sandboxing. Without network isolation, a compromised process could exfiltrate SSH keys or other sensitive files. Without filesystem isolation, a process could escape the sandbox and gain unrestricted network access.
109
+
110
+ **Filesystem Isolation** enforces read and write restrictions:
111
+
112
+ - **Read**: By default, read access is allowed everywhere. You can deny specific paths (e.g., `Read(~/.ssh)`)
113
+ - **Write**: By default, write access is only allowed in the current working directory. You can allow additional paths (e.g., `Edit(/tmp)`), and deny within allowed paths (e.g., deny `Edit(./secret)` even though `.` is allowed)
114
+
115
+ **Network Isolation** routes all traffic through proxy servers running on the host:
116
+
117
+ - **Linux**: Requests are routed via the filesystem over a Unix domain socket. The network namespace of the sandboxed process is removed entirely, so all network traffic must go through the proxies running on the host (listening on Unix sockets that are bind-mounted into the sandbox)
118
+
119
+ - **macOS**: The Seatbelt profile allows communication only to a specific localhost port. The proxies listen on this port, creating a controlled channel for all network access
120
+
121
+ Both HTTP/HTTPS (via HTTP proxy) and other TCP traffic (via SOCKS5 proxy) are mediated by these proxies, which enforce your domain allowlists and denylists.
122
+
123
+ For more details on sandboxing in Claude Code, see:
124
+ - [Claude Code Sandboxing Documentation](https://docs.claude.com/en/docs/claude-code/sandboxing)
125
+ - [Beyond Permission Prompts: Making Claude Code More Secure and Autonomous](https://www.anthropic.com/engineering/claude-code-sandboxing)
126
+
127
+ ## Architecture
128
+
129
+ ```
130
+ src/
131
+ ├── index.ts # Library exports
132
+ ├── cli.ts # CLI entrypoint (srt command)
133
+ ├── utils/ # Shared utilities
134
+ │ ├── debug.ts # Debug logging
135
+ │ ├── settings.ts # Settings reader (permissions + sandbox config)
136
+ │ ├── platform.ts # Platform detection
137
+ │ └── exec.ts # Command execution utilities
138
+ └── sandbox/ # Sandbox implementation
139
+ ├── sandbox-manager.ts # Main sandbox manager
140
+ ├── sandbox-schemas.ts # Zod schemas for validation
141
+ ├── sandbox-violation-store.ts # Violation tracking
142
+ ├── sandbox-utils.ts # Shared sandbox utilities
143
+ ├── http-proxy.ts # HTTP/HTTPS proxy for network filtering
144
+ ├── socks-proxy.ts # SOCKS5 proxy for network filtering
145
+ ├── linux-sandbox-utils.ts # Linux bubblewrap sandboxing
146
+ └── macos-sandbox-utils.ts # macOS sandbox-exec sandboxing
147
+ ```
148
+
149
+ ## Usage
150
+
151
+ ### As a CLI tool
152
+
153
+ The `srt` command (Anthropic Sandbox Runtime) wraps any command with security boundaries:
154
+
155
+ ```bash
156
+ # Run a command in the sandbox
157
+ srt echo "hello world"
158
+
159
+ # With debug logging
160
+ srt --debug curl https://example.com
161
+
162
+ # Specify custom settings file
163
+ srt --settings /path/to/settings.json npm install
164
+ ```
165
+
166
+ ### As a library
167
+
168
+ ```typescript
169
+ import { SandboxManager } from '@anthropic-ai/sandbox-runtime'
170
+ import { spawn } from 'child_process'
171
+
172
+ // Initialize the sandbox (starts proxy servers, etc.)
173
+ await SandboxManager.initialize()
174
+
175
+ // Wrap a command with sandbox restrictions
176
+ const sandboxedCommand = await SandboxManager.wrapWithSandbox('curl https://example.com')
177
+
178
+ // Execute the sandboxed command
179
+ const child = spawn(sandboxedCommand, { shell: true, stdio: 'inherit' })
180
+
181
+ // Handle exit
182
+ child.on('exit', (code) => {
183
+ console.log(`Command exited with code ${code}`)
184
+ })
185
+
186
+ // Cleanup when done (optional, happens automatically on process exit)
187
+ await SandboxManager.reset()
188
+ ```
189
+
190
+ #### Available exports
191
+
192
+ ```typescript
193
+ // Main sandbox manager
194
+ export { SandboxManager } from '@anthropic-ai/sandbox-runtime'
195
+
196
+ // Violation tracking
197
+ export { SandboxViolationStore } from '@anthropic-ai/sandbox-runtime'
198
+
199
+ // TypeScript types
200
+ export type {
201
+ SandboxAskCallback,
202
+ IgnoreViolationsConfig,
203
+ FsReadRestrictionConfig,
204
+ FsWriteRestrictionConfig,
205
+ NetworkRestrictionConfig,
206
+ } from '@anthropic-ai/sandbox-runtime'
207
+ ```
208
+
209
+ ## Configuration
210
+
211
+ **NOTE: Configuration format is provisional and subject to change.** The current configuration system is borrowed from Claude Code's permission model and uses Claude Code settings files. This format may evolve as the sandbox runtime matures as a standalone tool.
212
+
213
+ ### Settings File Locations
214
+
215
+ Settings are loaded and merged in priority order from:
216
+
217
+ 1. **User settings**: `~/.claude/settings.json`
218
+ 2. **Project settings**: `$CWD/.claude/settings.json`
219
+ 3. **Local settings**: `$CWD/.claude/settings.local.json`
220
+ 4. **Policy settings**: Platform-specific managed settings
221
+ - macOS: `/Library/Application Support/ClaudeCode/managed-settings.json`
222
+ - Linux: `/etc/claude-code/managed-settings.json`
223
+ 5. **Flag settings**: Custom path via `--settings` flag
224
+
225
+ ### Complete Configuration Example
226
+
227
+ ```json
228
+ {
229
+ "sandbox": {
230
+ "enabled": true,
231
+ "network": {
232
+ "allowUnixSockets": ["/var/run/docker.sock"],
233
+ "allowLocalBinding": false,
234
+ "httpProxyPort": 8888,
235
+ "socksProxyPort": 1080
236
+ }
237
+ },
238
+ "permissions": {
239
+ "allow": [
240
+ "WebFetch(domain:github.com)",
241
+ "WebFetch(domain:lfs.github.com)",
242
+ "WebFetch(domain:api.github.com)",
243
+ "WebFetch(domain:npmjs.org)",
244
+ "Edit(src/)",
245
+ "Edit(test/)",
246
+ "Read(.)"
247
+ ],
248
+ "deny": [
249
+ "Edit(.env)",
250
+ "Edit(config/production.json)",
251
+ "Read(~/.ssh)",
252
+ "WebFetch(domain:malicious.com)"
253
+ ]
254
+ }
255
+ }
256
+ ```
257
+
258
+ ### Configuration Options
259
+
260
+ #### Sandbox Settings
261
+
262
+ - `sandbox.enabled` - Enable/disable sandboxing (boolean)
263
+ - `sandbox.network.allowUnixSockets` - Unix sockets that can be accessed (array of paths)
264
+ - `sandbox.network.allowLocalBinding` - Allow binding to local ports (boolean)
265
+ - `sandbox.network.httpProxyPort` - Port for your own HTTP proxy (default: uses built-in proxy)
266
+ - `sandbox.network.socksProxyPort` - Port for your own SOCKS5 proxy (default: uses built-in proxy)
267
+
268
+ #### Permission Rules
269
+
270
+ Permission rules provide fine-grained control and use Claude Code's permission syntax:
271
+
272
+ - `WebFetch(domain:example.com)` - Allow/deny network access to a domain
273
+ - `Edit(path)` - Allow/deny file write access
274
+ - `Read(path)` - Allow/deny file read access
275
+
276
+ **Path Syntax (macOS):**
277
+
278
+ Paths support git-style glob patterns on macOS, similar to `.gitignore` syntax:
279
+
280
+ - `*` - Matches any characters except `/` (e.g., `*.ts` matches `foo.ts` but not `foo/bar.ts`)
281
+ - `**` - Matches any characters including `/` (e.g., `src/**/*.ts` matches all `.ts` files in `src/`)
282
+ - `?` - Matches any single character except `/` (e.g., `file?.txt` matches `file1.txt`)
283
+ - `[abc]` - Matches any character in the set (e.g., `file[0-9].txt` matches `file3.txt`)
284
+
285
+ Examples:
286
+ - `Edit(src/)` - Allow write to entire `src/` directory
287
+ - `Edit(src/**/*.ts)` - Allow write to all `.ts` files in `src/` and subdirectories
288
+ - `Read(~/.ssh)` - Deny read to SSH directory
289
+ - `Edit(.env)` - Deny write to `.env` file (even if current directory is allowed)
290
+
291
+ **Path Syntax (Linux):**
292
+
293
+ **Linux currently does not support glob matching.** Use literal paths only:
294
+ - `Edit(src/)` - Allow write to `src/` directory
295
+ - `Read(/home/user/.ssh)` - Deny read to SSH directory
296
+
297
+ **All platforms:**
298
+ - Paths can be absolute (e.g., `/home/user/.ssh`) or relative to the current working directory (e.g., `./src`)
299
+ - `~` expands to the user's home directory
300
+
301
+ ### Common Configuration Recipes
302
+
303
+ **Allow GitHub access** (all necessary endpoints):
304
+ ```json
305
+ {
306
+ "permissions": {
307
+ "allow": [
308
+ "WebFetch(domain:github.com)",
309
+ "WebFetch(domain:lfs.github.com)",
310
+ "WebFetch(domain:api.github.com)"
311
+ ]
312
+ }
313
+ }
314
+ ```
315
+
316
+ **Restrict to specific directories:**
317
+ ```json
318
+ {
319
+ "permissions": {
320
+ "allow": [
321
+ "Edit(src/)",
322
+ "Edit(test/)",
323
+ "Read(.)"
324
+ ],
325
+ "deny": [
326
+ "Edit(.env)",
327
+ "Edit(secrets/)",
328
+ "Read(~/.ssh)"
329
+ ]
330
+ }
331
+ }
332
+ ```
333
+
334
+ ### Common Issues and Tips
335
+
336
+ **Running Jest:** Use `--no-watchman` flag to avoid sandbox violations:
337
+ ```bash
338
+ srt "jest --no-watchman"
339
+ ```
340
+
341
+ Watchman accesses files outside the sandbox boundaries, which will trigger permission errors. Disabling it allows Jest to run with the built-in file watcher instead.
342
+
343
+ ## Platform Support
344
+
345
+ - **macOS**: Uses `sandbox-exec` with custom profiles (no additional dependencies)
346
+ - **Linux**: Uses `bubblewrap` (bwrap) for containerization
347
+ - **Windows**: Not yet supported
348
+
349
+ ### Platform-Specific Dependencies
350
+
351
+ **Linux requires:**
352
+ - `bubblewrap` - Container runtime
353
+ - Ubuntu/Debian: `apt-get install bubblewrap`
354
+ - Fedora: `dnf install bubblewrap`
355
+ - Arch: `pacman -S bubblewrap`
356
+ - `socat` - Socket relay for proxy bridging
357
+ - Ubuntu/Debian: `apt-get install socat`
358
+ - Fedora: `dnf install socat`
359
+ - Arch: `pacman -S socat`
360
+ - `ripgrep` - Fast search tool for deny path detection
361
+ - Ubuntu/Debian: `apt-get install ripgrep`
362
+ - Fedora: `dnf install ripgrep`
363
+ - Arch: `pacman -S ripgrep`
364
+
365
+ **macOS requires:**
366
+ - `ripgrep` - Fast search tool for deny path detection
367
+ - Install via Homebrew: `brew install ripgrep`
368
+ - Or download from: https://github.com/BurntSushi/ripgrep/releases
369
+
370
+ ## Development
371
+
372
+ ```bash
373
+ # Install dependencies
374
+ npm install
375
+
376
+ # Build the project
377
+ npm run build
378
+
379
+ # Type checking
380
+ npm run typecheck
381
+
382
+ # Lint code
383
+ npm run lint
384
+
385
+ # Format code
386
+ npm run format
387
+ ```
388
+
389
+ ## Implementation Details
390
+
391
+ ### Network Isolation Architecture
392
+
393
+ The sandbox runs HTTP and SOCKS5 proxy servers on the host machine that filter all network requests based on permission rules:
394
+
395
+ 1. **HTTP/HTTPS Traffic**: An HTTP proxy server intercepts requests and validates them against allowed/denied domains
396
+ 2. **Other Network Traffic**: A SOCKS5 proxy handles all other TCP connections (SSH, database connections, etc.)
397
+ 3. **Permission Enforcement**: The proxies enforce the `permissions` rules from your configuration
398
+
399
+ **Platform-specific proxy communication:**
400
+
401
+ - **Linux**: Requests are routed via the filesystem over Unix domain sockets (using `socat` for bridging). The network namespace is removed from the bubblewrap container, ensuring all network traffic must go through the proxies.
402
+
403
+ - **macOS**: The Seatbelt profile allows communication only to specific localhost ports where the proxies listen. All other network access is blocked.
404
+
405
+ ### Filesystem Isolation
406
+
407
+ Filesystem restrictions are enforced at the OS level:
408
+
409
+ - **macOS**: Uses `sandbox-exec` with dynamically generated Seatbelt profiles that specify allowed read/write paths
410
+ - **Linux**: Uses `bubblewrap` with bind mounts, marking directories as read-only or read-write based on configuration
411
+
412
+ **Default filesystem permissions:**
413
+
414
+ - **Read**: Allowed everywhere by default. You can deny specific paths using `Read(path)` deny rules
415
+ - Example: Deny `Read(~/.ssh)` to block access to SSH keys
416
+
417
+ - **Write**: Only allowed in the current working directory by default. You can:
418
+ - Allow additional paths using `Edit(path)` allow rules (e.g., `Edit(/tmp)`)
419
+ - Deny specific paths within allowed directories (e.g., deny `Edit(.env)` even though `.` is allowed)
420
+
421
+ This model lets you start with broad read access but tightly controlled write access, then refine both as needed.
422
+
423
+ ### Violation Detection and Monitoring
424
+
425
+ When a sandboxed process attempts to access a restricted resource:
426
+
427
+ 1. **Blocks the operation** at the OS level (returns `EPERM` error)
428
+ 2. **Logs the violation** (platform-specific mechanisms)
429
+ 3. **Notifies the user** (in Claude Code, this triggers a permission prompt)
430
+
431
+ **macOS**: The sandbox runtime taps into macOS's system sandbox violation log store. This provides real-time notifications with detailed information about what was attempted and why it was blocked. This is the same mechanism Claude Code uses for violation detection.
432
+
433
+ ```bash
434
+ # View sandbox violations in real-time
435
+ log stream --predicate 'process == "sandbox-exec"' --style syslog
436
+ ```
437
+
438
+ **Linux**: Bubblewrap doesn't provide built-in violation reporting. Use `strace` to trace system calls and identify blocked operations:
439
+
440
+ ```bash
441
+ # Trace all denied operations
442
+ strace -f srt <your-command> 2>&1 | grep EPERM
443
+
444
+ # Trace specific file operations
445
+ strace -f -e trace=open,openat,stat,access srt <your-command> 2>&1 | grep EPERM
446
+
447
+ # Trace network operations
448
+ strace -f -e trace=network srt <your-command> 2>&1 | grep EPERM
449
+ ```
450
+
451
+ ### Advanced: Bring Your Own Proxy
452
+
453
+ For more sophisticated network filtering, you can configure the sandbox to use your own proxy instead of the built-in ones. This enables:
454
+
455
+ - **Traffic inspection**: Use tools like [mitmproxy](https://mitmproxy.org/) to inspect and modify traffic
456
+ - **Custom filtering logic**: Implement complex rules beyond simple domain allowlists
457
+ - **Audit logging**: Log all network requests for compliance or debugging
458
+
459
+ **Example with mitmproxy:**
460
+
461
+ ```bash
462
+ # Start mitmproxy with custom filtering script
463
+ mitmproxy -s custom_filter.py --listen-port 8888
464
+
465
+ # Configure sandbox to use your proxy
466
+ {
467
+ "sandbox": {
468
+ "network": {
469
+ "httpProxyPort": 8888
470
+ }
471
+ }
472
+ }
473
+ ```
474
+
475
+ **Important security consideration:** Even with domain allowlists, exfiltration vectors may exist. For example, allowing `github.com` lets a process push to any repository. With a custom MITM proxy and proper certificate setup, you can inspect and filter specific API calls to prevent this.
476
+
477
+ ### Security Limitations
478
+
479
+ * Network Sandboxing Limitations: The network filtering system operates by restricting the domains that processes are allowed to connect to. It does not otherwise inspect the traffic passing through the proxy and users are responsible for ensuring they only allow trusted domains in their policy.
480
+
481
+ <Warning>
482
+ Users should be aware of potential risks that come from allowing broad domains like `github.com` that may allow for data exfiltration. Also, in some cases it may be possible to bypass the network filtering through [domain fronting](https://en.wikipedia.org/wiki/Domain_fronting).
483
+ </Warning>
484
+
485
+ * Privilege Escalation via Unix Sockets: The `allowUnixSockets` configuration can inadvertently grant access to powerful system services that could lead to sandbox bypasses. For example, if it is used to allow access to `/var/run/docker.sock` this would effectively grant access to the host system through exploiting the docker socket. Users are encouraged to carefully consider any unix sockets that they allow through the sandbox.
486
+ * Filesystem Permission Escalation: Overly broad filesystem write permissions can enable privilege escalation attacks. Allowing writes to directories containing executables in `$PATH`, system configuration directories, or user shell configuration files (`.bashrc`, `.zshrc`) can lead to code execution in different security contexts when other users or system processes access these files.
487
+ * Linux Sandbox Strength: The Linux implementation provides strong filesystem and network isolation but includes an `enableWeakerNestedSandbox` mode that enables it to work inside of Docker environments without privileged namespaces. This option considerably weakens security and should only be used incases where additional isolation is otherwise enforced.
488
+
489
+ ### Known Limitations and Future Work
490
+
491
+ **Linux proxy bypass**: Currently uses environment variables (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`) to direct traffic through proxies. This works for most applications but may be ignored by programs that don't respect these variables, leading to them being unable to connect to the internet.
492
+
493
+ **Future improvements:**
494
+
495
+ - **Proxychains support**: Add support for `proxychains` with `LD_PRELOAD` on Linux to intercept network calls at a lower level, making bypass more difficult
496
+
497
+ - **Linux violation monitoring**: Implement automatic `strace`-based violation detection for Linux, integrated with the violation store. Currently, Linux users must manually run `strace` to see violations, unlike macOS which has automatic violation monitoring via the system log store
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { SandboxManager } from './index.js';
4
+ import { spawn } from 'child_process';
5
+ import { logForDebugging } from './utils/debug.js';
6
+ import { setFlagSettingsPath } from './utils/settings.js';
7
+ async function main() {
8
+ const program = new Command();
9
+ program
10
+ .name('srt')
11
+ .description('Run commands in a sandbox with network and filesystem restrictions')
12
+ .version('1.0.0');
13
+ // Default command - run command in sandbox
14
+ program
15
+ .argument('<command...>', 'command to run in the sandbox')
16
+ .option('-d, --debug', 'enable debug logging')
17
+ .option('-s, --settings <path>', 'path to settings file (default: ~/.claude/settings.json)')
18
+ .allowUnknownOption()
19
+ .action(async (commandArgs, options) => {
20
+ try {
21
+ // Enable debug logging if requested
22
+ if (options.debug) {
23
+ process.env.DEBUG = 'true';
24
+ }
25
+ // Set flag settings path if provided
26
+ if (options.settings) {
27
+ setFlagSettingsPath(options.settings);
28
+ }
29
+ // Initialize sandbox
30
+ logForDebugging('Initializing sandbox...');
31
+ await SandboxManager.initialize();
32
+ // Join command arguments into a single command string
33
+ const command = commandArgs.join(' ');
34
+ logForDebugging(`Original command: ${command}`);
35
+ logForDebugging(JSON.stringify(SandboxManager.getNetworkRestrictionConfig(), null, 2));
36
+ // Wrap the command with sandbox restrictions
37
+ const sandboxedCommand = await SandboxManager.wrapWithSandbox(command);
38
+ // Execute the sandboxed command
39
+ console.log(`Running: ${command}`);
40
+ const child = spawn(sandboxedCommand, {
41
+ shell: true,
42
+ stdio: 'inherit',
43
+ });
44
+ // Handle process exit
45
+ child.on('exit', (code, signal) => {
46
+ if (signal) {
47
+ console.error(`Process killed by signal: ${signal}`);
48
+ process.exit(1);
49
+ }
50
+ process.exit(code ?? 0);
51
+ });
52
+ child.on('error', error => {
53
+ console.error(`Failed to execute command: ${error.message}`);
54
+ process.exit(1);
55
+ });
56
+ // Handle cleanup on interrupt
57
+ process.on('SIGINT', () => {
58
+ child.kill('SIGINT');
59
+ });
60
+ process.on('SIGTERM', () => {
61
+ child.kill('SIGTERM');
62
+ });
63
+ }
64
+ catch (error) {
65
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
66
+ process.exit(1);
67
+ }
68
+ });
69
+ program.parse();
70
+ }
71
+ main().catch(error => {
72
+ console.error('Fatal error:', error);
73
+ process.exit(1);
74
+ });
75
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { SandboxManager } from './sandbox/sandbox-manager.js';
2
+ export { SandboxViolationStore } from './sandbox/sandbox-violation-store.js';
3
+ export type { SandboxAskCallback, IgnoreViolationsConfig, FsReadRestrictionConfig, FsWriteRestrictionConfig, NetworkRestrictionConfig, } from './sandbox/sandbox-schemas.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAA;AAC5E,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,8BAA8B,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // Library exports
2
+ export { SandboxManager } from './sandbox/sandbox-manager.js';
3
+ export { SandboxViolationStore } from './sandbox/sandbox-violation-store.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAA"}
@@ -0,0 +1,7 @@
1
+ import type { Socket, Server } from 'node:net';
2
+ import type { Duplex } from 'node:stream';
3
+ export interface HttpProxyServerOptions {
4
+ filter(port: number, host: string, socket: Socket | Duplex): Promise<boolean> | boolean;
5
+ }
6
+ export declare function createHttpProxyServer(options: HttpProxyServerOptions): Server;
7
+ //# sourceMappingURL=http-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-proxy.d.ts","sourceRoot":"","sources":["../../src/sandbox/http-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAQzC,MAAM,WAAW,sBAAsB;IACrC,MAAM,CACJ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,MAAM,GACtB,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;CAC9B;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAgI7E"}