@sysid/sandbox-runtime-improved 0.0.52-sysid.1 → 0.0.55-sysid.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 +5 -2
- package/dist/cli.js +91 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/sandbox/http-proxy.d.ts +7 -0
- package/dist/sandbox/http-proxy.d.ts.map +1 -1
- package/dist/sandbox/http-proxy.js +20 -0
- package/dist/sandbox/http-proxy.js.map +1 -1
- package/dist/sandbox/linux-sandbox-utils.d.ts +2 -0
- package/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -1
- package/dist/sandbox/linux-sandbox-utils.js +107 -46
- package/dist/sandbox/linux-sandbox-utils.js.map +1 -1
- package/dist/sandbox/macos-sandbox-utils.d.ts +3 -0
- package/dist/sandbox/macos-sandbox-utils.d.ts.map +1 -1
- package/dist/sandbox/macos-sandbox-utils.js +32 -3
- package/dist/sandbox/macos-sandbox-utils.js.map +1 -1
- package/dist/sandbox/mitm-leaf.d.ts.map +1 -1
- package/dist/sandbox/mitm-leaf.js +18 -5
- package/dist/sandbox/mitm-leaf.js.map +1 -1
- package/dist/sandbox/sandbox-config.d.ts +63 -2
- package/dist/sandbox/sandbox-config.d.ts.map +1 -1
- package/dist/sandbox/sandbox-config.js +52 -2
- package/dist/sandbox/sandbox-config.js.map +1 -1
- package/dist/sandbox/sandbox-manager.d.ts +5 -0
- package/dist/sandbox/sandbox-manager.d.ts.map +1 -1
- package/dist/sandbox/sandbox-manager.js +208 -44
- package/dist/sandbox/sandbox-manager.js.map +1 -1
- package/dist/sandbox/sandbox-schemas.d.ts +9 -3
- package/dist/sandbox/sandbox-schemas.d.ts.map +1 -1
- package/dist/sandbox/sandbox-utils.d.ts +1 -1
- package/dist/sandbox/sandbox-utils.d.ts.map +1 -1
- package/dist/sandbox/sandbox-utils.js +46 -18
- package/dist/sandbox/sandbox-utils.js.map +1 -1
- package/dist/sandbox/socks-proxy.d.ts +6 -0
- package/dist/sandbox/socks-proxy.d.ts.map +1 -1
- package/dist/sandbox/socks-proxy.js +11 -0
- package/dist/sandbox/socks-proxy.js.map +1 -1
- package/dist/sandbox/tls-terminate-proxy.js +18 -4
- package/dist/sandbox/tls-terminate-proxy.js.map +1 -1
- package/dist/sandbox/windows-sandbox-utils.d.ts +224 -0
- package/dist/sandbox/windows-sandbox-utils.d.ts.map +1 -0
- package/dist/sandbox/windows-sandbox-utils.js +433 -0
- package/dist/sandbox/windows-sandbox-utils.js.map +1 -0
- package/dist/vendor/srt-win/Cargo.lock +361 -0
- package/dist/vendor/srt-win/Cargo.toml +46 -0
- package/dist/vendor/srt-win/ci/cleanup.ps1 +49 -0
- package/dist/vendor/srt-win/ci/smoke-exec.ps1 +446 -0
- package/dist/vendor/srt-win/ci/smoke.ps1 +307 -0
- package/dist/vendor/srt-win/src/job.rs +102 -0
- package/dist/vendor/srt-win/src/launch.rs +732 -0
- package/dist/vendor/srt-win/src/lib.rs +20 -0
- package/dist/vendor/srt-win/src/main.rs +669 -0
- package/dist/vendor/srt-win/src/self_protect.rs +169 -0
- package/dist/vendor/srt-win/src/sid.rs +296 -0
- package/dist/vendor/srt-win/src/token.rs +341 -0
- package/dist/vendor/srt-win/src/util.rs +42 -0
- package/dist/vendor/srt-win/src/wfp.rs +992 -0
- package/dist/vendor/srt-win/src/winsta.rs +209 -0
- package/dist/vendor/srt-win/tests/sd_access_check_matrix.rs +259 -0
- package/package.json +2 -2
- package/vendor/srt-win/Cargo.lock +361 -0
- package/vendor/srt-win/Cargo.toml +46 -0
- package/vendor/srt-win/ci/cleanup.ps1 +49 -0
- package/vendor/srt-win/ci/smoke-exec.ps1 +446 -0
- package/vendor/srt-win/ci/smoke.ps1 +307 -0
- package/vendor/srt-win/src/job.rs +102 -0
- package/vendor/srt-win/src/launch.rs +732 -0
- package/vendor/srt-win/src/lib.rs +20 -0
- package/vendor/srt-win/src/main.rs +669 -0
- package/vendor/srt-win/src/self_protect.rs +169 -0
- package/vendor/srt-win/src/sid.rs +296 -0
- package/vendor/srt-win/src/token.rs +341 -0
- package/vendor/srt-win/src/util.rs +42 -0
- package/vendor/srt-win/src/wfp.rs +992 -0
- package/vendor/srt-win/src/winsta.rs +209 -0
- package/vendor/srt-win/tests/sd_access_check_matrix.rs +259 -0
|
@@ -95,8 +95,12 @@ export const NetworkConfigSchema = z.object({
|
|
|
95
95
|
.array(domainPatternSchema)
|
|
96
96
|
.describe('List of allowed domains (e.g., ["github.com", "*.npmjs.org"])'),
|
|
97
97
|
deniedDomains: z
|
|
98
|
-
.array(domainPatternSchema)
|
|
99
|
-
.describe('List of denied domains'),
|
|
98
|
+
.array(z.union([z.literal('*'), domainPatternSchema]))
|
|
99
|
+
.describe('List of denied domains. Unlike allowedDomains, a bare "*" is accepted here (deny-all).'),
|
|
100
|
+
strictAllowlist: z
|
|
101
|
+
.boolean()
|
|
102
|
+
.optional()
|
|
103
|
+
.describe('If true, hosts not in allowedDomains are denied without consulting the ask callback. Set this when allowedDomains is policy enforcement, not a prompt-suppression hint.'),
|
|
100
104
|
allowUnixSockets: z
|
|
101
105
|
.array(z.string())
|
|
102
106
|
.optional()
|
|
@@ -215,6 +219,42 @@ export const RipgrepConfigSchema = z.object({
|
|
|
215
219
|
.optional()
|
|
216
220
|
.describe('Override argv[0] when spawning (for multicall binaries that dispatch on argv[0])'),
|
|
217
221
|
});
|
|
222
|
+
/**
|
|
223
|
+
* Windows-specific configuration schema. See
|
|
224
|
+
* `windows-sandbox-utils.ts` for the install flow these settings
|
|
225
|
+
* must agree with.
|
|
226
|
+
*/
|
|
227
|
+
export const WindowsConfigSchema = z.object({
|
|
228
|
+
groupName: z
|
|
229
|
+
.string()
|
|
230
|
+
.min(1)
|
|
231
|
+
.default('sandbox-runtime-net')
|
|
232
|
+
.describe('Discriminator group name. Must match the group created at install ' +
|
|
233
|
+
'time. Ignored if groupSid is set.'),
|
|
234
|
+
groupSid: z
|
|
235
|
+
.string()
|
|
236
|
+
.regex(/^S-1-/, 'must be an S-1-… SID string')
|
|
237
|
+
.optional()
|
|
238
|
+
.describe('Discriminator group SID. Overrides groupName lookup — use for ' +
|
|
239
|
+
'domain groups or where name resolution is unreliable.'),
|
|
240
|
+
wfpSublayerGuid: z
|
|
241
|
+
.string()
|
|
242
|
+
.uuid()
|
|
243
|
+
.optional()
|
|
244
|
+
.describe('WFP sublayer GUID under which the filters were installed. Omit to ' +
|
|
245
|
+
'use the srt-win compile-time default. Set this when filters were ' +
|
|
246
|
+
'installed by enterprise tooling under a custom sublayer.'),
|
|
247
|
+
proxyPortRange: z
|
|
248
|
+
.tuple([z.number().int().min(1), z.number().int().max(65535)])
|
|
249
|
+
.refine(([lo, hi]) => lo <= hi && hi - lo <= 64, {
|
|
250
|
+
message: 'low must be ≤ high and range width ≤ 64',
|
|
251
|
+
})
|
|
252
|
+
.optional()
|
|
253
|
+
.describe('Inclusive [low, high] port range the JS http/socks proxies bind ' +
|
|
254
|
+
'inside. MUST match the range passed to `srt-win wfp install ' +
|
|
255
|
+
'--proxy-port-range` (default 60080–60089) — the WFP loopback ' +
|
|
256
|
+
'permit only covers ports in that range.'),
|
|
257
|
+
});
|
|
218
258
|
/**
|
|
219
259
|
* Seccomp configuration schema (Linux only)
|
|
220
260
|
*/
|
|
@@ -248,6 +288,15 @@ export const SandboxRuntimeConfigSchema = z.object({
|
|
|
248
288
|
'This is needed for Go programs (gh, gcloud, terraform, kubectl, etc.) to verify TLS certificates ' +
|
|
249
289
|
'when using httpProxyPort with a MITM proxy and custom CA. Enabling this opens a potential data ' +
|
|
250
290
|
'exfiltration vector through the trustd service. Only enable if you need Go TLS verification.'),
|
|
291
|
+
allowAppleEvents: z
|
|
292
|
+
.boolean()
|
|
293
|
+
.optional()
|
|
294
|
+
.describe('Allow sending Apple Events and Launch Services open requests from the sandbox (macOS only). ' +
|
|
295
|
+
'Needed for open, osascript, and anything that opens URLs or scripts other apps via AppleScript. ' +
|
|
296
|
+
'This removes code-execution isolation: sandboxed commands can launch other applications ' +
|
|
297
|
+
'unsandboxed with no user prompt (launched apps are not subject to the sandbox filesystem or ' +
|
|
298
|
+
'network restrictions), and can script running apps subject to TCC automation consent. ' +
|
|
299
|
+
'Default: false.'),
|
|
251
300
|
ripgrep: RipgrepConfigSchema.optional().describe('Custom ripgrep configuration (default: { command: "rg" })'),
|
|
252
301
|
mandatoryDenySearchDepth: z
|
|
253
302
|
.number()
|
|
@@ -278,5 +327,6 @@ export const SandboxRuntimeConfigSchema = z.object({
|
|
|
278
327
|
.optional()
|
|
279
328
|
.describe('Linux only: absolute path to the socat binary. ' +
|
|
280
329
|
'When set, this path is used directly instead of resolving "socat" via PATH.'),
|
|
330
|
+
windows: WindowsConfigSchema.optional().describe('Windows-specific settings (group, WFP sublayer, proxy port range).'),
|
|
281
331
|
});
|
|
282
332
|
//# sourceMappingURL=sandbox-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-config.js","sourceRoot":"","sources":["../../src/sandbox/sandbox-config.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"sandbox-config.js","sourceRoot":"","sources":["../../src/sandbox/sandbox-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,11 +23,16 @@ export interface ISandboxManager {
|
|
|
23
23
|
getIgnoreViolations(): Record<string, string[]> | undefined;
|
|
24
24
|
getEnableWeakerNestedSandbox(): boolean | undefined;
|
|
25
25
|
getProxyPort(): number | undefined;
|
|
26
|
+
getProxyAuthToken(): string | undefined;
|
|
26
27
|
getSocksProxyPort(): number | undefined;
|
|
27
28
|
getLinuxHttpSocketPath(): string | undefined;
|
|
28
29
|
getLinuxSocksSocketPath(): string | undefined;
|
|
29
30
|
waitForNetworkInitialization(): Promise<boolean>;
|
|
30
31
|
wrapWithSandbox(command: string, binShell?: string, customConfig?: Partial<SandboxRuntimeConfig>, abortSignal?: AbortSignal): Promise<string>;
|
|
32
|
+
wrapWithSandboxArgv(command: string, binShell?: string, customConfig?: Partial<SandboxRuntimeConfig>, abortSignal?: AbortSignal): Promise<{
|
|
33
|
+
argv: string[];
|
|
34
|
+
env: NodeJS.ProcessEnv;
|
|
35
|
+
}>;
|
|
31
36
|
getSandboxViolationStore(): SandboxViolationStore;
|
|
32
37
|
annotateStderrWithSandboxFailures(command: string, stderr: string): string;
|
|
33
38
|
getLinuxGlobPatternWarnings(): string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-manager.d.ts","sourceRoot":"","sources":["../../src/sandbox/sandbox-manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAA+B,KAAK,MAAM,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"sandbox-manager.d.ts","sourceRoot":"","sources":["../../src/sandbox/sandbox-manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAA+B,KAAK,MAAM,EAAE,MAAM,cAAc,CAAA;AAMvE,OAAO,KAAK,EAAE,oBAAoB,EAAiB,MAAM,qBAAqB,CAAA;AAC9E,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAKL,KAAK,sBAAsB,EAE5B,MAAM,0BAA0B,CAAA;AAmBjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AA4tCpE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CACR,aAAa,EAAE,oBAAoB,EACnC,kBAAkB,CAAC,EAAE,kBAAkB,EACvC,gBAAgB,CAAC,EAAE,OAAO,GACzB,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,mBAAmB,IAAI,OAAO,CAAA;IAC9B,mBAAmB,IAAI,OAAO,CAAA;IAC9B,iBAAiB,CAAC,aAAa,CAAC,EAAE;QAChC,OAAO,EAAE,MAAM,CAAA;QACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAChB,GAAG,sBAAsB,CAAA;IAC1B,eAAe,IAAI,uBAAuB,CAAA;IAC1C,gBAAgB,IAAI,wBAAwB,CAAA;IAC5C,2BAA2B,IAAI,wBAAwB,CAAA;IACvD,mBAAmB,IAAI,MAAM,EAAE,GAAG,SAAS,CAAA;IAC3C,oBAAoB,IAAI,OAAO,GAAG,SAAS,CAAA;IAC3C,kBAAkB,IAAI,MAAM,EAAE,GAAG,SAAS,CAAA;IAC1C,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAA;IAC3D,4BAA4B,IAAI,OAAO,GAAG,SAAS,CAAA;IACnD,YAAY,IAAI,MAAM,GAAG,SAAS,CAAA;IAClC,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAAA;IACvC,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAAA;IACvC,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAAA;IAC5C,uBAAuB,IAAI,MAAM,GAAG,SAAS,CAAA;IAC7C,4BAA4B,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IAChD,eAAe,CACb,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,mBAAmB,CACjB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,CAAC,CAAA;IACtD,wBAAwB,IAAI,qBAAqB,CAAA;IACjD,iCAAiC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1E,2BAA2B,IAAI,MAAM,EAAE,CAAA;IACvC,SAAS,IAAI,oBAAoB,GAAG,SAAS,CAAA;IAC7C,SAAS,IAAI,MAAM,GAAG,SAAS,CAAA;IAC/B,YAAY,CAAC,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAA;IACnD,mBAAmB,IAAI,IAAI,CAAA;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAMD;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,eA6BnB,CAAA"}
|
|
@@ -5,8 +5,10 @@ import { logForDebugging } from '../utils/debug.js';
|
|
|
5
5
|
import { whichSync } from '../utils/which.js';
|
|
6
6
|
import { getPlatform, getWslVersion } from '../utils/platform.js';
|
|
7
7
|
import * as fs from 'fs';
|
|
8
|
+
import { randomBytes } from 'node:crypto';
|
|
8
9
|
import { wrapCommandWithSandboxLinux, initializeLinuxNetworkBridge, checkLinuxDependencies, cleanupBwrapMountPoints, } from './linux-sandbox-utils.js';
|
|
9
10
|
import { wrapCommandWithSandboxMacOS, startMacOSSandboxLogMonitor, } from './macos-sandbox-utils.js';
|
|
11
|
+
import { checkWindowsDependencies, wrapCommandWithSandboxWindows, DEFAULT_WINDOWS_GROUP_NAME, DEFAULT_WINDOWS_PROXY_PORT_RANGE, } from './windows-sandbox-utils.js';
|
|
10
12
|
import { getDefaultWritePaths, containsGlobChars, removeTrailingGlobSuffix, expandGlobPattern, ensureSandboxTmpdir, } from './sandbox-utils.js';
|
|
11
13
|
import { SandboxViolationStore } from './sandbox-violation-store.js';
|
|
12
14
|
import { canonicalizeHost, isValidHost, redactUrl, resolveParentProxy, stripBrackets, } from './parent-proxy.js';
|
|
@@ -24,6 +26,10 @@ let cleanupRegistered = false;
|
|
|
24
26
|
let logMonitorShutdown;
|
|
25
27
|
let parentProxy;
|
|
26
28
|
let mitmCA;
|
|
29
|
+
// Per-session proxy auth token. Generated at proxy start, exported only into
|
|
30
|
+
// the sandbox child env, checked on every CONNECT/request — so a host process
|
|
31
|
+
// dialing 127.0.0.1:<proxyPort> can't reach the filter callback.
|
|
32
|
+
let proxyAuthToken;
|
|
27
33
|
const sandboxViolationStore = new SandboxViolationStore();
|
|
28
34
|
// ============================================================================
|
|
29
35
|
// Private Helper Functions (not exported)
|
|
@@ -44,6 +50,10 @@ function registerCleanup() {
|
|
|
44
50
|
}
|
|
45
51
|
function matchesDomainPattern(hostname, pattern) {
|
|
46
52
|
const h = hostname.toLowerCase();
|
|
53
|
+
// Bare '*' is deny-all when it appears in deniedDomains. The schema only
|
|
54
|
+
// accepts it there (allowedDomains still rejects it as too broad).
|
|
55
|
+
if (pattern === '*')
|
|
56
|
+
return true;
|
|
47
57
|
// Support wildcard patterns like *.example.com. Never apply wildcard
|
|
48
58
|
// suffix matching to IP literals — an IPv6 zone-ID payload like
|
|
49
59
|
// `::ffff:1.2.3.4%x.allowed.com` would otherwise pass .endsWith() while
|
|
@@ -93,8 +103,9 @@ async function filterNetworkRequest(port, host, sandboxAskCallback) {
|
|
|
93
103
|
return true;
|
|
94
104
|
}
|
|
95
105
|
}
|
|
96
|
-
// No matching rules - ask user or deny
|
|
97
|
-
|
|
106
|
+
// No matching rules - ask user or deny. strictAllowlist makes the
|
|
107
|
+
// allowlist deterministic enforcement: never fall through to the callback.
|
|
108
|
+
if (!sandboxAskCallback || config.network.strictAllowlist) {
|
|
98
109
|
logForDebugging(`No matching config rule, denying: ${host}:${port}`);
|
|
99
110
|
return false;
|
|
100
111
|
}
|
|
@@ -135,54 +146,102 @@ function getMitmSocketPath(host) {
|
|
|
135
146
|
}
|
|
136
147
|
return undefined;
|
|
137
148
|
}
|
|
138
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Bind `server.listen()` to the first free port in `[lo, hi]`,
|
|
151
|
+
* skipping `EADDRINUSE`. With `range` undefined, binds to ephemeral
|
|
152
|
+
* port 0 (the previous behaviour).
|
|
153
|
+
*
|
|
154
|
+
* Used on Windows: the WFP loopback permit only covers a fixed port
|
|
155
|
+
* range (default 60080–60089), so the JS proxies must bind inside it
|
|
156
|
+
* for the sandboxed child to reach them. On other platforms the
|
|
157
|
+
* sandbox layer (seatbelt rule, namespace+socat) targets whatever
|
|
158
|
+
* port we landed on, so ephemeral is fine.
|
|
159
|
+
*/
|
|
160
|
+
function listenInRange(server, doListen, range, exclude) {
|
|
161
|
+
return new Promise((resolve, reject) => {
|
|
162
|
+
const [lo, hi] = range ?? [0, 0];
|
|
163
|
+
let port = lo;
|
|
164
|
+
const tryNext = () => {
|
|
165
|
+
while (exclude.has(port) && port <= hi)
|
|
166
|
+
port++;
|
|
167
|
+
if (port > hi) {
|
|
168
|
+
reject(new Error(`No free port in range ${lo}-${hi} (excluding ${[...exclude].join(',')})`));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const onListening = () => {
|
|
172
|
+
server.removeListener('error', onError);
|
|
173
|
+
resolve();
|
|
174
|
+
};
|
|
175
|
+
const onError = (err) => {
|
|
176
|
+
// The paired 'listening' once-listener never fired; drop it
|
|
177
|
+
// so retries don't accumulate stale listeners.
|
|
178
|
+
server.removeListener('listening', onListening);
|
|
179
|
+
if (range &&
|
|
180
|
+
err?.code === 'EADDRINUSE' &&
|
|
181
|
+
port < hi) {
|
|
182
|
+
port++;
|
|
183
|
+
tryNext();
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
reject(err ?? new Error('listen error'));
|
|
187
|
+
};
|
|
188
|
+
server.once('error', onError);
|
|
189
|
+
server.once('listening', onListening);
|
|
190
|
+
doListen(range ? port : 0);
|
|
191
|
+
};
|
|
192
|
+
tryNext();
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
async function startHttpProxyServer(sandboxAskCallback, portRange, excludePorts) {
|
|
139
196
|
httpProxyServer = createHttpProxyServer({
|
|
140
197
|
filter: (port, host) => filterNetworkRequest(port, host, sandboxAskCallback),
|
|
141
198
|
getMitmSocketPath,
|
|
142
199
|
mitmCA,
|
|
143
200
|
filterRequest: config?.network.filterRequest,
|
|
144
201
|
parentProxy,
|
|
202
|
+
proxyAuthToken,
|
|
145
203
|
});
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (address && typeof address === 'object') {
|
|
156
|
-
server.unref();
|
|
157
|
-
logForDebugging(`HTTP proxy listening on localhost:${address.port}`);
|
|
158
|
-
resolve(address.port);
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
reject(new Error('Failed to get proxy server address'));
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
server.listen(0, '127.0.0.1');
|
|
165
|
-
});
|
|
204
|
+
const server = httpProxyServer;
|
|
205
|
+
await listenInRange(server, p => server.listen(p, '127.0.0.1'), portRange, excludePorts);
|
|
206
|
+
const address = server.address();
|
|
207
|
+
if (!address || typeof address !== 'object') {
|
|
208
|
+
throw new Error('Failed to get HTTP proxy server address');
|
|
209
|
+
}
|
|
210
|
+
server.unref();
|
|
211
|
+
logForDebugging(`HTTP proxy listening on localhost:${address.port}`);
|
|
212
|
+
return address.port;
|
|
166
213
|
}
|
|
167
|
-
async function startSocksProxyServer(sandboxAskCallback) {
|
|
214
|
+
async function startSocksProxyServer(sandboxAskCallback, portRange, excludePorts) {
|
|
168
215
|
socksProxyServer = createSocksProxyServer({
|
|
169
216
|
filter: (port, host) => filterNetworkRequest(port, host, sandboxAskCallback),
|
|
170
217
|
parentProxy,
|
|
218
|
+
proxyAuthToken,
|
|
171
219
|
});
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
220
|
+
const wrapper = socksProxyServer;
|
|
221
|
+
// SocksProxyWrapper.listen() resolves with the bound port; we
|
|
222
|
+
// adapt it to the listenInRange shape by retrying on EADDRINUSE
|
|
223
|
+
// here directly rather than via the once('error') path.
|
|
224
|
+
if (!portRange) {
|
|
225
|
+
const port = await wrapper.listen(0, '127.0.0.1');
|
|
226
|
+
wrapper.unref();
|
|
227
|
+
return port;
|
|
228
|
+
}
|
|
229
|
+
let lastErr;
|
|
230
|
+
for (let p = portRange[0]; p <= portRange[1]; p++) {
|
|
231
|
+
if (excludePorts.has(p))
|
|
232
|
+
continue;
|
|
233
|
+
try {
|
|
234
|
+
const port = await wrapper.listen(p, '127.0.0.1');
|
|
235
|
+
wrapper.unref();
|
|
236
|
+
return port;
|
|
177
237
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
});
|
|
238
|
+
catch (err) {
|
|
239
|
+
lastErr = err;
|
|
240
|
+
if (err?.code !== 'EADDRINUSE')
|
|
241
|
+
throw err;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
throw new Error(`No free SOCKS port in range ${portRange[0]}-${portRange[1]}: ${lastErr?.message ?? 'all in use'}`);
|
|
186
245
|
}
|
|
187
246
|
// ============================================================================
|
|
188
247
|
// Public Module Functions (will be exported via namespace)
|
|
@@ -229,7 +288,20 @@ async function initialize(runtimeConfig, sandboxAskCallback, enableLogMonitor =
|
|
|
229
288
|
// Initialize network infrastructure
|
|
230
289
|
initializationPromise = (async () => {
|
|
231
290
|
try {
|
|
232
|
-
//
|
|
291
|
+
// On Windows the WFP loopback permit covers a fixed port
|
|
292
|
+
// range, so the proxies must bind inside it. Other platforms
|
|
293
|
+
// bake the actual ephemeral port into the sandbox profile, so
|
|
294
|
+
// they keep using port 0.
|
|
295
|
+
const portRange = getPlatform() === 'windows'
|
|
296
|
+
? (config.windows?.proxyPortRange ?? DEFAULT_WINDOWS_PROXY_PORT_RANGE)
|
|
297
|
+
: undefined;
|
|
298
|
+
// The auth token is only set when this process owns the proxy; an
|
|
299
|
+
// external proxy (config.network.httpProxyPort) handles its own auth,
|
|
300
|
+
// and embedding our token in its URL would be wrong.
|
|
301
|
+
proxyAuthToken =
|
|
302
|
+
config.network.httpProxyPort !== undefined
|
|
303
|
+
? undefined
|
|
304
|
+
: randomBytes(16).toString('hex');
|
|
233
305
|
let httpProxyPort;
|
|
234
306
|
if (config.network.httpProxyPort !== undefined) {
|
|
235
307
|
// Use external HTTP proxy (don't start a server)
|
|
@@ -238,7 +310,7 @@ async function initialize(runtimeConfig, sandboxAskCallback, enableLogMonitor =
|
|
|
238
310
|
}
|
|
239
311
|
else {
|
|
240
312
|
// Start local HTTP proxy
|
|
241
|
-
httpProxyPort = await startHttpProxyServer(sandboxAskCallback);
|
|
313
|
+
httpProxyPort = await startHttpProxyServer(sandboxAskCallback, portRange, new Set());
|
|
242
314
|
}
|
|
243
315
|
let socksProxyPort;
|
|
244
316
|
if (config.network.socksProxyPort !== undefined) {
|
|
@@ -247,8 +319,9 @@ async function initialize(runtimeConfig, sandboxAskCallback, enableLogMonitor =
|
|
|
247
319
|
logForDebugging(`Using external SOCKS proxy on port ${socksProxyPort}`);
|
|
248
320
|
}
|
|
249
321
|
else {
|
|
250
|
-
// Start local SOCKS proxy
|
|
251
|
-
|
|
322
|
+
// Start local SOCKS proxy. Skip the port the HTTP proxy
|
|
323
|
+
// already took.
|
|
324
|
+
socksProxyPort = await startSocksProxyServer(sandboxAskCallback, portRange, new Set([httpProxyPort]));
|
|
252
325
|
}
|
|
253
326
|
// Initialize platform-specific infrastructure
|
|
254
327
|
let linuxBridge;
|
|
@@ -284,7 +357,17 @@ function isSupportedPlatform() {
|
|
|
284
357
|
// WSL1 doesn't support bubblewrap
|
|
285
358
|
return getWslVersion() !== '1';
|
|
286
359
|
}
|
|
287
|
-
return platform === 'macos';
|
|
360
|
+
return platform === 'macos' || platform === 'windows';
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Resolve the Windows group reference from config. Used by both the
|
|
364
|
+
* dependency check and `wrapWithSandbox` so they agree.
|
|
365
|
+
*/
|
|
366
|
+
function getWindowsGroupRef() {
|
|
367
|
+
return {
|
|
368
|
+
groupName: config?.windows?.groupName ?? DEFAULT_WINDOWS_GROUP_NAME,
|
|
369
|
+
groupSid: config?.windows?.groupSid,
|
|
370
|
+
};
|
|
288
371
|
}
|
|
289
372
|
function isSandboxingEnabled() {
|
|
290
373
|
// Sandboxing is enabled if config has been set (via initialize())
|
|
@@ -318,6 +401,11 @@ function checkDependencies(ripgrepConfig) {
|
|
|
318
401
|
errors.push(...linuxDeps.errors);
|
|
319
402
|
warnings.push(...linuxDeps.warnings);
|
|
320
403
|
}
|
|
404
|
+
else if (platform === 'windows') {
|
|
405
|
+
const winDeps = checkWindowsDependencies(getWindowsGroupRef(), config?.windows?.wfpSublayerGuid);
|
|
406
|
+
errors.push(...winDeps.errors);
|
|
407
|
+
warnings.push(...winDeps.warnings);
|
|
408
|
+
}
|
|
321
409
|
return { errors, warnings };
|
|
322
410
|
}
|
|
323
411
|
function getFsReadConfig() {
|
|
@@ -390,10 +478,16 @@ function getNetworkRestrictionConfig() {
|
|
|
390
478
|
if (!config) {
|
|
391
479
|
return {};
|
|
392
480
|
}
|
|
481
|
+
// Preserve an explicitly-empty allowlist: consumers need to distinguish
|
|
482
|
+
// "no network restriction configured" (absent) from "allowlist configured
|
|
483
|
+
// with zero entries" (block-all / ask-only). Stripping the empty array
|
|
484
|
+
// made a host app's restriction-status UI report an airgapped config as
|
|
485
|
+
// unrestricted. deniedHosts keeps the strip — an empty denylist and an
|
|
486
|
+
// absent one are semantically identical.
|
|
393
487
|
const allowedHosts = config.network.allowedDomains;
|
|
394
488
|
const deniedHosts = config.network.deniedDomains;
|
|
395
489
|
return {
|
|
396
|
-
|
|
490
|
+
allowedHosts,
|
|
397
491
|
...(deniedHosts.length > 0 && { deniedHosts }),
|
|
398
492
|
};
|
|
399
493
|
}
|
|
@@ -418,6 +512,9 @@ function getEnableWeakerNestedSandbox() {
|
|
|
418
512
|
function getEnableWeakerNetworkIsolation() {
|
|
419
513
|
return config?.enableWeakerNetworkIsolation;
|
|
420
514
|
}
|
|
515
|
+
function getAllowAppleEvents() {
|
|
516
|
+
return config?.allowAppleEvents;
|
|
517
|
+
}
|
|
421
518
|
function getRipgrepConfig() {
|
|
422
519
|
return config?.ripgrep ?? { command: 'rg' };
|
|
423
520
|
}
|
|
@@ -430,6 +527,9 @@ function getAllowGitConfig() {
|
|
|
430
527
|
function getSeccompConfig() {
|
|
431
528
|
return config?.seccomp;
|
|
432
529
|
}
|
|
530
|
+
function getProxyAuthToken() {
|
|
531
|
+
return proxyAuthToken;
|
|
532
|
+
}
|
|
433
533
|
function getProxyPort() {
|
|
434
534
|
return managerContext?.httpProxyPort;
|
|
435
535
|
}
|
|
@@ -548,6 +648,7 @@ async function wrapWithSandbox(command, binShell, customConfig, abortSignal) {
|
|
|
548
648
|
// Only pass proxy ports if proxy is running (when there are domains to filter)
|
|
549
649
|
httpProxyPort: needsNetworkProxy ? getProxyPort() : undefined,
|
|
550
650
|
socksProxyPort: needsNetworkProxy ? getSocksProxyPort() : undefined,
|
|
651
|
+
proxyAuthToken: needsNetworkProxy ? proxyAuthToken : undefined,
|
|
551
652
|
caCertPath: mitmCA?.certPath,
|
|
552
653
|
readConfig,
|
|
553
654
|
writeConfig,
|
|
@@ -560,6 +661,7 @@ async function wrapWithSandbox(command, binShell, customConfig, abortSignal) {
|
|
|
560
661
|
allowBrowserProcess,
|
|
561
662
|
allowGitConfig: getAllowGitConfig(),
|
|
562
663
|
enableWeakerNetworkIsolation: getEnableWeakerNetworkIsolation(),
|
|
664
|
+
allowAppleEvents: getAllowAppleEvents(),
|
|
563
665
|
binShell,
|
|
564
666
|
});
|
|
565
667
|
case 'linux':
|
|
@@ -579,6 +681,7 @@ async function wrapWithSandbox(command, binShell, customConfig, abortSignal) {
|
|
|
579
681
|
socksProxyPort: needsNetworkProxy
|
|
580
682
|
? managerContext?.socksProxyPort
|
|
581
683
|
: undefined,
|
|
684
|
+
proxyAuthToken: needsNetworkProxy ? proxyAuthToken : undefined,
|
|
582
685
|
caCertPath: mitmCA?.certPath,
|
|
583
686
|
readConfig,
|
|
584
687
|
writeConfig,
|
|
@@ -593,11 +696,55 @@ async function wrapWithSandbox(command, binShell, customConfig, abortSignal) {
|
|
|
593
696
|
socatPath: config?.socatPath,
|
|
594
697
|
abortSignal,
|
|
595
698
|
});
|
|
699
|
+
case 'windows':
|
|
700
|
+
// Windows wraps to an argv array, not a shell string. Forcing
|
|
701
|
+
// callers through wrapWithSandboxArgv() means they spawn with
|
|
702
|
+
// {shell:false}, which is the security boundary that keeps the
|
|
703
|
+
// user's command bytes off the HOST shell.
|
|
704
|
+
throw new Error('wrapWithSandbox() returns a shell string and is not supported ' +
|
|
705
|
+
'on Windows. Use SandboxManager.wrapWithSandboxArgv() and ' +
|
|
706
|
+
'spawn the result with {shell: false}.');
|
|
596
707
|
default:
|
|
597
708
|
// Unsupported platform - this should not happen since isSandboxingEnabled() checks platform support
|
|
598
709
|
throw new Error(`Sandbox configuration is not supported on platform: ${platform}`);
|
|
599
710
|
}
|
|
600
711
|
}
|
|
712
|
+
/**
|
|
713
|
+
* Wrap `command` for the sandbox and return a spawn descriptor:
|
|
714
|
+
* `{ argv, env }`, suitable for
|
|
715
|
+
* `spawn(argv[0], argv.slice(1), {shell: false, env})`.
|
|
716
|
+
*
|
|
717
|
+
* On Windows this is the ONLY supported wrap method (see
|
|
718
|
+
* {@link wrapWithSandbox}); `env` carries the full proxy set that the
|
|
719
|
+
* sandboxed child inherits (`srt-win exec` forwards its environment
|
|
720
|
+
* verbatim — see {@link wrapCommandWithSandboxWindows}). On
|
|
721
|
+
* macOS/Linux `argv` is `[binShell, '-c', <wrapWithSandbox result>]`
|
|
722
|
+
* (proxy env is baked into that command) and `env` is the unchanged
|
|
723
|
+
* `process.env`, so callers can spawn uniformly across platforms.
|
|
724
|
+
*/
|
|
725
|
+
async function wrapWithSandboxArgv(command, binShell, customConfig, abortSignal) {
|
|
726
|
+
const platform = getPlatform();
|
|
727
|
+
if (platform === 'windows') {
|
|
728
|
+
const hasNetworkConfig = customConfig?.network?.allowedDomains !== undefined ||
|
|
729
|
+
config?.network?.allowedDomains !== undefined;
|
|
730
|
+
if (hasNetworkConfig) {
|
|
731
|
+
await waitForNetworkInitialization();
|
|
732
|
+
}
|
|
733
|
+
return wrapCommandWithSandboxWindows({
|
|
734
|
+
command,
|
|
735
|
+
group: getWindowsGroupRef(),
|
|
736
|
+
httpProxyPort: hasNetworkConfig ? getProxyPort() : undefined,
|
|
737
|
+
socksProxyPort: hasNetworkConfig ? getSocksProxyPort() : undefined,
|
|
738
|
+
proxyAuthToken: hasNetworkConfig ? proxyAuthToken : undefined,
|
|
739
|
+
binShell,
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
// macOS/Linux: delegate to the existing string wrapper, then put
|
|
743
|
+
// the result behind `<shell> -c` so the caller's argv-spawn works.
|
|
744
|
+
const wrapped = await wrapWithSandbox(command, binShell, customConfig, abortSignal);
|
|
745
|
+
const shell = binShell ?? '/bin/bash';
|
|
746
|
+
return { argv: [shell, '-c', wrapped], env: process.env };
|
|
747
|
+
}
|
|
601
748
|
/**
|
|
602
749
|
* Get the current sandbox configuration
|
|
603
750
|
* @returns The current configuration, or undefined if not initialized
|
|
@@ -606,7 +753,21 @@ function getConfig() {
|
|
|
606
753
|
return config;
|
|
607
754
|
}
|
|
608
755
|
/**
|
|
609
|
-
* Update the sandbox configuration
|
|
756
|
+
* Update the sandbox configuration in place.
|
|
757
|
+
*
|
|
758
|
+
* **Network/allowlist changes are a live swap**: the running
|
|
759
|
+
* http/socks proxies read `config.network.allowedDomains` /
|
|
760
|
+
* `deniedDomains` per-request (via `filterNetworkRequest`), so
|
|
761
|
+
* reassigning `config` here takes effect on the next connection
|
|
762
|
+
* with no proxy rebind and no port change — on every platform,
|
|
763
|
+
* including Windows. This is what lets a host enable/deny domains
|
|
764
|
+
* for already-running sandboxed children.
|
|
765
|
+
*
|
|
766
|
+
* Filesystem changes (denyRead/denyWrite) are NOT applied live:
|
|
767
|
+
* macOS bakes them into the seatbelt profile at wrap time, and
|
|
768
|
+
* Windows will need an explicit re-stamp. To change FS
|
|
769
|
+
* restrictions, reset() then initialize() with the new config.
|
|
770
|
+
*
|
|
610
771
|
* @param newConfig - The new configuration to use
|
|
611
772
|
*/
|
|
612
773
|
function updateConfig(newConfig) {
|
|
@@ -805,6 +966,7 @@ async function reset() {
|
|
|
805
966
|
await Promise.all(closePromises);
|
|
806
967
|
// Clear references
|
|
807
968
|
httpProxyServer = undefined;
|
|
969
|
+
proxyAuthToken = undefined;
|
|
808
970
|
socksProxyServer = undefined;
|
|
809
971
|
managerContext = undefined;
|
|
810
972
|
initializationPromise = undefined;
|
|
@@ -881,11 +1043,13 @@ export const SandboxManager = {
|
|
|
881
1043
|
getIgnoreViolations,
|
|
882
1044
|
getEnableWeakerNestedSandbox,
|
|
883
1045
|
getProxyPort,
|
|
1046
|
+
getProxyAuthToken,
|
|
884
1047
|
getSocksProxyPort,
|
|
885
1048
|
getLinuxHttpSocketPath,
|
|
886
1049
|
getLinuxSocksSocketPath,
|
|
887
1050
|
waitForNetworkInitialization,
|
|
888
1051
|
wrapWithSandbox,
|
|
1052
|
+
wrapWithSandboxArgv,
|
|
889
1053
|
cleanupAfterCommand,
|
|
890
1054
|
reset,
|
|
891
1055
|
getMitmCA: () => mitmCA,
|