@namzu/sandbox 2.0.3 → 3.0.0

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/dist/index.js CHANGED
@@ -139,6 +139,7 @@ function pickBackend(config) {
139
139
  ? { hostReachability: backend.hostReachability }
140
140
  : {}),
141
141
  ...(backend.network !== undefined ? { network: backend.network } : {}),
142
+ ...(backend.allowInwardFor !== undefined ? { allowInwardFor: backend.allowInwardFor } : {}),
142
143
  ...(backend.labels !== undefined ? { labels: backend.labels } : {}),
143
144
  });
144
145
  }
@@ -187,6 +188,7 @@ function pickBackend(config) {
187
188
  ? { hostReachability: backend.hostReachability }
188
189
  : {}),
189
190
  ...(backend.network !== undefined ? { network: backend.network } : {}),
191
+ ...(backend.allowInwardFor !== undefined ? { allowInwardFor: backend.allowInwardFor } : {}),
190
192
  ...(backend.labels !== undefined ? { labels: backend.labels } : {}),
191
193
  });
192
194
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/sandbox",
3
- "version": "2.0.3",
3
+ "version": "3.0.0",
4
4
  "description": "Pluggable sandbox provider for @namzu/sdk. Process-level isolation (bubblewrap on Linux, Seatbelt on macOS, via @anthropic-ai/sandbox-runtime) for developer dev loops; container-level isolation (HTTP worker + JWT-authenticated egress proxy) for multi-tenant production. Backend selected at construction time; the SDK consumes both through the same SandboxProvider interface.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "type": "module",
@@ -50,7 +50,7 @@
50
50
  "@types/node": "^22.19.17",
51
51
  "typescript": "^5.5.0",
52
52
  "vitest": "^3.2.6",
53
- "@namzu/sdk": "^15.0.0"
53
+ "@namzu/sdk": "^25.0.0"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "tsc --build",
@@ -43,7 +43,11 @@ import {
43
43
  withHint,
44
44
  } from '@namzu/sdk'
45
45
  import { EgressProxy } from '../../egress/index.js'
46
- import type { BrokeredCredential, RunningEgressProxy } from '../../egress/index.js'
46
+ import type {
47
+ BrokeredCredential,
48
+ EgressProxyOptions,
49
+ RunningEgressProxy,
50
+ } from '../../egress/index.js'
47
51
 
