@voratiq/sandbox-runtime 0.7.0-voratiq1
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/CHANGELOG.md +10 -0
- package/LICENSE +201 -0
- package/NOTICE +11 -0
- package/README.md +17 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +243 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox/generate-seccomp-filter.d.ts +56 -0
- package/dist/sandbox/generate-seccomp-filter.d.ts.map +1 -0
- package/dist/sandbox/generate-seccomp-filter.js +158 -0
- package/dist/sandbox/generate-seccomp-filter.js.map +1 -0
- package/dist/sandbox/http-proxy.d.ts +12 -0
- package/dist/sandbox/http-proxy.d.ts.map +1 -0
- package/dist/sandbox/http-proxy.js +489 -0
- package/dist/sandbox/http-proxy.js.map +1 -0
- package/dist/sandbox/linux-sandbox-utils.d.ts +111 -0
- package/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -0
- package/dist/sandbox/linux-sandbox-utils.js +518 -0
- package/dist/sandbox/linux-sandbox-utils.js.map +1 -0
- package/dist/sandbox/macos-sandbox-utils.d.ts +54 -0
- package/dist/sandbox/macos-sandbox-utils.d.ts.map +1 -0
- package/dist/sandbox/macos-sandbox-utils.js +559 -0
- package/dist/sandbox/macos-sandbox-utils.js.map +1 -0
- package/dist/sandbox/sandbox-config.d.ts +170 -0
- package/dist/sandbox/sandbox-config.d.ts.map +1 -0
- package/dist/sandbox/sandbox-config.js +126 -0
- package/dist/sandbox/sandbox-config.js.map +1 -0
- package/dist/sandbox/sandbox-manager.d.ts +35 -0
- package/dist/sandbox/sandbox-manager.d.ts.map +1 -0
- package/dist/sandbox/sandbox-manager.js +666 -0
- package/dist/sandbox/sandbox-manager.js.map +1 -0
- package/dist/sandbox/sandbox-schemas.d.ts +17 -0
- package/dist/sandbox/sandbox-schemas.d.ts.map +1 -0
- package/dist/sandbox/sandbox-schemas.js +2 -0
- package/dist/sandbox/sandbox-schemas.js.map +1 -0
- package/dist/sandbox/sandbox-utils.d.ts +53 -0
- package/dist/sandbox/sandbox-utils.d.ts.map +1 -0
- package/dist/sandbox/sandbox-utils.js +368 -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 +18 -0
- package/dist/sandbox/socks-proxy.d.ts.map +1 -0
- package/dist/sandbox/socks-proxy.js +242 -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/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 +20 -0
- package/dist/utils/ripgrep.d.ts.map +1 -0
- package/dist/utils/ripgrep.js +51 -0
- package/dist/utils/ripgrep.js.map +1 -0
- package/dist/utils/telemetry.d.ts +67 -0
- package/dist/utils/telemetry.d.ts.map +1 -0
- package/dist/utils/telemetry.js +249 -0
- package/dist/utils/telemetry.js.map +1 -0
- package/dist/vendor/seccomp/arm64/apply-seccomp +0 -0
- package/dist/vendor/seccomp/arm64/unix-block.bpf +0 -0
- package/dist/vendor/seccomp/x64/apply-seccomp +0 -0
- package/dist/vendor/seccomp/x64/unix-block.bpf +0 -0
- package/dist/vendor/seccomp-src/apply-seccomp.c +98 -0
- package/dist/vendor/seccomp-src/seccomp-unix-block.c +97 -0
- package/package.json +80 -0
- package/vendor/seccomp/arm64/apply-seccomp +0 -0
- package/vendor/seccomp/arm64/unix-block.bpf +0 -0
- package/vendor/seccomp/x64/apply-seccomp +0 -0
- package/vendor/seccomp/x64/unix-block.bpf +0 -0
- package/vendor/seccomp-src/apply-seccomp.c +98 -0
- package/vendor/seccomp-src/seccomp-unix-block.c +97 -0
|
@@ -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,111 @@
|
|
|
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
|
+
allowAllUnixSockets?: boolean;
|
|
23
|
+
binShell?: string;
|
|
24
|
+
ripgrepConfig?: {
|
|
25
|
+
command: string;
|
|
26
|
+
args?: string[];
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if Linux sandbox dependencies are available (synchronous)
|
|
31
|
+
* Returns true if bwrap and socat are installed.
|
|
32
|
+
* Unless allowAllUnixSockets is enabled, also requires seccomp dependencies:
|
|
33
|
+
* - On x64/arm64: Pre-generated BPF filters and apply-seccomp binaries available
|
|
34
|
+
* - On other architectures: Not currently supported (no apply-seccomp binary available)
|
|
35
|
+
*/
|
|
36
|
+
export declare function hasLinuxSandboxDependenciesSync(allowAllUnixSockets?: boolean): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Initialize the Linux network bridge for sandbox networking
|
|
39
|
+
*
|
|
40
|
+
* ARCHITECTURE NOTE:
|
|
41
|
+
* Linux network sandboxing uses bwrap --unshare-net which creates a completely isolated
|
|
42
|
+
* network namespace with NO network access. To enable network access, we:
|
|
43
|
+
*
|
|
44
|
+
* 1. Host side: Run socat bridges that listen on Unix sockets and forward to host proxy servers
|
|
45
|
+
* - HTTP bridge: Unix socket -> host HTTP proxy (for HTTP/HTTPS traffic)
|
|
46
|
+
* - SOCKS bridge: Unix socket -> host SOCKS5 proxy (for SSH/git traffic)
|
|
47
|
+
*
|
|
48
|
+
* 2. Sandbox side: Bind the Unix sockets into the isolated namespace and run socat listeners
|
|
49
|
+
* - HTTP listener on port 3128 -> HTTP Unix socket -> host HTTP proxy
|
|
50
|
+
* - SOCKS listener on port 1080 -> SOCKS Unix socket -> host SOCKS5 proxy
|
|
51
|
+
*
|
|
52
|
+
* 3. Configure environment:
|
|
53
|
+
* - HTTP_PROXY=http://localhost:3128 for HTTP/HTTPS tools
|
|
54
|
+
* - GIT_SSH_COMMAND with socat for SSH through SOCKS5
|
|
55
|
+
*
|
|
56
|
+
* LIMITATION: Unlike macOS sandbox which can enforce domain-based allowlists at the kernel level,
|
|
57
|
+
* Linux's --unshare-net provides only all-or-nothing network isolation. Domain filtering happens
|
|
58
|
+
* at the host proxy level, not the sandbox boundary. This means network restrictions on Linux
|
|
59
|
+
* depend on the proxy's filtering capabilities.
|
|
60
|
+
*
|
|
61
|
+
* DEPENDENCIES: Requires bwrap (bubblewrap) and socat
|
|
62
|
+
*/
|
|
63
|
+
export declare function initializeLinuxNetworkBridge(httpProxyPort: number, socksProxyPort: number): Promise<LinuxNetworkBridgeContext>;
|
|
64
|
+
/**
|
|
65
|
+
* Wrap a command with sandbox restrictions on Linux
|
|
66
|
+
*
|
|
67
|
+
* UNIX SOCKET BLOCKING (APPLY-SECCOMP):
|
|
68
|
+
* This implementation uses a custom apply-seccomp binary to block Unix domain socket
|
|
69
|
+
* creation for user commands while allowing network infrastructure:
|
|
70
|
+
*
|
|
71
|
+
* Stage 1: Outer bwrap - Network and filesystem isolation (NO seccomp)
|
|
72
|
+
* - Bubblewrap starts with isolated network namespace (--unshare-net)
|
|
73
|
+
* - Bubblewrap applies PID namespace isolation (--unshare-pid and --proc)
|
|
74
|
+
* - Filesystem restrictions are applied (read-only mounts, bind mounts, etc.)
|
|
75
|
+
* - Socat processes start and connect to Unix socket bridges (can use socket(AF_UNIX, ...))
|
|
76
|
+
*
|
|
77
|
+
* Stage 2: apply-seccomp - Seccomp filter application (ONLY seccomp)
|
|
78
|
+
* - apply-seccomp binary applies seccomp filter via prctl(PR_SET_SECCOMP)
|
|
79
|
+
* - Sets PR_SET_NO_NEW_PRIVS to allow seccomp without root
|
|
80
|
+
* - Execs user command with seccomp active (cannot create new Unix sockets)
|
|
81
|
+
*
|
|
82
|
+
* This solves the conflict between:
|
|
83
|
+
* - Security: Blocking arbitrary Unix socket creation in user commands
|
|
84
|
+
* - Functionality: Network sandboxing requires socat to call socket(AF_UNIX, ...) for bridge connections
|
|
85
|
+
*
|
|
86
|
+
* The seccomp-bpf filter blocks socket(AF_UNIX, ...) syscalls, preventing:
|
|
87
|
+
* - Creating new Unix domain socket file descriptors
|
|
88
|
+
*
|
|
89
|
+
* Security limitations:
|
|
90
|
+
* - Does NOT block operations (bind, connect, sendto, etc.) on inherited Unix socket FDs
|
|
91
|
+
* - Does NOT prevent passing Unix socket FDs via SCM_RIGHTS
|
|
92
|
+
* - For most sandboxing use cases, blocking socket creation is sufficient
|
|
93
|
+
*
|
|
94
|
+
* The filter allows:
|
|
95
|
+
* - All TCP/UDP sockets (AF_INET, AF_INET6) for normal network operations
|
|
96
|
+
* - All other syscalls
|
|
97
|
+
*
|
|
98
|
+
* PLATFORM NOTE:
|
|
99
|
+
* The allowUnixSockets configuration is not path-based on Linux (unlike macOS)
|
|
100
|
+
* because seccomp-bpf cannot inspect user-space memory to read socket paths.
|
|
101
|
+
*
|
|
102
|
+
* Requirements for seccomp filtering:
|
|
103
|
+
* - Pre-built apply-seccomp binaries are included for x64 and ARM64
|
|
104
|
+
* - Pre-generated BPF filters are included for x64 and ARM64
|
|
105
|
+
* - Other architectures are not currently supported (no apply-seccomp binary available)
|
|
106
|
+
* - To use sandboxing without Unix socket blocking on unsupported architectures,
|
|
107
|
+
* set allowAllUnixSockets: true in your configuration
|
|
108
|
+
* Dependencies are checked by hasLinuxSandboxDependenciesSync() before enabling the sandbox.
|
|
109
|
+
*/
|
|
110
|
+
export declare function wrapCommandWithSandboxLinux(params: LinuxSandboxParams): Promise<string>;
|
|
111
|
+
//# 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;AAQ7B,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;IACnC,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CACrD;AA2BD;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,mBAAmB,UAAQ,GAC1B,OAAO,CA0CT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,yBAAyB,CAAC,CAqGpC;AAqLD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CAiNjB"}
|
|
@@ -0,0 +1,518 @@
|
|
|
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
|
+
import { generateSeccompFilter, cleanupSeccompFilter, getPreGeneratedBpfPath, getApplySeccompBinaryPath, } from './generate-seccomp-filter.js';
|
|
10
|
+
// Track generated seccomp filters for cleanup on process exit
|
|
11
|
+
const generatedSeccompFilters = new Set();
|
|
12
|
+
let exitHandlerRegistered = false;
|
|
13
|
+
/**
|
|
14
|
+
* Register cleanup handler for generated seccomp filters
|
|
15
|
+
*/
|
|
16
|
+
function registerSeccompCleanupHandler() {
|
|
17
|
+
if (exitHandlerRegistered) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
process.on('exit', () => {
|
|
21
|
+
for (const filterPath of generatedSeccompFilters) {
|
|
22
|
+
try {
|
|
23
|
+
cleanupSeccompFilter(filterPath);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Ignore cleanup errors during exit
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
exitHandlerRegistered = true;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check if Linux sandbox dependencies are available (synchronous)
|
|
34
|
+
* Returns true if bwrap and socat are installed.
|
|
35
|
+
* Unless allowAllUnixSockets is enabled, also requires seccomp dependencies:
|
|
36
|
+
* - On x64/arm64: Pre-generated BPF filters and apply-seccomp binaries available
|
|
37
|
+
* - On other architectures: Not currently supported (no apply-seccomp binary available)
|
|
38
|
+
*/
|
|
39
|
+
export function hasLinuxSandboxDependenciesSync(allowAllUnixSockets = false) {
|
|
40
|
+
try {
|
|
41
|
+
const bwrapResult = spawnSync('which', ['bwrap'], {
|
|
42
|
+
stdio: 'ignore',
|
|
43
|
+
timeout: 1000,
|
|
44
|
+
});
|
|
45
|
+
const socatResult = spawnSync('which', ['socat'], {
|
|
46
|
+
stdio: 'ignore',
|
|
47
|
+
timeout: 1000,
|
|
48
|
+
});
|
|
49
|
+
const hasBasicDeps = bwrapResult.status === 0 && socatResult.status === 0;
|
|
50
|
+
// Also require seccomp dependencies unless allowAllUnixSockets is enabled
|
|
51
|
+
if (!allowAllUnixSockets) {
|
|
52
|
+
// Check if we have a pre-generated BPF filter for this architecture
|
|
53
|
+
const hasPreGeneratedBpf = getPreGeneratedBpfPath() !== null;
|
|
54
|
+
// Check if we have the apply-seccomp binary for this architecture
|
|
55
|
+
const hasApplySeccompBinary = getApplySeccompBinaryPath() !== null;
|
|
56
|
+
if (hasPreGeneratedBpf && hasApplySeccompBinary) {
|
|
57
|
+
// Pre-generated BPF and apply-seccomp binary available (x64/arm64)
|
|
58
|
+
return hasBasicDeps;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Architecture not supported - no pre-built apply-seccomp binary available
|
|
62
|
+
// Note: We cannot fall back to runtime BPF compilation because we need
|
|
63
|
+
// the apply-seccomp binary to actually apply the filter
|
|
64
|
+
logForDebugging(`[Sandbox Linux] Architecture ${process.arch} is not supported for seccomp filtering. ` +
|
|
65
|
+
`Only x64 and arm64 are currently supported. To disable Unix socket blocking, ` +
|
|
66
|
+
`set allowAllUnixSockets: true in your configuration.`, { level: 'warn' });
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return hasBasicDeps;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Initialize the Linux network bridge for sandbox networking
|
|
78
|
+
*
|
|
79
|
+
* ARCHITECTURE NOTE:
|
|
80
|
+
* Linux network sandboxing uses bwrap --unshare-net which creates a completely isolated
|
|
81
|
+
* network namespace with NO network access. To enable network access, we:
|
|
82
|
+
*
|
|
83
|
+
* 1. Host side: Run socat bridges that listen on Unix sockets and forward to host proxy servers
|
|
84
|
+
* - HTTP bridge: Unix socket -> host HTTP proxy (for HTTP/HTTPS traffic)
|
|
85
|
+
* - SOCKS bridge: Unix socket -> host SOCKS5 proxy (for SSH/git traffic)
|
|
86
|
+
*
|
|
87
|
+
* 2. Sandbox side: Bind the Unix sockets into the isolated namespace and run socat listeners
|
|
88
|
+
* - HTTP listener on port 3128 -> HTTP Unix socket -> host HTTP proxy
|
|
89
|
+
* - SOCKS listener on port 1080 -> SOCKS Unix socket -> host SOCKS5 proxy
|
|
90
|
+
*
|
|
91
|
+
* 3. Configure environment:
|
|
92
|
+
* - HTTP_PROXY=http://localhost:3128 for HTTP/HTTPS tools
|
|
93
|
+
* - GIT_SSH_COMMAND with socat for SSH through SOCKS5
|
|
94
|
+
*
|
|
95
|
+
* LIMITATION: Unlike macOS sandbox which can enforce domain-based allowlists at the kernel level,
|
|
96
|
+
* Linux's --unshare-net provides only all-or-nothing network isolation. Domain filtering happens
|
|
97
|
+
* at the host proxy level, not the sandbox boundary. This means network restrictions on Linux
|
|
98
|
+
* depend on the proxy's filtering capabilities.
|
|
99
|
+
*
|
|
100
|
+
* DEPENDENCIES: Requires bwrap (bubblewrap) and socat
|
|
101
|
+
*/
|
|
102
|
+
export async function initializeLinuxNetworkBridge(httpProxyPort, socksProxyPort) {
|
|
103
|
+
const socketId = randomBytes(8).toString('hex');
|
|
104
|
+
const httpSocketPath = join(tmpdir(), `claude-http-${socketId}.sock`);
|
|
105
|
+
const socksSocketPath = join(tmpdir(), `claude-socks-${socketId}.sock`);
|
|
106
|
+
// Start HTTP bridge
|
|
107
|
+
const httpSocatArgs = [
|
|
108
|
+
`UNIX-LISTEN:${httpSocketPath},fork,reuseaddr`,
|
|
109
|
+
`TCP:localhost:${httpProxyPort},keepalive,keepidle=10,keepintvl=5,keepcnt=3`,
|
|
110
|
+
];
|
|
111
|
+
logForDebugging(`Starting HTTP bridge: socat ${httpSocatArgs.join(' ')}`);
|
|
112
|
+
const httpBridgeProcess = spawn('socat', httpSocatArgs, {
|
|
113
|
+
stdio: 'ignore',
|
|
114
|
+
});
|
|
115
|
+
if (!httpBridgeProcess.pid) {
|
|
116
|
+
throw new Error('Failed to start HTTP bridge process');
|
|
117
|
+
}
|
|
118
|
+
// Start SOCKS bridge
|
|
119
|
+
const socksSocatArgs = [
|
|
120
|
+
`UNIX-LISTEN:${socksSocketPath},fork,reuseaddr`,
|
|
121
|
+
`TCP:localhost:${socksProxyPort},keepalive,keepidle=10,keepintvl=5,keepcnt=3`,
|
|
122
|
+
];
|
|
123
|
+
logForDebugging(`Starting SOCKS bridge: socat ${socksSocatArgs.join(' ')}`);
|
|
124
|
+
const socksBridgeProcess = spawn('socat', socksSocatArgs, {
|
|
125
|
+
stdio: 'ignore',
|
|
126
|
+
});
|
|
127
|
+
if (!socksBridgeProcess.pid) {
|
|
128
|
+
// Clean up HTTP bridge
|
|
129
|
+
if (httpBridgeProcess.pid) {
|
|
130
|
+
try {
|
|
131
|
+
process.kill(httpBridgeProcess.pid, 'SIGTERM');
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Ignore errors
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
throw new Error('Failed to start SOCKS bridge process');
|
|
138
|
+
}
|
|
139
|
+
// Wait for both sockets to be ready
|
|
140
|
+
const maxAttempts = 5;
|
|
141
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
142
|
+
if (!httpBridgeProcess.pid ||
|
|
143
|
+
httpBridgeProcess.killed ||
|
|
144
|
+
!socksBridgeProcess.pid ||
|
|
145
|
+
socksBridgeProcess.killed) {
|
|
146
|
+
throw new Error('Linux bridge process died unexpectedly');
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
// fs already imported
|
|
150
|
+
if (fs.existsSync(httpSocketPath) && fs.existsSync(socksSocketPath)) {
|
|
151
|
+
logForDebugging(`Linux bridges ready after ${i + 1} attempts`);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
logForDebugging(`Error checking sockets (attempt ${i + 1}): ${err}`, {
|
|
157
|
+
level: 'error',
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (i === maxAttempts - 1) {
|
|
161
|
+
// Clean up both processes
|
|
162
|
+
if (httpBridgeProcess.pid) {
|
|
163
|
+
try {
|
|
164
|
+
process.kill(httpBridgeProcess.pid, 'SIGTERM');
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Ignore errors
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (socksBridgeProcess.pid) {
|
|
171
|
+
try {
|
|
172
|
+
process.kill(socksBridgeProcess.pid, 'SIGTERM');
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Ignore errors
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
throw new Error(`Failed to create bridge sockets after ${maxAttempts} attempts`);
|
|
179
|
+
}
|
|
180
|
+
await new Promise(resolve => setTimeout(resolve, i * 100));
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
httpSocketPath,
|
|
184
|
+
socksSocketPath,
|
|
185
|
+
httpBridgeProcess,
|
|
186
|
+
socksBridgeProcess,
|
|
187
|
+
httpProxyPort,
|
|
188
|
+
socksProxyPort,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Build the command that runs inside the sandbox.
|
|
193
|
+
* Sets up HTTP proxy on port 3128 and SOCKS proxy on port 1080
|
|
194
|
+
*/
|
|
195
|
+
function buildSandboxCommand(httpSocketPath, socksSocketPath, userCommand, seccompFilterPath, shell) {
|
|
196
|
+
// Default to bash for backward compatibility
|
|
197
|
+
const shellPath = shell || 'bash';
|
|
198
|
+
const socatCommands = [
|
|
199
|
+
`socat TCP-LISTEN:3128,fork,reuseaddr UNIX-CONNECT:${httpSocketPath} >/dev/null 2>&1 &`,
|
|
200
|
+
`socat TCP-LISTEN:1080,fork,reuseaddr UNIX-CONNECT:${socksSocketPath} >/dev/null 2>&1 &`,
|
|
201
|
+
'trap "kill %1 %2 2>/dev/null; exit" EXIT',
|
|
202
|
+
];
|
|
203
|
+
// If seccomp filter is provided, use apply-seccomp to apply it
|
|
204
|
+
if (seccompFilterPath) {
|
|
205
|
+
// apply-seccomp approach:
|
|
206
|
+
// 1. Outer bwrap/bash: starts socat processes (can use Unix sockets)
|
|
207
|
+
// 2. apply-seccomp: applies seccomp filter and execs user command
|
|
208
|
+
// 3. User command runs with seccomp active (Unix sockets blocked)
|
|
209
|
+
//
|
|
210
|
+
// apply-seccomp is a simple C program that:
|
|
211
|
+
// - Sets PR_SET_NO_NEW_PRIVS
|
|
212
|
+
// - Applies the seccomp BPF filter via prctl(PR_SET_SECCOMP)
|
|
213
|
+
// - Execs the user command
|
|
214
|
+
//
|
|
215
|
+
// This is simpler and more portable than nested bwrap, with no FD redirects needed.
|
|
216
|
+
const applySeccompBinary = getApplySeccompBinaryPath();
|
|
217
|
+
if (!applySeccompBinary) {
|
|
218
|
+
throw new Error('apply-seccomp binary not found. This should have been caught earlier. ' +
|
|
219
|
+
'Ensure vendor/seccomp/{x64,arm64}/apply-seccomp binaries are included in the package.');
|
|
220
|
+
}
|
|
221
|
+
const applySeccompCmd = shellquote.quote([
|
|
222
|
+
applySeccompBinary,
|
|
223
|
+
seccompFilterPath,
|
|
224
|
+
shellPath,
|
|
225
|
+
'-c',
|
|
226
|
+
userCommand,
|
|
227
|
+
]);
|
|
228
|
+
const innerScript = [...socatCommands, applySeccompCmd].join('\n');
|
|
229
|
+
return `${shellPath} -c ${shellquote.quote([innerScript])}`;
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
// No seccomp filter - run user command directly
|
|
233
|
+
const innerScript = [
|
|
234
|
+
...socatCommands,
|
|
235
|
+
`eval ${shellquote.quote([userCommand])}`,
|
|
236
|
+
].join('\n');
|
|
237
|
+
return `${shellPath} -c ${shellquote.quote([innerScript])}`;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Generate filesystem bind mount arguments for bwrap
|
|
242
|
+
*/
|
|
243
|
+
async function generateFilesystemArgs(readConfig, writeConfig, ripgrepConfig = { command: 'rg' }) {
|
|
244
|
+
const args = [];
|
|
245
|
+
// fs already imported
|
|
246
|
+
// Determine initial root mount based on write restrictions
|
|
247
|
+
if (writeConfig) {
|
|
248
|
+
// Write restrictions: Start with read-only root, then allow writes to specific paths
|
|
249
|
+
args.push('--ro-bind', '/', '/');
|
|
250
|
+
// Collect normalized allowed write paths for later checking
|
|
251
|
+
const allowedWritePaths = [];
|
|
252
|
+
// Allow writes to specific paths
|
|
253
|
+
for (const pathPattern of writeConfig.allowOnly || []) {
|
|
254
|
+
const normalizedPath = normalizePathForSandbox(pathPattern);
|
|
255
|
+
logForDebugging(`[Sandbox Linux] Processing write path: ${pathPattern} -> ${normalizedPath}`);
|
|
256
|
+
// Skip /dev/* paths since --dev /dev already handles them
|
|
257
|
+
if (normalizedPath.startsWith('/dev/')) {
|
|
258
|
+
logForDebugging(`[Sandbox Linux] Skipping /dev path: ${normalizedPath}`);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
262
|
+
logForDebugging(`[Sandbox Linux] Skipping non-existent write path: ${normalizedPath}`);
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
args.push('--bind', normalizedPath, normalizedPath);
|
|
266
|
+
allowedWritePaths.push(normalizedPath);
|
|
267
|
+
}
|
|
268
|
+
// Deny writes within allowed paths (user-specified + mandatory denies)
|
|
269
|
+
const denyPaths = [
|
|
270
|
+
...(writeConfig.denyWithinAllow || []),
|
|
271
|
+
...(await getMandatoryDenyWithinAllow(ripgrepConfig)),
|
|
272
|
+
];
|
|
273
|
+
for (const pathPattern of denyPaths) {
|
|
274
|
+
const normalizedPath = normalizePathForSandbox(pathPattern);
|
|
275
|
+
// Skip /dev/* paths since --dev /dev already handles them
|
|
276
|
+
if (normalizedPath.startsWith('/dev/')) {
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
// Skip non-existent paths
|
|
280
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
281
|
+
logForDebugging(`[Sandbox Linux] Skipping non-existent deny path: ${normalizedPath}`);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
// Only add deny binding if this path is within an allowed write path
|
|
285
|
+
// Otherwise it's already read-only from the initial --ro-bind / /
|
|
286
|
+
const isWithinAllowedPath = allowedWritePaths.some(allowedPath => normalizedPath.startsWith(allowedPath + '/') ||
|
|
287
|
+
normalizedPath === allowedPath);
|
|
288
|
+
if (isWithinAllowedPath) {
|
|
289
|
+
args.push('--ro-bind', normalizedPath, normalizedPath);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
logForDebugging(`[Sandbox Linux] Skipping deny path not within allowed paths: ${normalizedPath}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
// No write restrictions: Allow all writes
|
|
298
|
+
args.push('--bind', '/', '/');
|
|
299
|
+
}
|
|
300
|
+
// Handle read restrictions by mounting tmpfs over denied paths
|
|
301
|
+
const readDenyPaths = [...(readConfig?.denyOnly || [])];
|
|
302
|
+
// Always hide /etc/ssh/ssh_config.d to avoid permission issues with OrbStack
|
|
303
|
+
// SSH is very strict about config file permissions and ownership, and they can
|
|
304
|
+
// appear wrong inside the sandbox causing "Bad owner or permissions" errors
|
|
305
|
+
if (fs.existsSync('/etc/ssh/ssh_config.d')) {
|
|
306
|
+
readDenyPaths.push('/etc/ssh/ssh_config.d');
|
|
307
|
+
}
|
|
308
|
+
for (const pathPattern of readDenyPaths) {
|
|
309
|
+
const normalizedPath = normalizePathForSandbox(pathPattern);
|
|
310
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
311
|
+
logForDebugging(`[Sandbox Linux] Skipping non-existent read deny path: ${normalizedPath}`);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
const readDenyStat = fs.statSync(normalizedPath);
|
|
315
|
+
if (readDenyStat.isDirectory()) {
|
|
316
|
+
args.push('--tmpfs', normalizedPath);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
// For files, bind /dev/null instead of tmpfs
|
|
320
|
+
args.push('--ro-bind', '/dev/null', normalizedPath);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return args;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Wrap a command with sandbox restrictions on Linux
|
|
327
|
+
*
|
|
328
|
+
* UNIX SOCKET BLOCKING (APPLY-SECCOMP):
|
|
329
|
+
* This implementation uses a custom apply-seccomp binary to block Unix domain socket
|
|
330
|
+
* creation for user commands while allowing network infrastructure:
|
|
331
|
+
*
|
|
332
|
+
* Stage 1: Outer bwrap - Network and filesystem isolation (NO seccomp)
|
|
333
|
+
* - Bubblewrap starts with isolated network namespace (--unshare-net)
|
|
334
|
+
* - Bubblewrap applies PID namespace isolation (--unshare-pid and --proc)
|
|
335
|
+
* - Filesystem restrictions are applied (read-only mounts, bind mounts, etc.)
|
|
336
|
+
* - Socat processes start and connect to Unix socket bridges (can use socket(AF_UNIX, ...))
|
|
337
|
+
*
|
|
338
|
+
* Stage 2: apply-seccomp - Seccomp filter application (ONLY seccomp)
|
|
339
|
+
* - apply-seccomp binary applies seccomp filter via prctl(PR_SET_SECCOMP)
|
|
340
|
+
* - Sets PR_SET_NO_NEW_PRIVS to allow seccomp without root
|
|
341
|
+
* - Execs user command with seccomp active (cannot create new Unix sockets)
|
|
342
|
+
*
|
|
343
|
+
* This solves the conflict between:
|
|
344
|
+
* - Security: Blocking arbitrary Unix socket creation in user commands
|
|
345
|
+
* - Functionality: Network sandboxing requires socat to call socket(AF_UNIX, ...) for bridge connections
|
|
346
|
+
*
|
|
347
|
+
* The seccomp-bpf filter blocks socket(AF_UNIX, ...) syscalls, preventing:
|
|
348
|
+
* - Creating new Unix domain socket file descriptors
|
|
349
|
+
*
|
|
350
|
+
* Security limitations:
|
|
351
|
+
* - Does NOT block operations (bind, connect, sendto, etc.) on inherited Unix socket FDs
|
|
352
|
+
* - Does NOT prevent passing Unix socket FDs via SCM_RIGHTS
|
|
353
|
+
* - For most sandboxing use cases, blocking socket creation is sufficient
|
|
354
|
+
*
|
|
355
|
+
* The filter allows:
|
|
356
|
+
* - All TCP/UDP sockets (AF_INET, AF_INET6) for normal network operations
|
|
357
|
+
* - All other syscalls
|
|
358
|
+
*
|
|
359
|
+
* PLATFORM NOTE:
|
|
360
|
+
* The allowUnixSockets configuration is not path-based on Linux (unlike macOS)
|
|
361
|
+
* because seccomp-bpf cannot inspect user-space memory to read socket paths.
|
|
362
|
+
*
|
|
363
|
+
* Requirements for seccomp filtering:
|
|
364
|
+
* - Pre-built apply-seccomp binaries are included for x64 and ARM64
|
|
365
|
+
* - Pre-generated BPF filters are included for x64 and ARM64
|
|
366
|
+
* - Other architectures are not currently supported (no apply-seccomp binary available)
|
|
367
|
+
* - To use sandboxing without Unix socket blocking on unsupported architectures,
|
|
368
|
+
* set allowAllUnixSockets: true in your configuration
|
|
369
|
+
* Dependencies are checked by hasLinuxSandboxDependenciesSync() before enabling the sandbox.
|
|
370
|
+
*/
|
|
371
|
+
export async function wrapCommandWithSandboxLinux(params) {
|
|
372
|
+
const { command, hasNetworkRestrictions, hasFilesystemRestrictions, httpSocketPath, socksSocketPath, httpProxyPort, socksProxyPort, readConfig, writeConfig, enableWeakerNestedSandbox, allowAllUnixSockets, binShell, ripgrepConfig = { command: 'rg' }, } = params;
|
|
373
|
+
// Check if we need any sandboxing
|
|
374
|
+
if (!hasNetworkRestrictions && !hasFilesystemRestrictions) {
|
|
375
|
+
return command;
|
|
376
|
+
}
|
|
377
|
+
const bwrapArgs = [];
|
|
378
|
+
let seccompFilterPath = undefined;
|
|
379
|
+
try {
|
|
380
|
+
// ========== SECCOMP FILTER (Unix Socket Blocking) ==========
|
|
381
|
+
// Use bwrap's --seccomp flag to apply BPF filter that blocks Unix socket creation
|
|
382
|
+
//
|
|
383
|
+
// NOTE: Seccomp filtering is only enabled when allowAllUnixSockets is false
|
|
384
|
+
// (when true, Unix sockets are allowed)
|
|
385
|
+
if (!allowAllUnixSockets) {
|
|
386
|
+
seccompFilterPath = generateSeccompFilter() ?? undefined;
|
|
387
|
+
if (!seccompFilterPath) {
|
|
388
|
+
// Fail loudly - seccomp filtering is required for security
|
|
389
|
+
throw new Error('Failed to generate seccomp filter for Unix socket blocking. ' +
|
|
390
|
+
'This may occur on unsupported architectures (only x64 and arm64 are currently supported). ' +
|
|
391
|
+
'To disable Unix socket blocking, set allowAllUnixSockets: true in your configuration.');
|
|
392
|
+
}
|
|
393
|
+
// Track filter for cleanup and register exit handler
|
|
394
|
+
// Only track runtime-generated filters (not pre-generated ones from vendor/)
|
|
395
|
+
if (!seccompFilterPath.includes('/vendor/seccomp/')) {
|
|
396
|
+
generatedSeccompFilters.add(seccompFilterPath);
|
|
397
|
+
registerSeccompCleanupHandler();
|
|
398
|
+
}
|
|
399
|
+
logForDebugging('[Sandbox Linux] Generated seccomp BPF filter for Unix socket blocking');
|
|
400
|
+
}
|
|
401
|
+
else if (allowAllUnixSockets) {
|
|
402
|
+
logForDebugging('[Sandbox Linux] Skipping seccomp filter - allowAllUnixSockets is enabled');
|
|
403
|
+
}
|
|
404
|
+
// ========== NETWORK RESTRICTIONS ==========
|
|
405
|
+
if (hasNetworkRestrictions) {
|
|
406
|
+
// Only sandbox if we have network config and Linux bridges
|
|
407
|
+
if (!httpSocketPath || !socksSocketPath) {
|
|
408
|
+
throw new Error('Linux network sandboxing was requested but bridge socket paths are not available');
|
|
409
|
+
}
|
|
410
|
+
bwrapArgs.push('--unshare-net');
|
|
411
|
+
// Bind both sockets into the sandbox
|
|
412
|
+
bwrapArgs.push('--bind', httpSocketPath, httpSocketPath);
|
|
413
|
+
bwrapArgs.push('--bind', socksSocketPath, socksSocketPath);
|
|
414
|
+
// Add proxy environment variables
|
|
415
|
+
// HTTP_PROXY points to the socat listener inside the sandbox (port 3128)
|
|
416
|
+
// which forwards to the Unix socket that bridges to the host's proxy server
|
|
417
|
+
const proxyEnv = generateProxyEnvVars(3128, // Internal HTTP listener port
|
|
418
|
+
1080);
|
|
419
|
+
bwrapArgs.push(...proxyEnv.flatMap((env) => {
|
|
420
|
+
const firstEq = env.indexOf('=');
|
|
421
|
+
const key = env.slice(0, firstEq);
|
|
422
|
+
const value = env.slice(firstEq + 1);
|
|
423
|
+
return ['--setenv', key, value];
|
|
424
|
+
}));
|
|
425
|
+
// Add host proxy port environment variables for debugging/transparency
|
|
426
|
+
// These show which host ports the Unix socket bridges connect to
|
|
427
|
+
if (httpProxyPort !== undefined) {
|
|
428
|
+
bwrapArgs.push('--setenv', 'CLAUDE_CODE_HOST_HTTP_PROXY_PORT', String(httpProxyPort));
|
|
429
|
+
}
|
|
430
|
+
if (socksProxyPort !== undefined) {
|
|
431
|
+
bwrapArgs.push('--setenv', 'CLAUDE_CODE_HOST_SOCKS_PROXY_PORT', String(socksProxyPort));
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// ========== FILESYSTEM RESTRICTIONS ==========
|
|
435
|
+
const fsArgs = await generateFilesystemArgs(readConfig, writeConfig, ripgrepConfig);
|
|
436
|
+
bwrapArgs.push(...fsArgs);
|
|
437
|
+
// Always bind /dev
|
|
438
|
+
bwrapArgs.push('--dev', '/dev');
|
|
439
|
+
// ========== PID NAMESPACE ISOLATION ==========
|
|
440
|
+
// IMPORTANT: These must come AFTER filesystem binds for nested bwrap to work
|
|
441
|
+
// By default, always unshare PID namespace and mount fresh /proc.
|
|
442
|
+
// If we don't have --unshare-pid, it is possible to escape the sandbox.
|
|
443
|
+
// If we don't have --proc, it is possible to read host /proc and leak information about code running
|
|
444
|
+
// outside the sandbox. But, --proc is not available when running in unprivileged docker containers
|
|
445
|
+
// so we support running without it if explicitly requested.
|
|
446
|
+
bwrapArgs.push('--unshare-pid');
|
|
447
|
+
if (!enableWeakerNestedSandbox) {
|
|
448
|
+
// Mount fresh /proc if PID namespace is isolated (secure mode)
|
|
449
|
+
bwrapArgs.push('--proc', '/proc');
|
|
450
|
+
}
|
|
451
|
+
// ========== COMMAND ==========
|
|
452
|
+
// Use the user's shell (zsh, bash, etc.) to ensure aliases/snapshots work
|
|
453
|
+
// Resolve the full path to the shell binary since bwrap doesn't use $PATH
|
|
454
|
+
const shellName = binShell || 'bash';
|
|
455
|
+
const shellPathResult = spawnSync('which', [shellName], {
|
|
456
|
+
encoding: 'utf8',
|
|
457
|
+
});
|
|
458
|
+
if (shellPathResult.status !== 0) {
|
|
459
|
+
throw new Error(`Shell '${shellName}' not found in PATH`);
|
|
460
|
+
}
|
|
461
|
+
const shell = shellPathResult.stdout.trim();
|
|
462
|
+
bwrapArgs.push('--', shell, '-c');
|
|
463
|
+
// If we have network restrictions, use the network bridge setup with apply-seccomp for seccomp
|
|
464
|
+
// Otherwise, just run the command directly with apply-seccomp if needed
|
|
465
|
+
if (hasNetworkRestrictions && httpSocketPath && socksSocketPath) {
|
|
466
|
+
// Pass seccomp filter to buildSandboxCommand for apply-seccomp application
|
|
467
|
+
// This allows socat to start before seccomp is applied
|
|
468
|
+
const sandboxCommand = buildSandboxCommand(httpSocketPath, socksSocketPath, command, seccompFilterPath, shell);
|
|
469
|
+
bwrapArgs.push(sandboxCommand);
|
|
470
|
+
}
|
|
471
|
+
else if (seccompFilterPath) {
|
|
472
|
+
// No network restrictions but we have seccomp - use apply-seccomp directly
|
|
473
|
+
// apply-seccomp is a simple C program that applies the seccomp filter and execs the command
|
|
474
|
+
const applySeccompBinary = getApplySeccompBinaryPath();
|
|
475
|
+
if (!applySeccompBinary) {
|
|
476
|
+
throw new Error('apply-seccomp binary not found. This should have been caught earlier. ' +
|
|
477
|
+
'Ensure vendor/seccomp/{x64,arm64}/apply-seccomp binaries are included in the package.');
|
|
478
|
+
}
|
|
479
|
+
const applySeccompCmd = shellquote.quote([
|
|
480
|
+
applySeccompBinary,
|
|
481
|
+
seccompFilterPath,
|
|
482
|
+
shell,
|
|
483
|
+
'-c',
|
|
484
|
+
command,
|
|
485
|
+
]);
|
|
486
|
+
bwrapArgs.push(applySeccompCmd);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
bwrapArgs.push(command);
|
|
490
|
+
}
|
|
491
|
+
// Build the outer bwrap command
|
|
492
|
+
const wrappedCommand = shellquote.quote(['bwrap', ...bwrapArgs]);
|
|
493
|
+
const restrictions = [];
|
|
494
|
+
if (hasNetworkRestrictions)
|
|
495
|
+
restrictions.push('network');
|
|
496
|
+
if (hasFilesystemRestrictions)
|
|
497
|
+
restrictions.push('filesystem');
|
|
498
|
+
if (seccompFilterPath)
|
|
499
|
+
restrictions.push('seccomp(unix-block)');
|
|
500
|
+
logForDebugging(`[Sandbox Linux] Wrapped command with bwrap (${restrictions.join(', ')} restrictions)`);
|
|
501
|
+
return wrappedCommand;
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
// Clean up seccomp filter on error
|
|
505
|
+
if (seccompFilterPath && !seccompFilterPath.includes('/vendor/seccomp/')) {
|
|
506
|
+
generatedSeccompFilters.delete(seccompFilterPath);
|
|
507
|
+
try {
|
|
508
|
+
cleanupSeccompFilter(seccompFilterPath);
|
|
509
|
+
}
|
|
510
|
+
catch (cleanupError) {
|
|
511
|
+
logForDebugging(`[Sandbox Linux] Failed to clean up seccomp filter on error: ${cleanupError}`, { level: 'error' });
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
// Re-throw the original error
|
|
515
|
+
throw error;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
//# sourceMappingURL=linux-sandbox-utils.js.map
|