@namzu/sandbox 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/package.json +12 -2
  3. package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.d.ts +0 -2
  4. package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.d.ts.map +0 -1
  5. package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.js +0 -61
  6. package/dist/backends/aci-standby-pool/__tests__/unenforceable-controls.test.js.map +0 -1
  7. package/dist/backends/docker/__tests__/hardening.test.d.ts +0 -2
  8. package/dist/backends/docker/__tests__/hardening.test.d.ts.map +0 -1
  9. package/dist/backends/docker/__tests__/hardening.test.js +0 -32
  10. package/dist/backends/docker/__tests__/hardening.test.js.map +0 -1
  11. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts +0 -40
  12. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts.map +0 -1
  13. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js +0 -157
  14. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js.map +0 -1
  15. package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.d.ts +0 -16
  16. package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.d.ts.map +0 -1
  17. package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.js +0 -37
  18. package/dist/backends/firecracker/__tests__/agent-timeout-clamp.test.js.map +0 -1
  19. package/dist/backends/firecracker/__tests__/backend.test.d.ts +0 -13
  20. package/dist/backends/firecracker/__tests__/backend.test.d.ts.map +0 -1
  21. package/dist/backends/firecracker/__tests__/backend.test.js +0 -361
  22. package/dist/backends/firecracker/__tests__/backend.test.js.map +0 -1
  23. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts +0 -19
  24. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts.map +0 -1
  25. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js +0 -209
  26. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js.map +0 -1
  27. package/dist/backends/firecracker/__tests__/egress-policy.test.d.ts +0 -2
  28. package/dist/backends/firecracker/__tests__/egress-policy.test.d.ts.map +0 -1
  29. package/dist/backends/firecracker/__tests__/egress-policy.test.js +0 -67
  30. package/dist/backends/firecracker/__tests__/egress-policy.test.js.map +0 -1
  31. package/dist/backends/firecracker/__tests__/fixtures/ipc-path.d.ts +0 -21
  32. package/dist/backends/firecracker/__tests__/fixtures/ipc-path.d.ts.map +0 -1
  33. package/dist/backends/firecracker/__tests__/fixtures/ipc-path.js +0 -30
  34. package/dist/backends/firecracker/__tests__/fixtures/ipc-path.js.map +0 -1
  35. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts +0 -39
  36. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts.map +0 -1
  37. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js +0 -149
  38. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js.map +0 -1
  39. package/dist/backends/firecracker/__tests__/protocol.test.d.ts +0 -6
  40. package/dist/backends/firecracker/__tests__/protocol.test.d.ts.map +0 -1
  41. package/dist/backends/firecracker/__tests__/protocol.test.js +0 -67
  42. package/dist/backends/firecracker/__tests__/protocol.test.js.map +0 -1
  43. package/dist/backends/firecracker/__tests__/transport.test.d.ts +0 -20
  44. package/dist/backends/firecracker/__tests__/transport.test.d.ts.map +0 -1
  45. package/dist/backends/firecracker/__tests__/transport.test.js +0 -457
  46. package/dist/backends/firecracker/__tests__/transport.test.js.map +0 -1
  47. package/dist/egress/__tests__/allowlist.test.d.ts +0 -2
  48. package/dist/egress/__tests__/allowlist.test.d.ts.map +0 -1
  49. package/dist/egress/__tests__/allowlist.test.js +0 -85
  50. package/dist/egress/__tests__/allowlist.test.js.map +0 -1
  51. package/dist/egress/__tests__/proxy.test.d.ts +0 -2
  52. package/dist/egress/__tests__/proxy.test.d.ts.map +0 -1
  53. package/dist/egress/__tests__/proxy.test.js +0 -177
  54. package/dist/egress/__tests__/proxy.test.js.map +0 -1
  55. package/dist/index.test.d.ts +0 -28
  56. package/dist/index.test.d.ts.map +0 -1
  57. package/dist/index.test.js +0 -649
  58. package/dist/index.test.js.map +0 -1
  59. package/src/backends/aci-standby-pool/__tests__/unenforceable-controls.test.ts +0 -69
  60. package/src/backends/docker/__tests__/hardening.test.ts +0 -43
  61. package/src/backends/docker/__tests__/leaf-permissions.smoke.test.ts +0 -169
  62. package/src/backends/firecracker/__tests__/agent-timeout-clamp.test.ts +0 -48
  63. package/src/backends/firecracker/__tests__/backend.test.ts +0 -429
  64. package/src/backends/firecracker/__tests__/control-plane-mtls.test.ts +0 -261
  65. package/src/backends/firecracker/__tests__/egress-policy.test.ts +0 -91
  66. package/src/backends/firecracker/__tests__/fixtures/ipc-path.ts +0 -31
  67. package/src/backends/firecracker/__tests__/fixtures/mtls-pki.ts +0 -166
  68. package/src/backends/firecracker/__tests__/protocol.test.ts +0 -75
  69. package/src/backends/firecracker/__tests__/transport.test.ts +0 -534
  70. package/src/egress/__tests__/allowlist.test.ts +0 -103
  71. package/src/egress/__tests__/proxy.test.ts +0 -212
  72. package/src/index.test.ts +0 -709
