@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.
- package/README.md +497 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +75 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox/http-proxy.d.ts +7 -0
- package/dist/sandbox/http-proxy.d.ts.map +1 -0
- package/dist/sandbox/http-proxy.js +118 -0
- package/dist/sandbox/http-proxy.js.map +1 -0
- package/dist/sandbox/linux-sandbox-utils.d.ts +60 -0
- package/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -0
- package/dist/sandbox/linux-sandbox-utils.js +333 -0
- package/dist/sandbox/linux-sandbox-utils.js.map +1 -0
- package/dist/sandbox/macos-sandbox-utils.d.ts +53 -0
- package/dist/sandbox/macos-sandbox-utils.d.ts.map +1 -0
- package/dist/sandbox/macos-sandbox-utils.js +496 -0
- package/dist/sandbox/macos-sandbox-utils.js.map +1 -0
- package/dist/sandbox/sandbox-manager.d.ts +34 -0
- package/dist/sandbox/sandbox-manager.d.ts.map +1 -0
- package/dist/sandbox/sandbox-manager.js +655 -0
- package/dist/sandbox/sandbox-manager.js.map +1 -0
- package/dist/sandbox/sandbox-schemas.d.ts +93 -0
- package/dist/sandbox/sandbox-schemas.d.ts.map +1 -0
- package/dist/sandbox/sandbox-schemas.js +231 -0
- package/dist/sandbox/sandbox-schemas.js.map +1 -0
- package/dist/sandbox/sandbox-utils.d.ts +49 -0
- package/dist/sandbox/sandbox-utils.d.ts.map +1 -0
- package/dist/sandbox/sandbox-utils.js +345 -0
- package/dist/sandbox/sandbox-utils.js.map +1 -0
- package/dist/sandbox/sandbox-violation-store.d.ts +19 -0
- package/dist/sandbox/sandbox-violation-store.d.ts.map +1 -0
- package/dist/sandbox/sandbox-violation-store.js +54 -0
- package/dist/sandbox/sandbox-violation-store.js.map +1 -0
- package/dist/sandbox/socks-proxy.d.ts +13 -0
- package/dist/sandbox/socks-proxy.d.ts.map +1 -0
- package/dist/sandbox/socks-proxy.js +95 -0
- package/dist/sandbox/socks-proxy.js.map +1 -0
- package/dist/utils/debug.d.ts +7 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +22 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/exec.d.ts +13 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +38 -0
- package/dist/utils/exec.js.map +1 -0
- package/dist/utils/platform.d.ts +6 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +16 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/ripgrep.d.ts +16 -0
- package/dist/utils/ripgrep.d.ts.map +1 -0
- package/dist/utils/ripgrep.js +57 -0
- package/dist/utils/ripgrep.js.map +1 -0
- package/dist/utils/settings.d.ts +147 -0
- package/dist/utils/settings.d.ts.map +1 -0
- package/dist/utils/settings.js +244 -0
- package/dist/utils/settings.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { createServer } from 'node:http';
|
|
2
|
+
import { request as httpRequest } from 'node:http';
|
|
3
|
+
import { request as httpsRequest } from 'node:https';
|
|
4
|
+
import { connect } from 'node:net';
|
|
5
|
+
import { URL } from 'node:url';
|
|
6
|
+
import { logForDebugging } from '../utils/debug.js';
|
|
7
|
+
export function createHttpProxyServer(options) {
|
|
8
|
+
const server = createServer();
|
|
9
|
+
// Handle CONNECT requests for HTTPS traffic
|
|
10
|
+
server.on('connect', async (req, socket) => {
|
|
11
|
+
// Attach error handler immediately to prevent unhandled errors
|
|
12
|
+
socket.on('error', err => {
|
|
13
|
+
logForDebugging(`Client socket error: ${err.message}`, { level: 'error' });
|
|
14
|
+
});
|
|
15
|
+
try {
|
|
16
|
+
const [hostname, portStr] = req.url.split(':');
|
|
17
|
+
const port = portStr === undefined ? undefined : parseInt(portStr, 10);
|
|
18
|
+
if (!hostname || !port) {
|
|
19
|
+
logForDebugging(`Invalid CONNECT request: ${req.url}`, {
|
|
20
|
+
level: 'error',
|
|
21
|
+
});
|
|
22
|
+
socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const allowed = await options.filter(port, hostname, socket);
|
|
26
|
+
if (!allowed) {
|
|
27
|
+
logForDebugging(`Connection blocked to ${hostname}:${port}`, {
|
|
28
|
+
level: 'error',
|
|
29
|
+
});
|
|
30
|
+
socket.end('HTTP/1.1 403 Forbidden\r\n' +
|
|
31
|
+
'Content-Type: text/plain\r\n' +
|
|
32
|
+
'X-Proxy-Error: blocked-by-allowlist\r\n' +
|
|
33
|
+
'\r\n' +
|
|
34
|
+
'Connection blocked by network allowlist');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const serverSocket = connect(port, hostname, () => {
|
|
38
|
+
socket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
|
|
39
|
+
serverSocket.pipe(socket);
|
|
40
|
+
socket.pipe(serverSocket);
|
|
41
|
+
});
|
|
42
|
+
serverSocket.on('error', err => {
|
|
43
|
+
logForDebugging(`CONNECT tunnel failed: ${err.message}`, {
|
|
44
|
+
level: 'error',
|
|
45
|
+
});
|
|
46
|
+
socket.end('HTTP/1.1 502 Bad Gateway\r\n\r\n');
|
|
47
|
+
});
|
|
48
|
+
socket.on('error', err => {
|
|
49
|
+
logForDebugging(`Client socket error: ${err.message}`, {
|
|
50
|
+
level: 'error',
|
|
51
|
+
});
|
|
52
|
+
serverSocket.destroy();
|
|
53
|
+
});
|
|
54
|
+
socket.on('end', () => serverSocket.end());
|
|
55
|
+
serverSocket.on('end', () => socket.end());
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
logForDebugging(`Error handling CONNECT: ${err}`, { level: 'error' });
|
|
59
|
+
socket.end('HTTP/1.1 500 Internal Server Error\r\n\r\n');
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// Handle regular HTTP requests
|
|
63
|
+
server.on('request', async (req, res) => {
|
|
64
|
+
try {
|
|
65
|
+
const url = new URL(req.url);
|
|
66
|
+
const hostname = url.hostname;
|
|
67
|
+
const port = url.port
|
|
68
|
+
? parseInt(url.port, 10)
|
|
69
|
+
: url.protocol === 'https:'
|
|
70
|
+
? 443
|
|
71
|
+
: 80;
|
|
72
|
+
const allowed = await options.filter(port, hostname, req.socket);
|
|
73
|
+
if (!allowed) {
|
|
74
|
+
logForDebugging(`HTTP request blocked to ${hostname}:${port}`, {
|
|
75
|
+
level: 'error',
|
|
76
|
+
});
|
|
77
|
+
res.writeHead(403, {
|
|
78
|
+
'Content-Type': 'text/plain',
|
|
79
|
+
'X-Proxy-Error': 'blocked-by-allowlist',
|
|
80
|
+
});
|
|
81
|
+
res.end('Connection blocked by network allowlist');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// Choose http or https module
|
|
85
|
+
const requestFn = url.protocol === 'https:' ? httpsRequest : httpRequest;
|
|
86
|
+
const proxyReq = requestFn({
|
|
87
|
+
hostname,
|
|
88
|
+
port,
|
|
89
|
+
path: url.pathname + url.search,
|
|
90
|
+
method: req.method,
|
|
91
|
+
headers: {
|
|
92
|
+
...req.headers,
|
|
93
|
+
host: url.host,
|
|
94
|
+
},
|
|
95
|
+
}, proxyRes => {
|
|
96
|
+
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
97
|
+
proxyRes.pipe(res);
|
|
98
|
+
});
|
|
99
|
+
proxyReq.on('error', err => {
|
|
100
|
+
logForDebugging(`Proxy request failed: ${err.message}`, {
|
|
101
|
+
level: 'error',
|
|
102
|
+
});
|
|
103
|
+
if (!res.headersSent) {
|
|
104
|
+
res.writeHead(502, { 'Content-Type': 'text/plain' });
|
|
105
|
+
res.end('Bad Gateway');
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
req.pipe(proxyReq);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
logForDebugging(`Error handling HTTP request: ${err}`, { level: 'error' });
|
|
112
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
113
|
+
res.end('Internal Server Error');
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return server;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=http-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-proxy.js","sourceRoot":"","sources":["../../src/sandbox/http-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ChildProcess } from 'node:child_process';
|
|
2
|
+
import type { FsReadRestrictionConfig, FsWriteRestrictionConfig } from './sandbox-schemas.js';
|
|
3
|
+
export interface LinuxNetworkBridgeContext {
|
|
4
|
+
httpSocketPath: string;
|
|
5
|
+
socksSocketPath: string;
|
|
6
|
+
httpBridgeProcess: ChildProcess;
|
|
7
|
+
socksBridgeProcess: ChildProcess;
|
|
8
|
+
httpProxyPort: number;
|
|
9
|
+
socksProxyPort: number;
|
|
10
|
+
}
|
|
11
|
+
export interface LinuxSandboxParams {
|
|
12
|
+
command: string;
|
|
13
|
+
hasNetworkRestrictions: boolean;
|
|
14
|
+
hasFilesystemRestrictions: boolean;
|
|
15
|
+
httpSocketPath?: string;
|
|
16
|
+
socksSocketPath?: string;
|
|
17
|
+
httpProxyPort?: number;
|
|
18
|
+
socksProxyPort?: number;
|
|
19
|
+
readConfig?: FsReadRestrictionConfig;
|
|
20
|
+
writeConfig?: FsWriteRestrictionConfig;
|
|
21
|
+
enableWeakerNestedSandbox?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if Linux sandbox dependencies are available (synchronous)
|
|
25
|
+
* Returns true if bwrap, socat, and rg are installed, false otherwise
|
|
26
|
+
* Cached to avoid repeated system calls
|
|
27
|
+
*/
|
|
28
|
+
export declare function hasLinuxSandboxDependenciesSync(): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Initialize the Linux network bridge for sandbox networking
|
|
31
|
+
*
|
|
32
|
+
* ARCHITECTURE NOTE:
|
|
33
|
+
* Linux network sandboxing uses bwrap --unshare-net which creates a completely isolated
|
|
34
|
+
* network namespace with NO network access. To enable network access, we:
|
|
35
|
+
*
|
|
36
|
+
* 1. Host side: Run socat bridges that listen on Unix sockets and forward to host proxy servers
|
|
37
|
+
* - HTTP bridge: Unix socket -> host HTTP proxy (for HTTP/HTTPS traffic)
|
|
38
|
+
* - SOCKS bridge: Unix socket -> host SOCKS5 proxy (for SSH/git traffic)
|
|
39
|
+
*
|
|
40
|
+
* 2. Sandbox side: Bind the Unix sockets into the isolated namespace and run socat listeners
|
|
41
|
+
* - HTTP listener on port 3128 -> HTTP Unix socket -> host HTTP proxy
|
|
42
|
+
* - SOCKS listener on port 1080 -> SOCKS Unix socket -> host SOCKS5 proxy
|
|
43
|
+
*
|
|
44
|
+
* 3. Configure environment:
|
|
45
|
+
* - HTTP_PROXY=http://localhost:3128 for HTTP/HTTPS tools
|
|
46
|
+
* - GIT_SSH_COMMAND with socat for SSH through SOCKS5
|
|
47
|
+
*
|
|
48
|
+
* LIMITATION: Unlike macOS sandbox which can enforce domain-based allowlists at the kernel level,
|
|
49
|
+
* Linux's --unshare-net provides only all-or-nothing network isolation. Domain filtering happens
|
|
50
|
+
* at the host proxy level, not the sandbox boundary. This means network restrictions on Linux
|
|
51
|
+
* depend on the proxy's filtering capabilities.
|
|
52
|
+
*
|
|
53
|
+
* DEPENDENCIES: Requires bwrap (bubblewrap) and socat
|
|
54
|
+
*/
|
|
55
|
+
export declare function initializeLinuxNetworkBridge(httpProxyPort: number, socksProxyPort: number): Promise<LinuxNetworkBridgeContext>;
|
|
56
|
+
/**
|
|
57
|
+
* Wrap a command with sandbox restrictions on Linux
|
|
58
|
+
*/
|
|
59
|
+
export declare function wrapCommandWithSandboxLinux(params: LinuxSandboxParams): Promise<string>;
|
|
60
|
+
//# sourceMappingURL=linux-sandbox-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linux-sandbox-utils.d.ts","sourceRoot":"","sources":["../../src/sandbox/linux-sandbox-utils.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAQtD,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,sBAAsB,CAAA;AAE7B,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,YAAY,CAAA;IAC/B,kBAAkB,EAAE,YAAY,CAAA;IAChC,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,sBAAsB,EAAE,OAAO,CAAA;IAC/B,yBAAyB,EAAE,OAAO,CAAA;IAClC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,uBAAuB,CAAA;IACpC,WAAW,CAAC,EAAE,wBAAwB,CAAA;IACtC,yBAAyB,CAAC,EAAE,OAAO,CAAA;CACpC;AAKD;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,OAAO,CA4BzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,yBAAyB,CAAC,CAqGpC;AA4ID;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CAgHjB"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import shellquote from 'shell-quote';
|
|
2
|
+
import { logForDebugging } from '../utils/debug.js';
|
|
3
|
+
import { randomBytes } from 'node:crypto';
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
6
|
+
import { tmpdir } from 'node:os';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import { generateProxyEnvVars, normalizePathForSandbox, getMandatoryDenyWithinAllow, } from './sandbox-utils.js';
|
|
9
|
+
// Cache for Linux sandbox dependencies check
|
|
10
|
+
let linuxDepsCache;
|
|
11
|
+
/**
|
|
12
|
+
* Check if Linux sandbox dependencies are available (synchronous)
|
|
13
|
+
* Returns true if bwrap, socat, and rg are installed, false otherwise
|
|
14
|
+
* Cached to avoid repeated system calls
|
|
15
|
+
*/
|
|
16
|
+
export function hasLinuxSandboxDependenciesSync() {
|
|
17
|
+
if (linuxDepsCache !== undefined) {
|
|
18
|
+
return linuxDepsCache;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const bwrapResult = spawnSync('which', ['bwrap'], {
|
|
22
|
+
stdio: 'ignore',
|
|
23
|
+
timeout: 1000,
|
|
24
|
+
});
|
|
25
|
+
const socatResult = spawnSync('which', ['socat'], {
|
|
26
|
+
stdio: 'ignore',
|
|
27
|
+
timeout: 1000,
|
|
28
|
+
});
|
|
29
|
+
const rgResult = spawnSync('which', ['rg'], {
|
|
30
|
+
stdio: 'ignore',
|
|
31
|
+
timeout: 1000,
|
|
32
|
+
});
|
|
33
|
+
linuxDepsCache =
|
|
34
|
+
bwrapResult.status === 0 &&
|
|
35
|
+
socatResult.status === 0 &&
|
|
36
|
+
rgResult.status === 0;
|
|
37
|
+
return linuxDepsCache;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
linuxDepsCache = false;
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Initialize the Linux network bridge for sandbox networking
|
|
46
|
+
*
|
|
47
|
+
* ARCHITECTURE NOTE:
|
|
48
|
+
* Linux network sandboxing uses bwrap --unshare-net which creates a completely isolated
|
|
49
|
+
* network namespace with NO network access. To enable network access, we:
|
|
50
|
+
*
|
|
51
|
+
* 1. Host side: Run socat bridges that listen on Unix sockets and forward to host proxy servers
|
|
52
|
+
* - HTTP bridge: Unix socket -> host HTTP proxy (for HTTP/HTTPS traffic)
|
|
53
|
+
* - SOCKS bridge: Unix socket -> host SOCKS5 proxy (for SSH/git traffic)
|
|
54
|
+
*
|
|
55
|
+
* 2. Sandbox side: Bind the Unix sockets into the isolated namespace and run socat listeners
|
|
56
|
+
* - HTTP listener on port 3128 -> HTTP Unix socket -> host HTTP proxy
|
|
57
|
+
* - SOCKS listener on port 1080 -> SOCKS Unix socket -> host SOCKS5 proxy
|
|
58
|
+
*
|
|
59
|
+
* 3. Configure environment:
|
|
60
|
+
* - HTTP_PROXY=http://localhost:3128 for HTTP/HTTPS tools
|
|
61
|
+
* - GIT_SSH_COMMAND with socat for SSH through SOCKS5
|
|
62
|
+
*
|
|
63
|
+
* LIMITATION: Unlike macOS sandbox which can enforce domain-based allowlists at the kernel level,
|
|
64
|
+
* Linux's --unshare-net provides only all-or-nothing network isolation. Domain filtering happens
|
|
65
|
+
* at the host proxy level, not the sandbox boundary. This means network restrictions on Linux
|
|
66
|
+
* depend on the proxy's filtering capabilities.
|
|
67
|
+
*
|
|
68
|
+
* DEPENDENCIES: Requires bwrap (bubblewrap) and socat
|
|
69
|
+
*/
|
|
70
|
+
export async function initializeLinuxNetworkBridge(httpProxyPort, socksProxyPort) {
|
|
71
|
+
const socketId = randomBytes(8).toString('hex');
|
|
72
|
+
const httpSocketPath = join(tmpdir(), `claude-http-${socketId}.sock`);
|
|
73
|
+
const socksSocketPath = join(tmpdir(), `claude-socks-${socketId}.sock`);
|
|
74
|
+
// Start HTTP bridge
|
|
75
|
+
const httpSocatArgs = [
|
|
76
|
+
`UNIX-LISTEN:${httpSocketPath},fork,reuseaddr`,
|
|
77
|
+
`TCP:localhost:${httpProxyPort},keepalive,keepidle=10,keepintvl=5,keepcnt=3`,
|
|
78
|
+
];
|
|
79
|
+
logForDebugging(`Starting HTTP bridge: socat ${httpSocatArgs.join(' ')}`);
|
|
80
|
+
const httpBridgeProcess = spawn('socat', httpSocatArgs, {
|
|
81
|
+
stdio: 'ignore',
|
|
82
|
+
});
|
|
83
|
+
if (!httpBridgeProcess.pid) {
|
|
84
|
+
throw new Error('Failed to start HTTP bridge process');
|
|
85
|
+
}
|
|
86
|
+
// Start SOCKS bridge
|
|
87
|
+
const socksSocatArgs = [
|
|
88
|
+
`UNIX-LISTEN:${socksSocketPath},fork,reuseaddr`,
|
|
89
|
+
`TCP:localhost:${socksProxyPort},keepalive,keepidle=10,keepintvl=5,keepcnt=3`,
|
|
90
|
+
];
|
|
91
|
+
logForDebugging(`Starting SOCKS bridge: socat ${socksSocatArgs.join(' ')}`);
|
|
92
|
+
const socksBridgeProcess = spawn('socat', socksSocatArgs, {
|
|
93
|
+
stdio: 'ignore',
|
|
94
|
+
});
|
|
95
|
+
if (!socksBridgeProcess.pid) {
|
|
96
|
+
// Clean up HTTP bridge
|
|
97
|
+
if (httpBridgeProcess.pid) {
|
|
98
|
+
try {
|
|
99
|
+
process.kill(httpBridgeProcess.pid, 'SIGTERM');
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Ignore errors
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
throw new Error('Failed to start SOCKS bridge process');
|
|
106
|
+
}
|
|
107
|
+
// Wait for both sockets to be ready
|
|
108
|
+
const maxAttempts = 5;
|
|
109
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
110
|
+
if (!httpBridgeProcess.pid ||
|
|
111
|
+
httpBridgeProcess.killed ||
|
|
112
|
+
!socksBridgeProcess.pid ||
|
|
113
|
+
socksBridgeProcess.killed) {
|
|
114
|
+
throw new Error('Linux bridge process died unexpectedly');
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
// fs already imported
|
|
118
|
+
if (fs.existsSync(httpSocketPath) && fs.existsSync(socksSocketPath)) {
|
|
119
|
+
logForDebugging(`Linux bridges ready after ${i + 1} attempts`);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
logForDebugging(`Error checking sockets (attempt ${i + 1}): ${err}`, {
|
|
125
|
+
level: 'error',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if (i === maxAttempts - 1) {
|
|
129
|
+
// Clean up both processes
|
|
130
|
+
if (httpBridgeProcess.pid) {
|
|
131
|
+
try {
|
|
132
|
+
process.kill(httpBridgeProcess.pid, 'SIGTERM');
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Ignore errors
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (socksBridgeProcess.pid) {
|
|
139
|
+
try {
|
|
140
|
+
process.kill(socksBridgeProcess.pid, 'SIGTERM');
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Ignore errors
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
throw new Error(`Failed to create bridge sockets after ${maxAttempts} attempts`);
|
|
147
|
+
}
|
|
148
|
+
await new Promise(resolve => setTimeout(resolve, i * 100));
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
httpSocketPath,
|
|
152
|
+
socksSocketPath,
|
|
153
|
+
httpBridgeProcess,
|
|
154
|
+
socksBridgeProcess,
|
|
155
|
+
httpProxyPort,
|
|
156
|
+
socksProxyPort,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Build the command that runs inside the sandbox.
|
|
161
|
+
* Sets up HTTP proxy on port 3128 and SOCKS proxy on port 1080
|
|
162
|
+
*/
|
|
163
|
+
function buildSandboxCommand(httpSocketPath, socksSocketPath, userCommand) {
|
|
164
|
+
// Use a single trap that kills all jobs on EXIT
|
|
165
|
+
// This avoids issues with $! variable expansion through shellquote
|
|
166
|
+
const innerScript = [
|
|
167
|
+
`socat TCP-LISTEN:3128,fork,reuseaddr UNIX-CONNECT:${httpSocketPath} >/dev/null 2>&1 &`,
|
|
168
|
+
`socat TCP-LISTEN:1080,fork,reuseaddr UNIX-CONNECT:${socksSocketPath} >/dev/null 2>&1 &`,
|
|
169
|
+
'trap "kill %1 %2 2>/dev/null; exit" EXIT',
|
|
170
|
+
`eval ${shellquote.quote([userCommand])}`,
|
|
171
|
+
].join('\n');
|
|
172
|
+
return `bash -c ${shellquote.quote([innerScript])}`;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Generate filesystem bind mount arguments for bwrap
|
|
176
|
+
*/
|
|
177
|
+
async function generateFilesystemArgs(readConfig, writeConfig) {
|
|
178
|
+
const args = [];
|
|
179
|
+
// fs already imported
|
|
180
|
+
// Determine initial root mount based on write restrictions
|
|
181
|
+
if (writeConfig) {
|
|
182
|
+
// Write restrictions: Start with read-only root, then allow writes to specific paths
|
|
183
|
+
args.push('--ro-bind', '/', '/');
|
|
184
|
+
// Collect normalized allowed write paths for later checking
|
|
185
|
+
const allowedWritePaths = [];
|
|
186
|
+
// Allow writes to specific paths
|
|
187
|
+
for (const pathPattern of writeConfig.allowOnly || []) {
|
|
188
|
+
const normalizedPath = normalizePathForSandbox(pathPattern);
|
|
189
|
+
logForDebugging(`[Sandbox Linux] Processing write path: ${pathPattern} -> ${normalizedPath}`);
|
|
190
|
+
// Skip /dev/* paths since --dev /dev already handles them
|
|
191
|
+
if (normalizedPath.startsWith('/dev/')) {
|
|
192
|
+
logForDebugging(`[Sandbox Linux] Skipping /dev path: ${normalizedPath}`);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
196
|
+
logForDebugging(`[Sandbox Linux] Skipping non-existent write path: ${normalizedPath}`);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
args.push('--bind', normalizedPath, normalizedPath);
|
|
200
|
+
allowedWritePaths.push(normalizedPath);
|
|
201
|
+
}
|
|
202
|
+
// Deny writes within allowed paths (user-specified + mandatory denies)
|
|
203
|
+
const denyPaths = [
|
|
204
|
+
...(writeConfig.denyWithinAllow || []),
|
|
205
|
+
...(await getMandatoryDenyWithinAllow()),
|
|
206
|
+
];
|
|
207
|
+
for (const pathPattern of denyPaths) {
|
|
208
|
+
const normalizedPath = normalizePathForSandbox(pathPattern);
|
|
209
|
+
// Skip /dev/* paths since --dev /dev already handles them
|
|
210
|
+
if (normalizedPath.startsWith('/dev/')) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
// Skip non-existent paths
|
|
214
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
215
|
+
logForDebugging(`[Sandbox Linux] Skipping non-existent deny path: ${normalizedPath}`);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
// Only add deny binding if this path is within an allowed write path
|
|
219
|
+
// Otherwise it's already read-only from the initial --ro-bind / /
|
|
220
|
+
const isWithinAllowedPath = allowedWritePaths.some(allowedPath => normalizedPath.startsWith(allowedPath + '/') ||
|
|
221
|
+
normalizedPath === allowedPath);
|
|
222
|
+
if (isWithinAllowedPath) {
|
|
223
|
+
args.push('--ro-bind', normalizedPath, normalizedPath);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
logForDebugging(`[Sandbox Linux] Skipping deny path not within allowed paths: ${normalizedPath}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
// No write restrictions: Allow all writes
|
|
232
|
+
args.push('--bind', '/', '/');
|
|
233
|
+
}
|
|
234
|
+
// Handle read restrictions by mounting tmpfs over denied paths
|
|
235
|
+
const readDenyPaths = [...(readConfig?.denyOnly || [])];
|
|
236
|
+
// Always hide /etc/ssh/ssh_config.d to avoid permission issues with OrbStack
|
|
237
|
+
// SSH is very strict about config file permissions and ownership, and they can
|
|
238
|
+
// appear wrong inside the sandbox causing "Bad owner or permissions" errors
|
|
239
|
+
if (fs.existsSync('/etc/ssh/ssh_config.d')) {
|
|
240
|
+
readDenyPaths.push('/etc/ssh/ssh_config.d');
|
|
241
|
+
}
|
|
242
|
+
for (const pathPattern of readDenyPaths) {
|
|
243
|
+
const normalizedPath = normalizePathForSandbox(pathPattern);
|
|
244
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
245
|
+
logForDebugging(`[Sandbox Linux] Skipping non-existent read deny path: ${normalizedPath}`);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
const readDenyStat = fs.statSync(normalizedPath);
|
|
249
|
+
if (readDenyStat.isDirectory()) {
|
|
250
|
+
args.push('--tmpfs', normalizedPath);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
// For files, bind /dev/null instead of tmpfs
|
|
254
|
+
args.push('--ro-bind', '/dev/null', normalizedPath);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return args;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Wrap a command with sandbox restrictions on Linux
|
|
261
|
+
*/
|
|
262
|
+
export async function wrapCommandWithSandboxLinux(params) {
|
|
263
|
+
const { command, hasNetworkRestrictions, hasFilesystemRestrictions, httpSocketPath, socksSocketPath, httpProxyPort, socksProxyPort, readConfig, writeConfig, enableWeakerNestedSandbox, } = params;
|
|
264
|
+
// Check if we need any sandboxing
|
|
265
|
+
if (!hasNetworkRestrictions && !hasFilesystemRestrictions) {
|
|
266
|
+
return command;
|
|
267
|
+
}
|
|
268
|
+
const bwrapArgs = [];
|
|
269
|
+
// By default, always unshare PID namespace and mount fresh /proc.
|
|
270
|
+
// If we don't have --unshare-pid, it is possible to escape the sandbox.
|
|
271
|
+
// If we don't have --proc, it is possible to read host /proc and leak information about code running
|
|
272
|
+
// outside the sandbox. But, --proc is not available when running in unprivileged docker containers
|
|
273
|
+
// so we support running without it if explicitly requested.
|
|
274
|
+
bwrapArgs.push('--unshare-pid');
|
|
275
|
+
if (!enableWeakerNestedSandbox) {
|
|
276
|
+
// Mount fresh /proc if PID namespace is isolated (secure mode)
|
|
277
|
+
bwrapArgs.push('--proc', '/proc');
|
|
278
|
+
}
|
|
279
|
+
// ========== NETWORK RESTRICTIONS ==========
|
|
280
|
+
if (hasNetworkRestrictions) {
|
|
281
|
+
// Only sandbox if we have network config and Linux bridges
|
|
282
|
+
if (!httpSocketPath || !socksSocketPath) {
|
|
283
|
+
throw new Error('Linux network sandboxing was requested but bridge socket paths are not available');
|
|
284
|
+
}
|
|
285
|
+
bwrapArgs.push('--unshare-net');
|
|
286
|
+
// Bind both sockets into the sandbox
|
|
287
|
+
bwrapArgs.push('--bind', httpSocketPath, httpSocketPath);
|
|
288
|
+
bwrapArgs.push('--bind', socksSocketPath, socksSocketPath);
|
|
289
|
+
// Add proxy environment variables
|
|
290
|
+
// HTTP_PROXY points to the socat listener inside the sandbox (port 3128)
|
|
291
|
+
// which forwards to the Unix socket that bridges to the host's proxy server
|
|
292
|
+
const proxyEnv = generateProxyEnvVars(3128, // Internal HTTP listener port
|
|
293
|
+
1080);
|
|
294
|
+
bwrapArgs.push(...proxyEnv.flatMap((env) => {
|
|
295
|
+
const firstEq = env.indexOf('=');
|
|
296
|
+
const key = env.slice(0, firstEq);
|
|
297
|
+
const value = env.slice(firstEq + 1);
|
|
298
|
+
return ['--setenv', key, value];
|
|
299
|
+
}));
|
|
300
|
+
// Add host proxy port environment variables for debugging/transparency
|
|
301
|
+
// These show which host ports the Unix socket bridges connect to
|
|
302
|
+
if (httpProxyPort !== undefined) {
|
|
303
|
+
bwrapArgs.push('--setenv', 'CLAUDE_CODE_HOST_HTTP_PROXY_PORT', String(httpProxyPort));
|
|
304
|
+
}
|
|
305
|
+
if (socksProxyPort !== undefined) {
|
|
306
|
+
bwrapArgs.push('--setenv', 'CLAUDE_CODE_HOST_SOCKS_PROXY_PORT', String(socksProxyPort));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// ========== FILESYSTEM RESTRICTIONS ==========
|
|
310
|
+
const fsArgs = await generateFilesystemArgs(readConfig, writeConfig);
|
|
311
|
+
bwrapArgs.push(...fsArgs);
|
|
312
|
+
// Always bind /dev
|
|
313
|
+
bwrapArgs.push('--dev', '/dev');
|
|
314
|
+
// ========== COMMAND ==========
|
|
315
|
+
bwrapArgs.push('--', 'bash', '-c');
|
|
316
|
+
// If we have network restrictions, use the network bridge setup
|
|
317
|
+
// Otherwise, just run the command directly
|
|
318
|
+
if (hasNetworkRestrictions && httpSocketPath && socksSocketPath) {
|
|
319
|
+
bwrapArgs.push(buildSandboxCommand(httpSocketPath, socksSocketPath, command));
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
bwrapArgs.push(command);
|
|
323
|
+
}
|
|
324
|
+
const wrappedCommand = shellquote.quote(['bwrap', ...bwrapArgs]);
|
|
325
|
+
const restrictions = [];
|
|
326
|
+
if (hasNetworkRestrictions)
|
|
327
|
+
restrictions.push('network');
|
|
328
|
+
if (hasFilesystemRestrictions)
|
|
329
|
+
restrictions.push('filesystem');
|
|
330
|
+
logForDebugging(`[Sandbox Linux] Wrapped command with bwrap (${restrictions.join(', ')} restrictions)`);
|
|
331
|
+
return wrappedCommand;
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=linux-sandbox-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linux-sandbox-utils.js","sourceRoot":"","sources":["../../src/sandbox/linux-sandbox-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { IgnoreViolationsConfig, FsReadRestrictionConfig, FsWriteRestrictionConfig } from './sandbox-schemas.js';
|
|
2
|
+
/**
|
|
3
|
+
* Check if macOS sandbox dependencies are available (synchronous)
|
|
4
|
+
* Returns true if rg (ripgrep) is installed, false otherwise
|
|
5
|
+
* Cached to avoid repeated system calls
|
|
6
|
+
*/
|
|
7
|
+
export declare function hasMacOSSandboxDependenciesSync(): boolean;
|
|
8
|
+
export interface MacOSSandboxParams {
|
|
9
|
+
command: string;
|
|
10
|
+
httpProxyPort?: number;
|
|
11
|
+
socksProxyPort?: number;
|
|
12
|
+
needsNetworkRestriction: boolean;
|
|
13
|
+
allowUnixSockets?: string[];
|
|
14
|
+
allowLocalBinding?: boolean;
|
|
15
|
+
readConfig: FsReadRestrictionConfig | undefined;
|
|
16
|
+
writeConfig: FsWriteRestrictionConfig | undefined;
|
|
17
|
+
ignoreViolations?: IgnoreViolationsConfig | undefined;
|
|
18
|
+
}
|
|
19
|
+
export interface SandboxViolationEvent {
|
|
20
|
+
line: string;
|
|
21
|
+
command?: string;
|
|
22
|
+
encodedCommand?: string;
|
|
23
|
+
timestamp: Date;
|
|
24
|
+
}
|
|
25
|
+
export type SandboxViolationCallback = (violation: SandboxViolationEvent) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Convert a glob pattern to a regular expression for macOS sandbox profiles
|
|
28
|
+
*
|
|
29
|
+
* This implements gitignore-style pattern matching to match the behavior of the
|
|
30
|
+
* `ignore` library used by the permission system/
|
|
31
|
+
*
|
|
32
|
+
* Supported patterns:
|
|
33
|
+
* - * matches any characters except / (e.g., *.ts matches foo.ts but not foo/bar.ts)
|
|
34
|
+
* - ** matches any characters including / (e.g., src/** /*.ts matches all .ts files in src/)
|
|
35
|
+
* - ? matches any single character except / (e.g., file?.txt matches file1.txt)
|
|
36
|
+
* - [abc] matches any character in the set (e.g., file[0-9].txt matches file3.txt)
|
|
37
|
+
*
|
|
38
|
+
* Note: This is designed for macOS sandbox (regex ...) syntax. The resulting regex
|
|
39
|
+
* will be used in sandbox profiles like: (deny file-write* (regex "pattern"))
|
|
40
|
+
*
|
|
41
|
+
* Exported for testing purposes.
|
|
42
|
+
*/
|
|
43
|
+
export declare function globToRegex(globPattern: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Wrap command with macOS sandbox
|
|
46
|
+
*/
|
|
47
|
+
export declare function wrapCommandWithSandboxMacOS(params: MacOSSandboxParams): Promise<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Start monitoring macOS system logs for sandbox violations
|
|
50
|
+
* Look for sandbox-related kernel deny events ending in {logTag}
|
|
51
|
+
*/
|
|
52
|
+
export declare function startMacOSSandboxLogMonitor(callback: SandboxViolationCallback, ignoreViolations?: IgnoreViolationsConfig): () => void;
|
|
53
|
+
//# sourceMappingURL=macos-sandbox-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"macos-sandbox-utils.d.ts","sourceRoot":"","sources":["../../src/sandbox/macos-sandbox-utils.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,sBAAsB,CAAA;AAK7B;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,OAAO,CAiBzD;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,uBAAuB,EAAE,OAAO,CAAA;IAChC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,UAAU,EAAE,uBAAuB,GAAG,SAAS,CAAA;IAC/C,WAAW,EAAE,wBAAwB,GAAG,SAAS,CAAA;IACjD,gBAAgB,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAA;CACtD;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,IAAI,CAAA;CAChB;AAED,MAAM,MAAM,wBAAwB,GAAG,CACrC,SAAS,EAAE,qBAAqB,KAC7B,IAAI,CAAA;AAIT;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAkBvD;AAmYD;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CA2DjB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,wBAAwB,EAClC,gBAAgB,CAAC,EAAE,sBAAsB,GACxC,MAAM,IAAI,CA8GZ"}
|