48
52
  import {
49
53
  ContainerSandboxLayoutValidationError,
@@ -97,6 +101,22 @@ export interface DockerBackendInternalConfig {
97
101
  */
98
102
  readonly brokeredCredentials?: readonly BrokeredCredential[]
99
103
 
104
+ /**
105
+ * Allowlisted hosts permitted to resolve to an inward address anyway.
106
+ *
107
+ * The egress boundary refuses a host that resolves to loopback, a private
108
+ * range or the link-local metadata block, whatever the allowlist says —
109
+ * because an allowlisted name whose DNS someone else controls is not a
110
+ * permitted destination, it is a permitted spelling. An operator who
111
+ * genuinely proxies to one service on a private network names it here.
112
+ *
113
+ * Per host, matched by the allowlist's own rules so `.internal.example`
114
+ * covers subdomains. There is deliberately no switch that turns the screen
115
+ * off: one would hand every other allowlisted name the same reach, which
116
+ * is the hole the screen exists to close.
117
+ */
118
+ readonly allowInwardFor?: readonly string[]
119
+
100
120
  readonly network?: 'none' | 'bridge' | string
101
121
  readonly readyPollIntervalMs?: number
102
122
  readonly readyTimeoutMs?: number
@@ -217,6 +237,29 @@ export function needsEgressProxy(egress: EgressPolicy | undefined): boolean {
217
237
  return egress?.kind === 'static' || egress?.kind === 'resolver'
218
238
  }
219
239
 
240
+ /**
241
+ * The options the boundary is built from, as a value.
242
+ *
243
+ * Extracted for the same reason {@link resolveNetwork} is: everything
244
+ * downstream of here needs a running Docker daemon, so a policy that never
245
+ * reached the proxy could only be caught by an operator noticing their
246
+ * traffic denied in production. A knob a host sets and the boundary never
247
+ * receives is the failure this shape exists to make testable.
248
+ */
249
+ export function egressProxyOptions(
250
+ config: Pick<DockerBackendInternalConfig, 'brokeredCredentials' | 'allowInwardFor'>,
251
+ policy: EgressPolicy,
252
+ ): EgressProxyOptions {
253
+ return {
254
+ // Re-resolved per request rather than captured once, so a `resolver`
255
+ // policy that rotates is honoured and `setNetworkPolicy` can swap it
256
+ // on a live sandbox.
257
+ allowedHosts: () => resolveAllowedHosts(policy),
258
+ credentials: config.brokeredCredentials ?? [],
259
+ ...(config.allowInwardFor ? { allowInwardFor: config.allowInwardFor } : {}),
260
+ }
261
+ }
262
+
220
263
  /**
221
264
  * Confinement flags applied to every container.
222
265
  *
@@ -251,13 +294,7 @@ async function spawnDockerSandbox(
251
294
  let egressProxy: RunningEgressProxy | undefined
252
295
  if (needsEgressProxy(options.egress) && options.egress) {
253
296
  const policy = options.egress
254
- egressProxy = await new EgressProxy({
255
- // Re-resolved per request rather than captured once, so a
256
- // `resolver` policy that rotates is honoured and
257
- // `setNetworkPolicy` can swap it on a live sandbox.
258
- allowedHosts: () => resolveAllowedHosts(policy),
259
- credentials: config.brokeredCredentials ?? [],
260
- }).listen()
297
+ egressProxy = await new EgressProxy(egressProxyOptions(config, policy)).listen()
261
298
  }
262
299
 
263
300
  const network = resolveNetwork(
@@ -0,0 +1,366 @@
1
+ import { lookup as dnsLookup } from 'node:dns'
2
+ import type { LookupAddress } from 'node:dns'
3
+ import { isIP } from 'node:net'
4
+
5
+ /**
6
+ * Address-level screening for egress.
7
+ *
8
+ * The allowlist answers "is this NAME permitted". That is a different
9
+ * question from "where does this name go", and only the second one decides
10
+ * what the socket actually reaches. A name on the allowlist whose DNS the
11
+ * attacker controls — or that simply has an inward-pointing record — resolves
12
+ * to the loopback interface, the private network the sandbox host sits on, or
13
+ * the link-local address cloud metadata services answer on.
14
+ *
15
+ * The proxy stamps a brokered credential on before the request goes out, so
16
+ * without this screen the credential-brokering design is the delivery
17
+ * mechanism: the token reaches whatever the name resolved to. That is the
18
+ * exact outcome `BrokeredCredential.host` exists to prevent, and it could not
19
+ * prevent it while the scope was a name rather than an address.
20
+ */
21
+
22
+ /** Blocked ranges, and the name of what each one protects. */
23
+ interface Range {
24
+ readonly reason: string
25
+ readonly matches: (octets: readonly number[]) => boolean
26
+ }
27
+
28
+ const V4_RANGES: readonly Range[] = [
29
+ { reason: 'loopback', matches: (o) => o[0] === 127 },
30
+ { reason: 'this-host', matches: (o) => o[0] === 0 },
31
+ { reason: 'private', matches: (o) => o[0] === 10 },
32
+ { reason: 'private', matches: (o) => o[0] === 172 && (o[1] ?? 0) >= 16 && (o[1] ?? 0) <= 31 },
33
+ { reason: 'private', matches: (o) => o[0] === 192 && o[1] === 168 },
34
+ // 169.254.0.0/16. The metadata address every major host platform answers
35
+ // on lives here, which is why this range is the one that turns a name
36
+ // check into a credential leak.
37
+ { reason: 'link-local', matches: (o) => o[0] === 169 && o[1] === 254 },
38
+ {
39
+ reason: 'shared-address-space',
40
+ matches: (o) => o[0] === 100 && (o[1] ?? 0) >= 64 && (o[1] ?? 0) <= 127,
41
+ },
42
+ { reason: 'benchmarking', matches: (o) => o[0] === 198 && (o[1] === 18 || o[1] === 19) },
43
+ { reason: 'multicast', matches: (o) => (o[0] ?? 0) >= 224 && (o[0] ?? 0) <= 239 },
44
+ { reason: 'reserved', matches: (o) => (o[0] ?? 0) >= 240 },
45
+ ]
46
+
47
+ function parseV4(address: string): readonly number[] | null {
48
+ const parts = address.split('.')
49
+ if (parts.length !== 4) return null
50
+ const octets: number[] = []
51
+ for (const part of parts) {
52
+ if (!/^\d{1,3}$/.test(part)) return null
53
+ const n = Number(part)
54
+ if (n > 255) return null
55
+ octets.push(n)
56
+ }
57
+ return octets
58
+ }
59
+
60
+ /**
61
+ * Expand an IPv6 literal into its eight 16-bit groups, or `null`.
62
+ *
63
+ * Written out rather than pattern-matched on the text, because a prefix
64
+ * matched as a STRING is a different question from a prefix matched as a
65
+ * NUMBER, and the two disagree exactly where it hurts. `/^f[cd]/` was the
66
+ * first spelling of the unique-local check here, and `fd::1` matches it —
67
+ * but `fd::1` is `00fd:0:…`, an ordinary global address, so that check
68
+ * deleted a slice of the internet. `fe8::1` did the same against
69
+ * `/^fe[89ab]/`. Both are the `>=`-where-`>`-was-meant mistake wearing a
70
+ * regex.
71
+ *
72
+ * It fails the other way too. `0:0:0:0:0:ffff:169.254.169.254` is the
73
+ * metadata address written long, and no `^::`-anchored pattern sees it.
74
+ */
75
+ function parseV6(address: string): number[] | null {
76
+ // A zone id (`%eth0`) names an interface, not a different address.
77
+ const text = (address.toLowerCase().split('%')[0] ?? '').trim()
78
+ if (text.length === 0) return null
79
+
80
+ // A trailing dotted quad is the last two groups written in v4 notation.
81
+ let head = text
82
+ let tail: number[] = []
83
+ const lastColon = text.lastIndexOf(':')
84
+ const after = lastColon >= 0 ? text.slice(lastColon + 1) : ''
85
+ if (after.includes('.')) {
86
+ const quad = parseV4(after)
87
+ if (!quad) return null
88
+ const [a, b, c, d] = quad as [number, number, number, number]
89
+ tail = [(a << 8) | b, (c << 8) | d]
90
+ head = text.slice(0, lastColon + 1)
91
+ if (head.endsWith(':') && !head.endsWith('::')) head = head.slice(0, -1)
92
+ }
93
+
94
+ const halves = head.split('::')
95
+ if (halves.length > 2) return null
96
+
97
+ const toGroups = (part: string): number[] | null => {
98
+ if (part.length === 0) return []
99
+ const out: number[] = []
100
+ for (const piece of part.split(':')) {
101
+ if (!/^[0-9a-f]{1,4}$/.test(piece)) return null
102
+ out.push(Number.parseInt(piece, 16))
103
+ }
104
+ return out
105
+ }
106
+
107
+ if (halves.length === 1) {
108
+ const only = toGroups(halves[0] ?? '')
109
+ if (!only) return null
110
+ const groups = [...only, ...tail]
111
+ return groups.length === 8 ? groups : null
112
+ }
113
+
114
+ const left = toGroups(halves[0] ?? '')
115
+ const right = toGroups(halves[1] ?? '')
116
+ if (!left || !right) return null
117
+ const known = left.length + right.length + tail.length
118
+ if (known > 8) return null
119
+ return [...left, ...new Array<number>(8 - known).fill(0), ...right, ...tail]
120
+ }
121
+
122
+ /** Whether the first `count` groups are all zero. */
123
+ function zeroPrefix(groups: readonly number[], count: number): boolean {
124
+ return groups.slice(0, count).every((g) => g === 0)
125
+ }
126
+
127
+ /**
128
+ * Why this address must not be reached, or `null` if it may be.
129
+ *
130
+ * Returns a reason rather than a boolean because the reason is what a
131
+ * denied operator needs: "link-local" and "private" are different mistakes
132
+ * with different fixes, and a bare `false` sends them to read this file.
133
+ */
134
+ export function blockedAddressReason(address: string): string | null {
135
+ const literal = unbracket(address)
136
+ const v4 = parseV4(literal)
137
+ if (v4) {
138
+ for (const range of V4_RANGES) {
139
+ if (range.matches(v4)) return range.reason
140
+ }
141
+ return null
142
+ }
143
+
144
+ const groups = parseV6(literal)
145
+ if (!groups) return null
146
+
147
+ // `::ffff:a.b.c.d` (v4-mapped) and the deprecated `::a.b.c.d`
148
+ // (v4-compatible) are both the v4 address wearing a v6 spelling, and both
149
+ // reach the v4 host. A screen that only understands dotted quads passes
150
+ // them, which is a documented way through this kind of filter rather than
151
+ // an oversight worth ignoring.
152
+ if (zeroPrefix(groups, 5) && groups[5] === 0xffff) {
153
+ return blockedAddressReason(v4FromGroups(groups))
154
+ }
155
+ if (zeroPrefix(groups, 6) && !(groups[6] === 0 && (groups[7] ?? 0) <= 1)) {
156
+ return blockedAddressReason(v4FromGroups(groups))
157
+ }
158
+
159
+ if (zeroPrefix(groups, 7)) {
160
+ if (groups[7] === 1) return 'loopback'
161
+ if (groups[7] === 0) return 'unspecified'
162
+ }
163
+
164
+ const first = groups[0] ?? 0
165
+ // Masked, not prefix-matched: fc00::/7, fe80::/10, ff00::/8.
166
+ if ((first & 0xfe00) === 0xfc00) return 'unique-local'
167
+ if ((first & 0xffc0) === 0xfe80) return 'link-local'
168
+ if ((first & 0xff00) === 0xff00) return 'multicast'
169
+ return null
170
+ }
171
+
172
+ function v4FromGroups(groups: readonly number[]): string {
173
+ const high = groups[6] ?? 0
174
+ const low = groups[7] ?? 0
175
+ return `${high >> 8}.${high & 0xff}.${low >> 8}.${low & 0xff}`
176
+ }
177
+
178
+ /**
179
+ * An IPv6 literal arrives bracketed from one of the two paths.
180
+ *
181
+ * `new URL('http://[::1]/').hostname` is `[::1]`, brackets included, and
182
+ * `parseTarget` reads exactly that. The `Host`-header path hands the same
183
+ * address over bare, because `splitAuthority` strips the brackets itself —
184
+ * two spellings of one address, normalised here rather than at either call
185
+ * site.
186
+ *
187
+ * This is a layer, not a hole closed, and the difference was measured rather
188
+ * than assumed: Node does not read a bracketed string as an IP literal
189
+ * either, so without this the host falls through to `dns.lookup` and the
190
+ * screening resolver refuses it there. What this buys is that
191
+ * `blockedLiteralReason` stops answering `null` about an address it plainly
192
+ * recognises — a true-looking answer the next caller would build on.
193
+ */
194
+ function unbracket(host: string): string {
195
+ const trimmed = host.trim()
196
+ return trimmed.startsWith('[') && trimmed.endsWith(']') ? trimmed.slice(1, -1) : trimmed
197
+ }
198
+
199
+ /**
200
+ * Screen a target that is already an address rather than a name.
201
+ *
202
+ * A `lookup` hook cannot cover this case and it is not obvious why: the
203
+ * socket layer skips resolution entirely when the host is a valid IP
204
+ * literal, so the screening resolver is never called. The whole existing
205
+ * egress suite passed with the resolver in place *because* its upstream is
206
+ * `127.0.0.1` — a literal, never resolved, never screened. A green suite
207
+ * was the evidence the hole was still open.
208
+ *
209
+ * So the two cases need two checks: names are screened inside the resolver
210
+ * the socket calls, literals are screened here before it dials.
211
+ */
212
+ export function blockedLiteralReason(host: string): string | null {
213
+ // The `isIP` guard states the contract: only an address is screened here.
214
+ //
215
+ // It is defence in depth rather than the thing that saves a hostname, and
216
+ // that was measured — removing it kills no test, because `parseV6` refuses
217
+ // `fdsomething.example` and `ff-cdn.example` on its own. It earns its place
218
+ // against the version of this file that does not: the first screen written
219
+ // here matched `/^f[cd]/` against the raw text, and under that screen this
220
+ // line was the only thing standing between an ordinary CDN hostname and a
221
+ // refusal. Keeping it means a future loosening of the parser cannot quietly
222
+ // turn an address screen back into a name filter.
223
+ if (isIP(unbracket(host)) === 0) return null
224
+ return blockedAddressReason(host)
225
+ }
226
+
227
+ export class EgressAddressDenied extends Error {
228
+ readonly host: string
229
+ readonly address: string
230
+ readonly reason: string
231
+
232
+ constructor(host: string, address: string, reason: string) {
233
+ super(
234
+ `Egress denied: ${host} resolves to ${address}, which is a ${reason} address. The host is on the allowlist; the address it resolves to is not reachable from a sandbox.`,
235
+ )
236
+ this.name = 'EgressAddressDenied'
237
+ this.host = host
238
+ this.address = address
239
+ this.reason = reason
240
+ }
241
+ }
242
+
243
+ export interface ScreeningLookupOptions {
244
+ /**
245
+ * Hosts permitted to resolve inward anyway, matched by the allowlist's
246
+ * own rules so `.internal.example` covers subdomains.
247
+ *
248
+ * Per host, never a global switch. An operator who genuinely proxies to
249
+ * one service on a private network needs that service exempted, and
250
+ * turning the screen off entirely to get it would hand every other
251
+ * allowlisted name the same reach.
252
+ */
253
+ readonly allowInwardFor?: readonly string[]
254
+ /** Injected in tests. Defaults to the platform resolver. */
255
+ readonly resolve?: AddressResolver
256
+ }
257
+
258
+ /**
259
+ * The one shape this module asks a resolver for: every address, in the
260
+ * order the resolver returned them.
261
+ *
262
+ * Narrower than the platform signature on purpose. The screen has to see
263
+ * ALL the addresses to be worth anything, so a resolver that can be asked
264
+ * for one is a resolver this code could accidentally ask wrongly.
265
+ */
266
+ export type AddressResolver = (
267
+ hostname: string,
268
+ options: { readonly all: true; readonly verbatim: true },
269
+ callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void,
270
+ ) => void
271
+
272
+ const platformResolver: AddressResolver = (hostname, options, callback) => {
273
+ dnsLookup(hostname, options, callback)
274
+ }
275
+
276
+ type LookupCallback = (
277
+ err: NodeJS.ErrnoException | null,
278
+ address: string | LookupAddress[],
279
+ family?: number,
280
+ ) => void
281
+
282
+ /**
283
+ * A `lookup` implementation that screens before the socket uses the answer.
284
+ *
285
+ * This is deliberately not "resolve, check, then connect to the address we
286
+ * checked". That shape leaves the socket free to resolve again, and the
287
+ * second answer is the one that decides where the bytes go — so a name that
288
+ * alternates records walks straight through a check that passed a moment
289
+ * earlier. Screening inside the resolver the socket itself calls means there
290
+ * is one resolution, and the address that was screened is the address that
291
+ * gets connected to.
292
+ *
293
+ * Every returned address is screened, not just the one chosen. A record set
294
+ * mixing a public address with an inward one is the ordinary shape of this
295
+ * attack, and screening only the winner makes the outcome depend on which
296
+ * record the resolver happened to order first.
297
+ */
298
+ export function createScreeningLookup(
299
+ options: ScreeningLookupOptions = {},
300
+ isExempt: (host: string, patterns: readonly string[]) => boolean = () => false,
301
+ ): (hostname: string, opts: unknown, callback: LookupCallback) => void {
302
+ const resolver = options.resolve ?? platformResolver
303
+ const exemptions = options.allowInwardFor ?? []
304
+
305
+ return (hostname, opts, callback) => {
306
+ const wantsAll =
307
+ typeof opts === 'object' && opts !== null && (opts as { all?: boolean }).all === true
308
+ const family =
309
+ typeof opts === 'number'
310
+ ? opts
311
+ : typeof opts === 'object' && opts !== null
312
+ ? ((opts as { family?: number }).family ?? 0)
313
+ : 0
314
+
315
+ resolver(hostname, { all: true, verbatim: true }, (err, addresses) => {
316
+ if (err) {
317
+ callback(err, '', 0)
318
+ return
319
+ }
320
+ const found = addresses ?? []
321
+ if (found.length === 0) {
322
+ const empty: NodeJS.ErrnoException = new Error(
323
+ `Egress denied: ${hostname} resolved to no addresses.`,
324
+ )
325
+ empty.code = 'ENOTFOUND'
326
+ callback(empty, '', 0)
327
+ return
328
+ }
329
+
330
+ if (!(exemptions.length > 0 && isExempt(hostname, exemptions))) {
331
+ for (const candidate of found) {
332
+ const reason = blockedAddressReason(candidate.address)
333
+ if (reason) {
334
+ callback(new EgressAddressDenied(hostname, candidate.address, reason), '', 0)
335
+ return
336
+ }
337
+ }
338
+ }
339
+
340
+ const usable = family === 0 ? found : found.filter((a) => a.family === family)
341
+ if (usable.length === 0) {
342
+ const mismatch: NodeJS.ErrnoException = new Error(
343
+ `Egress denied: ${hostname} has no address in the requested family.`,
344
+ )
345
+ mismatch.code = 'ENOTFOUND'
346
+ callback(mismatch, '', 0)
347
+ return
348
+ }
349
+
350
+ if (wantsAll) {
351
+ callback(null, usable)
352
+ return
353
+ }
354
+ const first = usable[0]
355
+ if (!first) {
356
+ const none: NodeJS.ErrnoException = new Error(
357
+ `Egress denied: ${hostname} resolved to no usable address.`,
358
+ )
359
+ none.code = 'ENOTFOUND'
360
+ callback(none, '', 0)
361
+ return
362
+ }
363
+ callback(null, first.address, first.family)
364
+ })
365
+ }
366
+ }
@@ -1,3 +1,10 @@
1
+ export {
2
+ blockedAddressReason,
3
+ blockedLiteralReason,
4
+ createScreeningLookup,
5
+ EgressAddressDenied,
6
+ } from './address.js'
7
+ export type { AddressResolver, ScreeningLookupOptions } from './address.js'
1
8
  export { isHostAllowed, splitAuthority } from './allowlist.js'
2
9
  export { EgressProxy } from './proxy.js'
3
10
  export type {