@@ -1,457 +0,0 @@
1
- /**
2
- * Loopback transport round-trip tests for the Firecracker vsock path.
3
- *
4
- * These prove the NEW transport (host dialer ↔ in-VM agent) over a
5
- * **unix-socket stand-in** — the faithful local peer for AF_VSOCK,
6
- * because the production vsock path also terminates on a host
7
- * unix socket (see `transport.ts` docblock). The peer is the REAL
8
- * `agent/agent.cjs` connection handler (its spawn/jail + NDJSON shapes
9
- * verbatim), driven in-process over a temp unix socket; the client is
10
- * the REAL {@link VsockAgentTransport}. So one test exercises:
11
- * - exec → streamed stdout/stderr/result NDJSON, accumulated;
12
- * - writeFile / readFile → base64 round-trip through the jail;
13
- * - a simulated resume (server torn down + re-listened) survived by
14
- * the dialer's connect-retry budget — the FC #4713 invariant.
15
- *
16
- * No docker, no Azure, no AF_VSOCK kernel support required: pure
17
- * loopback, safe in CI.
18
- */
19
- import { mkdtempSync, rmSync } from 'node:fs';
20
- import { createServer, connect as netConnect } from 'node:net';
21
- import { tmpdir } from 'node:os';
22
- import { join } from 'node:path';
23
- import { createServer as createTlsServer } from 'node:tls';
24
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
25
- import { VsockAgentTransport } from '../transport.js';
26
- // The agent is a CommonJS module that reads NAMZU_SANDBOX_WORKSPACE at
27
- // require-time. Set the env, then require it through createRequire so
28
- // each test file gets a fresh module bound to its own workspace dir.
29
- import { createRequire } from 'node:module';
30
- import { localIpcPath } from './fixtures/ipc-path.js';
31
- // The loopback agent under test is the guest-side agent for a Linux microVM:
32
- // it spawns `/bin/sh` to run commands, and that binary does not exist on
33
- // Windows. These cases assert behavior the platform cannot produce, so they
34
- // skip there rather than leaving the suite permanently red for Windows
35
- // contributors. The socket-address fixture IS platform-correct, so the
36
- // transport is still exercised wherever it can be.
37
- const IS_WINDOWS = process.platform === 'win32';
38
- const require_ = createRequire(import.meta.url);
39
- let workDir;
40
- let sockPath;
41
- let server;
42
- let agent;
43
- function startAgentServer(connHandler) {
44
- return new Promise((resolve, reject) => {
45
- const s = createServer(connHandler);
46
- s.on('error', reject);
47
- s.listen(sockPath, () => resolve(s));
48
- });
49
- }
50
- beforeEach(() => {
51
- workDir = mkdtempSync(join(tmpdir(), 'fc-agent-test-'));
52
- sockPath = localIpcPath(workDir);
53
- // Bind the agent's workspace jail to the temp dir BEFORE requiring it.
54
- process.env.NAMZU_SANDBOX_WORKSPACE = workDir;
55
- // The agent's root-normalization filters env on PRESENCE; `= undefined`
56
- // sets the literal string "undefined" and would widen READ/WRITE_ROOTS, so
57
- // these must be true deletes.
58
- // biome-ignore lint/performance/noDelete: must remove the var, not set "undefined".
59
- delete process.env.NAMZU_SANDBOX_READ_ROOTS;
60
- // biome-ignore lint/performance/noDelete: must remove the var, not set "undefined".
61
- delete process.env.NAMZU_SANDBOX_WRITE_ROOTS;
62
- // Fresh module each test so WORKSPACE_ROOT is rebound.
63
- delete require_.cache[require_.resolve('../../../../agent/agent.cjs')];
64
- agent = require_('../../../../agent/agent.cjs');
65
- });
66
- afterEach(async () => {
67
- if (server) {
68
- await new Promise((r) => server?.close(() => r()));
69
- server = undefined;
70
- }
71
- rmSync(workDir, { recursive: true, force: true });
72
- });
73
- describe.skipIf(IS_WINDOWS)('VsockAgentTransport over a unix-socket loopback agent', () => {
74
- it('streams stdout/stderr/result NDJSON from an exec', async () => {
75
- server = await startAgentServer(agent.handleConnection);
76
- const transport = new VsockAgentTransport({ kind: 'unix', path: sockPath });
77
- const r = await transport.execute({
78
- command: '/bin/sh',
79
- args: ['-c', 'echo out-line; echo err-line 1>&2; exit 3'],
80
- });
81
- expect(r.stdout).toContain('out-line');
82
- expect(r.stderr).toContain('err-line');
83
- expect(r.exitCode).toBe(3);
84
- expect(r.timedOut).toBe(false);
85
- expect(r.durationMs).toBeGreaterThanOrEqual(0);
86
- });
87
- it('streams a large multi-chunk stdout intact (delta accumulation)', async () => {
88
- server = await startAgentServer(agent.handleConnection);
89
- const transport = new VsockAgentTransport({ kind: 'unix', path: sockPath });
90
- // 200 lines so the agent emits multiple stdout_delta frames the
91
- // FrameReader must reassemble across socket chunks.
92
- const r = await transport.execute({
93
- command: '/bin/sh',
94
- args: ['-c', 'for i in $(seq 1 200); do echo "line-$i"; done'],
95
- });
96
- expect(r.exitCode).toBe(0);
97
- const lines = r.stdout.trim().split('\n');
98
- expect(lines.length).toBe(200);
99
- expect(lines[0]).toBe('line-1');
100
- expect(lines[199]).toBe('line-200');
101
- });
102
- it('round-trips writeFile/readFile as base64 through the workspace jail', async () => {
103
- server = await startAgentServer(agent.handleConnection);
104
- const transport = new VsockAgentTransport({ kind: 'unix', path: sockPath });
105
- // Binary content (non-UTF8 bytes) proves base64 fidelity, not
106
- // just text.
107
- const payload = Buffer.from([0x00, 0xff, 0x10, 0x42, 0x00, 0x99, 0xfe]);
108
- await transport.writeFile('sub/dir/blob.bin', payload);
109
- const read = await transport.readFile('sub/dir/blob.bin');
110
- expect(read.equals(payload)).toBe(true);
111
- });
112
- it('rejects a path that escapes the workspace jail', async () => {
113
- server = await startAgentServer(agent.handleConnection);
114
- const transport = new VsockAgentTransport({ kind: 'unix', path: sockPath });
115
- await expect(transport.readFile('../../../../etc/passwd')).rejects.toThrow(/escapes/);
116
- });
117
- it('healthz returns true against a live agent', async () => {
118
- server = await startAgentServer(agent.handleConnection);
119
- const transport = new VsockAgentTransport({ kind: 'unix', path: sockPath });
120
- expect(await transport.healthz()).toBe(true);
121
- });
122
- it('surfaces an exec error event as a thrown error', async () => {
123
- server = await startAgentServer(agent.handleConnection);
124
- const transport = new VsockAgentTransport({ kind: 'unix', path: sockPath });
125
- // Empty command name → agent emits { type: 'error' }.
126
- await expect(transport.execute({ command: '' })).rejects.toThrow();
127
- });
128
- it('survives a simulated resume: server torn down then re-listened, dialer reconnects', async () => {
129
- // 1. Agent is up; one exec succeeds.
130
- server = await startAgentServer(agent.handleConnection);
131
- const transport = new VsockAgentTransport({ kind: 'unix', path: sockPath },
132
- // Tight retry budget so the test is fast but still proves retry.
133
- { connectRetryBudgetMs: 5_000, connectRetryIntervalMs: 50, connectTimeoutMs: 1_000 });
134
- const first = await transport.execute({ command: '/bin/sh', args: ['-c', 'echo before'] });
135
- expect(first.stdout).toContain('before');
136
- // 2. Simulate a resume: the FC vsock driver closes all connections
137
- // and the listener is gone until the agent re-LISTENs. Tear the
138
- // server down entirely.
139
- await new Promise((r) => server?.close(() => r()));
140
- server = undefined;
141
- // 3. Kick off an exec WHILE the agent is still down. The dialer's
142
- // connect-retry budget must hold (ECONNREFUSED) until the agent
143
- // re-listens — this is the FC #4713 / TRANSPORT_RESET-not-
144
- // delivered mitigation: the host re-dials rather than hanging.
145
- const pending = transport.execute({ command: '/bin/sh', args: ['-c', 'echo after'] });
146
- // 4. After a beat, the agent re-establishes its listen on the SAME
147
- // address (the resume re-listen invariant).
148
- await new Promise((r) => setTimeout(r, 300));
149
- server = await startAgentServer(agent.handleConnection);
150
- const after = await pending;
151
- expect(after.stdout).toContain('after');
152
- expect(after.exitCode).toBe(0);
153
- });
154
- it('connect-retry budget gives up with a clear error when the agent never returns', async () => {
155
- // No server started at all. The dialer should exhaust its budget
156
- // and throw a descriptive error rather than hang forever.
157
- const transport = new VsockAgentTransport({ kind: 'unix', path: sockPath }, { connectRetryBudgetMs: 400, connectRetryIntervalMs: 50, connectTimeoutMs: 200 });
158
- await expect(transport.healthz()).resolves.toBe(false);
159
- await expect(transport.readFile('x')).rejects.toThrow(/could not connect to agent/);
160
- });
161
- });
162
- // ---------------------------------------------------------------------------
163
- // Ring-0 mTLS arm — pure-local TLS loopback "relay" (no Azure, no FC host)
164
- // ---------------------------------------------------------------------------
165
- //
166
- // Proves the ADDITIVE `kind:'mtls'` transport arm without a real fleet:
167
- // - a `tls.createServer` plays the per-FC-host RELAY (requestCert +
168
- // rejectUnauthorized), reads the `SANDBOX <id>` routing preamble,
169
- // then bridges verbatim to the SAME `agent.handleConnection` peer
170
- // the vsock/unix arms use — so the IDENTICAL framing round-trips.
171
- // - the dialer presents the fleet CLIENT cert and verifies the relay
172
- // server cert; a WRONG-CA client is rejected at the TLS layer.
173
- // - the `SANDBOX <id>` preamble is the FIRST bytes after the
174
- // handshake (the relay's routing key), and the caller never writes
175
- // a guest `CONNECT 1024` line (the relay issues that host-side).
176
- //
177
- // The cert material is a throwaway P-256 test PKI (CA + server leaf +
178
- // client leaf + an unrelated rogue client) baked in as PEM constants —
179
- // no openssl/forge at test time, keeping the package dependency-light.
180
- // Test PKI. Minted offline with: openssl ec/x509 self-signed CA + leaves
181
- // (server SAN = DNS:sandbox.fc.internal, IP:127.0.0.1). Far-future expiry.
182
- // `ROGUE_*` chains to a DIFFERENT CA to prove rejectUnauthorized blocks it.
183
- const CA_CRT = `-----BEGIN CERTIFICATE-----
184
- MIIBjjCCATWgAwIBAgIUGXUtG14KQr4spNGW7rpfjZGoBIIwCgYIKoZIzj0EAwIw
185
- HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
186
- MjEyNjA1MjMwODMyNTJaMBwxGjAYBgNVBAMMEXZhbmRhbC1mYy10ZXN0LWNhMFkw
187
- EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5l+vjhjm/PX02D55n56EwelgvM1jrqQM
188
- Z+ezzvMmrZEBGWInvBND3z3kc6nv7snu6fHT2HHOyhwUNoLqmrIg/qNTMFEwHQYD
189
- VR0OBBYEFP0M8/KZY1ovxyGDci5iuoYXcmZgMB8GA1UdIwQYMBaAFP0M8/KZY1ov
190
- xyGDci5iuoYXcmZgMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIg
191
- C0xtFDASnwsOYT0GiZwzYWTOBfgmjDWK7ANXQQFNTh4CICVLQwq5eLy3424drEHk
192
- 5Ol/FNKVZcGRjE96rB0mRUOp
193
- -----END CERTIFICATE-----
194
- `;
195
- const SERVER_CRT = `-----BEGIN CERTIFICATE-----
196
- MIIBsDCCAVWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1MwCgYIKoZIzj0EAwIw
197
- HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
198
- MjEyNjA1MjMwODMyNTJaMBIxEDAOBgNVBAMMB2ZjLWhvc3QwWTATBgcqhkjOPQIB
199
- BggqhkjOPQMBBwNCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMBfmonVb7dUhM0ZWpo
200
- ePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6o30wezAkBgNVHREEHTAbghNz
201
- YW5kYm94LmZjLmludGVybmFshwR/AAABMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0G
202
- A1UdDgQWBBRXHU1vlX7WvqzcbaNxRxV4f3gfDDAfBgNVHSMEGDAWgBT9DPPymWNa
203
- L8chg3IuYrqGF3JmYDAKBggqhkjOPQQDAgNJADBGAiEAlqzKqgBf5hxJqd26QwcY
204
- n3cvEKi4f2BSLe1Rfzr5oSoCIQD0izUOJXLNvmac9cMgV0HvkftBerDKFOcGeGTN
205
- g3Eunw==
206
- -----END CERTIFICATE-----
207
- `;
208
- const SERVER_KEY = `-----BEGIN PRIVATE KEY-----
209
- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/ROnYXIkMKnipbLt
210
- JnFEwXAifgeOv9TGLcK2RojE7jmhRANCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMB
211
- fmonVb7dUhM0ZWpoePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6
212
- -----END PRIVATE KEY-----
213
- `;
214
- const CLIENT_CRT = `-----BEGIN CERTIFICATE-----
215
- MIIBjjCCATWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1QwCgYIKoZIzj0EAwIw
216
- HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
217
- MjEyNjA1MjMwODMyNTJaMBgxFjAUBgNVBAMMDWNhLXZhbmRhbC1hcHAwWTATBgcq
218
- hkjOPQIBBggqhkjOPQMBBwNCAASlCMCwjtrQUicWcWsO29R5S7fzjMbbxXvDh8/K
219
- w57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXko1cwVTATBgNVHSUE
220
- DDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQU2cxDCNrlVkk4ODs6ZPrkC6GzHjkwHwYD
221
- VR0jBBgwFoAU/Qzz8pljWi/HIYNyLmK6hhdyZmAwCgYIKoZIzj0EAwIDRwAwRAIg
222
- RghqArNm3bXnWnRi+jkEEJa8mRb2z0Wj4G7SIhtMurUCIBQSllVtICgZB9hvcM0D
223
- d24fcW4nlfvaZJMJ6dRC1Wle
224
- -----END CERTIFICATE-----
225
- `;
226
- const CLIENT_KEY = `-----BEGIN PRIVATE KEY-----
227
- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaamj/ycrEuPqpiC2
228
- IhAYx/M5iN4t4P+B17V4GO54Nb2hRANCAASlCMCwjtrQUicWcWsO29R5S7fzjMbb
229
- xXvDh8/Kw57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXk
230
- -----END PRIVATE KEY-----
231
- `;
232
- const ROGUE_CLIENT_CRT = `-----BEGIN CERTIFICATE-----
233
- MIIBhjCCASugAwIBAgIUbAYOlW4PQGyXjjRsjCPy62EHUmIwCgYIKoZIzj0EAwIw
234
- EzERMA8GA1UEAwwIcm9ndWUtY2EwIBcNMjYwNjE2MDgzMjUyWhgPMjEyNjA1MjMw
235
- ODMyNTJaMBcxFTATBgNVBAMMDHJvZ3VlLWNsaWVudDBZMBMGByqGSM49AgEGCCqG
236
- SM49AwEHA0IABOPSzdzQTQz3M5CDHLVPguvHd10ncaDV9t4zKUy/PCE+U7GTJwN2
237
- TtypGnmYEahbcl45j94hwu495P5VbR5ohb6jVzBVMBMGA1UdJQQMMAoGCCsGAQUF
238
- BwMCMB0GA1UdDgQWBBTf0woauniche3/ps77+Kd0dsbbSDAfBgNVHSMEGDAWgBSX
239
- Yu0IJlPxi79Gyi5hR1IfS/sqyzAKBggqhkjOPQQDAgNJADBGAiEAxD4N4XWtaHPJ
240
- yaCOzQP0e5RRyNst3QrhH0NSMyPw89wCIQC+bezLX97TuV1sId53Bo1l9j1TSOMa
241
- EZotN/Wsq6L+qw==
242
- -----END CERTIFICATE-----
243
- `;
244
- const ROGUE_CLIENT_KEY = `-----BEGIN PRIVATE KEY-----
245
- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR6fGq27O9eT/hi0Q
246
- c+L5+lSm5fbDEghVJCo6k7HrG62hRANCAATj0s3c0E0M9zOQgxy1T4Lrx3ddJ3Gg
247
- 1fbeMylMvzwhPlOxkycDdk7cqRp5mBGoW3JeOY/eIcLuPeT+VW0eaIW+
248
- -----END PRIVATE KEY-----
249
- `;
250
- /**
251
- * A loopback stand-in for the per-FC-host mTLS relay.
252
- *
253
- * Terminates mTLS (requestCert + rejectUnauthorized + CA pin), reads the
254
- * `SANDBOX <id>\n` routing preamble line, then bridges the rest of the
255
- * TLS stream verbatim to a FRESH `net.connect` to `agentSockPath` (the
256
- * unix-socket-backed real agent) — exactly the dumb byte-pump the
257
- * production relay is. It does NOT speak framing itself and does NOT
258
- * send an ack line (matching the transport's no-ack INTEGRATE contract).
259
- */
260
- function startMtlsRelay(agentSockPath, listenPort = 0) {
261
- let resolvePreamble;
262
- const preamble = new Promise((r) => {
263
- resolvePreamble = r;
264
- });
265
- return new Promise((resolve, reject) => {
266
- const server = createTlsServer({
267
- requestCert: true,
268
- rejectUnauthorized: true,
269
- ca: CA_CRT,
270
- cert: SERVER_CRT,
271
- key: SERVER_KEY,
272
- minVersion: 'TLSv1.3',
273
- }, (tlsSock) => {
274
- // Read exactly the `SANDBOX <id>\n` preamble line, then bridge.
275
- let pre = Buffer.alloc(0);
276
- const onPreambleData = (chunk) => {
277
- pre = Buffer.concat([pre, chunk]);
278
- const nl = pre.indexOf(0x0a);
279
- if (nl < 0)
280
- return;
281
- tlsSock.removeListener('data', onPreambleData);
282
- // Pause + unshift any post-preamble bytes so flowing-mode
283
- // data is not dropped between removing this listener and
284
- // attaching the pipe (the framed request can arrive in the
285
- // same OR a later chunk). `pipe` resumes the stream.
286
- tlsSock.pause();
287
- const line = pre.subarray(0, nl).toString('utf8');
288
- const rest = pre.subarray(nl + 1);
289
- if (rest.length > 0)
290
- tlsSock.unshift(rest);
291
- const m = /^SANDBOX (.+)$/.exec(line);
292
- const id = m?.[1];
293
- if (id === undefined) {
294
- tlsSock.destroy();
295
- return;
296
- }
297
- resolvePreamble(id);
298
- // 1 inbound mTLS conn -> 1 FRESH local agent connect (the
299
- // resume-survival invariant the relay must preserve).
300
- const upstream = netConnect({ path: agentSockPath });
301
- upstream.on('error', () => tlsSock.destroy());
302
- tlsSock.on('error', () => upstream.destroy());
303
- upstream.once('connect', () => {
304
- tlsSock.pipe(upstream);
305
- upstream.pipe(tlsSock);
306
- });
307
- };
308
- tlsSock.on('data', onPreambleData);
309
- });
310
- server.on('error', reject);
311
- server.listen(listenPort, '127.0.0.1', () => {
312
- const addr = server.address();
313
- if (addr === null || typeof addr === 'string') {
314
- reject(new Error('relay: no TCP port'));
315
- return;
316
- }
317
- resolve({ server, port: addr.port, preamble: () => preamble });
318
- });
319
- });
320
- }
321
- /** Re-listen the relay on a FIXED port (the host-bridge-restart case). */
322
- function startMtlsRelayOnPort(agentSockPath, port) {
323
- return startMtlsRelay(agentSockPath, port);
324
- }
325
- describe.skipIf(IS_WINDOWS)('VsockAgentTransport mtls arm over a TLS loopback relay', () => {
326
- let agentServer;
327
- let relay;
328
- afterEach(async () => {
329
- if (relay) {
330
- await new Promise((r) => relay?.server.close(() => r()));
331
- relay = undefined;
332
- }
333
- if (agentServer) {
334
- await new Promise((r) => agentServer?.close(() => r()));
335
- agentServer = undefined;
336
- }
337
- });
338
- function mtlsTransport(opts) {
339
- if (!relay)
340
- throw new Error('relay not started');
341
- return new VsockAgentTransport({
342
- kind: 'mtls',
343
- host: '127.0.0.1',
344
- port: relay.port,
345
- sandboxId: 'sbx-ring0-abc123',
346
- tls: {
347
- ca: CA_CRT,
348
- cert: CLIENT_CRT,
349
- key: CLIENT_KEY,
350
- servername: 'sandbox.fc.internal',
351
- },
352
- }, opts);
353
- }
354
- it('round-trips exec + write/read + healthz through the mTLS relay', async () => {
355
- agentServer = await startAgentServer(agent.handleConnection);
356
- relay = await startMtlsRelay(sockPath);
357
- const transport = mtlsTransport();
358
- const r = await transport.execute({
359
- command: '/bin/sh',
360
- args: ['-c', 'echo mtls-out; echo mtls-err 1>&2; exit 7'],
361
- });
362
- expect(r.stdout).toContain('mtls-out');
363
- expect(r.stderr).toContain('mtls-err');
364
- expect(r.exitCode).toBe(7);
365
- const payload = Buffer.from([0x00, 0xff, 0x10, 0x42, 0x00, 0x99, 0xfe]);
366
- await transport.writeFile('m/blob.bin', payload);
367
- const read = await transport.readFile('m/blob.bin');
368
- expect(read.equals(payload)).toBe(true);
369
- expect(await transport.healthz()).toBe(true);
370
- });
371
- it('sends `SANDBOX <id>` as the first bytes after the handshake (no CONNECT line)', async () => {
372
- agentServer = await startAgentServer(agent.handleConnection);
373
- relay = await startMtlsRelay(sockPath);
374
- const transport = mtlsTransport();
375
- // Any op drives a dial; the relay records the preamble line.
376
- expect(await transport.healthz()).toBe(true);
377
- // The caller's first line is the routing preamble, NOT `CONNECT 1024`
378
- // — the relay issues the guest CONNECT host-side.
379
- await expect(relay.preamble()).resolves.toBe('sbx-ring0-abc123');
380
- });
381
- it('rejects a client presenting a wrong-CA cert (rejectUnauthorized blocks it)', async () => {
382
- agentServer = await startAgentServer(agent.handleConnection);
383
- relay = await startMtlsRelay(sockPath);
384
- // Rogue client cert chains to a DIFFERENT CA than the relay trusts.
385
- const rogue = new VsockAgentTransport({
386
- kind: 'mtls',
387
- host: '127.0.0.1',
388
- port: relay.port,
389
- sandboxId: 'sbx-ring0-abc123',
390
- tls: {
391
- ca: CA_CRT,
392
- cert: ROGUE_CLIENT_CRT,
393
- key: ROGUE_CLIENT_KEY,
394
- servername: 'sandbox.fc.internal',
395
- },
396
- }, { connectRetryBudgetMs: 600, connectRetryIntervalMs: 50, connectTimeoutMs: 300 });
397
- // The relay's `rejectUnauthorized` drops the connection AFTER the
398
- // client handshake completes (the client trusts the server CA), so
399
- // the failure surfaces as a torn-down round-trip, not a TLS verify
400
- // error on the client side. Either way no agent traffic completes:
401
- // healthz swallows it into `false`; readFile rejects.
402
- expect(await rogue.healthz()).toBe(false);
403
- await expect(rogue.readFile('x')).rejects.toThrow();
404
- });
405
- it('rejects a server whose cert does not chain to the pinned CA (caller-side verify)', async () => {
406
- agentServer = await startAgentServer(agent.handleConnection);
407
- relay = await startMtlsRelay(sockPath);
408
- // The CALLER pins the ROGUE CA, so the relay's good-CA server cert
409
- // fails verification — proves the dialer's rejectUnauthorized works.
410
- const wrongCaCaller = new VsockAgentTransport({
411
- kind: 'mtls',
412
- host: '127.0.0.1',
413
- port: relay.port,
414
- sandboxId: 'sbx-ring0-abc123',
415
- tls: {
416
- ca: ROGUE_CLIENT_CRT, // not the issuing CA → server cert unverifiable
417
- cert: CLIENT_CRT,
418
- key: CLIENT_KEY,
419
- servername: 'sandbox.fc.internal',
420
- },
421
- }, { connectRetryBudgetMs: 600, connectRetryIntervalMs: 50, connectTimeoutMs: 300 });
422
- await expect(wrongCaCaller.readFile('x')).rejects.toThrow(/could not connect to agent/);
423
- });
424
- it('survives a simulated resume through the relay (relay torn down then re-listened on the same port)', async () => {
425
- agentServer = await startAgentServer(agent.handleConnection);
426
- relay = await startMtlsRelay(sockPath);
427
- const fixedPort = relay.port;
428
- const transport = new VsockAgentTransport({
429
- kind: 'mtls',
430
- host: '127.0.0.1',
431
- port: fixedPort,
432
- sandboxId: 'sbx-ring0-abc123',
433
- tls: {
434
- ca: CA_CRT,
435
- cert: CLIENT_CRT,
436
- key: CLIENT_KEY,
437
- servername: 'sandbox.fc.internal',
438
- },
439
- }, { connectRetryBudgetMs: 5_000, connectRetryIntervalMs: 50, connectTimeoutMs: 1_000 });
440
- const first = await transport.execute({ command: '/bin/sh', args: ['-c', 'echo before'] });
441
- expect(first.stdout).toContain('before');
442
- // Simulate the FC host bridge going away then coming back (the
443
- // network analogue of a vsock re-LISTEN): tear the relay down so the
444
- // caller's TLS connect gets ECONNREFUSED, and the per-request fresh
445
- // dial must ride the connect-retry budget until the relay is back.
446
- await new Promise((r) => relay?.server.close(() => r()));
447
- relay = undefined;
448
- const pending = transport.execute({ command: '/bin/sh', args: ['-c', 'echo after'] });
449
- await new Promise((r) => setTimeout(r, 300));
450
- // Re-listen the relay on the SAME port (the host bridge restarts).
451
- relay = await startMtlsRelayOnPort(sockPath, fixedPort);
452
- const after = await pending;
453
- expect(after.stdout).toContain('after');
454
- expect(after.exitCode).toBe(0);
455
- });
456
- });
457
- //# sourceMappingURL=transport.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transport.test.js","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/transport.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=allowlist.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"allowlist.test.d.ts","sourceRoot":"","sources":["../../../src/egress/__tests__/allowlist.test.ts"],"names":[],"mappings":""}
@@ -1,85 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { isHostAllowed, splitAuthority } from '../allowlist.js';
3
- /**
4
- * The part that decides whether untrusted code reaches the network.
5
- *
6
- * Substring matching is the obvious implementation and it is a hole: an
7
- * entry of `example.com` would admit `example.com.attacker.net`, a domain
8
- * the attacker owns. Plain suffix matching has the same hole without a
9
- * leading dot — `notexample.com` ends with `example.com`.
10
- */
11
- describe('an exact host entry', () => {
12
- it('matches only that host', () => {
13
- expect(isHostAllowed('api.example.com', ['api.example.com'])).toBe(true);
14
- expect(isHostAllowed('other.example.com', ['api.example.com'])).toBe(false);
15
- });
16
- it('does not match a host that merely contains it', () => {
17
- // The whole reason this is not `includes`.
18
- expect(isHostAllowed('api.example.com.attacker.net', ['api.example.com'])).toBe(false);
19
- });
20
- it('does not match a prefix of itself', () => {
21
- expect(isHostAllowed('example.com', ['api.example.com'])).toBe(false);
22
- });
23
- });
24
- describe('a wildcard entry', () => {
25
- it('matches subdomains', () => {
26
- expect(isHostAllowed('api.example.com', ['.example.com'])).toBe(true);
27
- expect(isHostAllowed('deep.api.example.com', ['.example.com'])).toBe(true);
28
- });
29
- it('matches the apex too', () => {
30
- // An author writing the wildcard form means the site; admitting
31
- // `www.example.com` but not `example.com` reads as a bug.
32
- expect(isHostAllowed('example.com', ['.example.com'])).toBe(true);
33
- });
34
- it('does not match a domain that merely ends with the same letters', () => {
35
- // This is why the leading dot is required rather than optional.
36
- expect(isHostAllowed('notexample.com', ['.example.com'])).toBe(false);
37
- expect(isHostAllowed('evilexample.com', ['.example.com'])).toBe(false);
38
- });
39
- it('does not match a domain that only contains it', () => {
40
- expect(isHostAllowed('example.com.attacker.net', ['.example.com'])).toBe(false);
41
- });
42
- });
43
- describe('normalisation', () => {
44
- it('ignores case, because DNS does', () => {
45
- expect(isHostAllowed('API.Example.COM', ['api.example.com'])).toBe(true);
46
- });
47
- it('ignores a trailing dot, which is the same name', () => {
48
- // An allowlist that treats `example.com.` as different is bypassable
49
- // by typing the host differently.
50
- expect(isHostAllowed('example.com.', ['example.com'])).toBe(true);
51
- });
52
- it('ignores surrounding whitespace in an entry', () => {
53
- expect(isHostAllowed('example.com', [' example.com '])).toBe(true);
54
- });
55
- });
56
- describe('an empty allowlist', () => {
57
- it('denies everything', () => {
58
- expect(isHostAllowed('example.com', [])).toBe(false);
59
- });
60
- it('is not satisfied by an empty entry', () => {
61
- // `''` must not become a wildcard through some string coincidence.
62
- expect(isHostAllowed('example.com', ['', ' '])).toBe(false);
63
- });
64
- it('denies an empty host', () => {
65
- expect(isHostAllowed('', ['example.com'])).toBe(false);
66
- });
67
- });
68
- describe('splitting an authority', () => {
69
- it('separates host from port', () => {
70
- expect(splitAuthority('example.com:8443')).toEqual({ host: 'example.com', port: 8443 });
71
- });
72
- it('leaves a bare host alone', () => {
73
- expect(splitAuthority('example.com')).toEqual({ host: 'example.com' });
74
- });
75
- it('handles a bracketed IPv6 literal', () => {
76
- // A `split(':')` would shred this, and the allowlist would then be
77
- // matching against a fragment.
78
- expect(splitAuthority('[::1]:9000')).toEqual({ host: '::1', port: 9000 });
79
- expect(splitAuthority('[2001:db8::1]')).toEqual({ host: '2001:db8::1' });
80
- });
81
- it('keeps the whole value when the port is not a number', () => {
82
- expect(splitAuthority('example.com:notaport')).toEqual({ host: 'example.com:notaport' });
83
- });
84
- });
85
- //# sourceMappingURL=allowlist.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"allowlist.test.js","sourceRoot":"","sources":["../../../src/egress/__tests__/allowlist.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=proxy.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"proxy.test.d.ts","sourceRoot":"","sources":["../../../src/egress/__tests__/proxy.test.ts"],"names":[],"mappings":""}