@hachej/boring-sandbox 0.1.83 → 0.1.85

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.
@@ -1,4 +1,6 @@
1
1
  import { z } from 'zod';
2
+ import { d as RuntimeIsolationEvidenceV1, b as RuntimeIsolationDigest, e as RuntimeIsolationEvidenceVerification } from '../../runtimeIsolation-Bn8t1ADl.js';
3
+ export { R as RUNTIME_ISOLATION_ERROR_CODES, a as RUNTIME_ISOLATION_PROBE_IDS, c as RuntimeIsolationErrorCode, f as RuntimeIsolationProbeId, g as RuntimeIsolationProfileV1 } from '../../runtimeIsolation-Bn8t1ADl.js';
2
4
 
3
5
  declare const RunscPreflightConfigSchema: z.ZodEffects<z.ZodObject<{
4
6
  stateRoot: z.ZodEffects<z.ZodString, string, string>;
@@ -213,4 +215,13 @@ interface RunscHostCommandRunner {
213
215
  }
214
216
  declare function preflightRunsc(input: unknown, runner: RunscHostCommandRunner): Promise<RunscPreflightResult>;
215
217
 
216
- export { RUNSC_PREFLIGHT_ERROR_CODES, RUNSC_REQUIRED_BLOCKED_CIDRS, RUNSC_UNPROVEN_SECURITY_FACTS, type RunscHostCommand, type RunscHostCommandResult, type RunscHostCommandRunner, type RunscPreflightConfig, RunscPreflightError, type RunscPreflightErrorCode, type RunscPreflightErrorRecord, type RunscPreflightResult, type RunscStructuralObservations, type RunscUnprovenSecurityFacts, preflightRunsc, validateRunscPreflightConfig };
218
+ declare function digestRuntimeIsolationValue(value: unknown): RuntimeIsolationDigest;
219
+ declare function createRuntimeIsolationEvidence(input: {
220
+ profile: unknown;
221
+ testSuiteDigest: unknown;
222
+ probes: unknown;
223
+ positiveControls: unknown;
224
+ }): RuntimeIsolationEvidenceV1;
225
+ declare function verifyRuntimeIsolationEvidence(value: unknown, observedProfile: unknown, observedTestSuiteDigest: unknown): RuntimeIsolationEvidenceVerification;
226
+
227
+ export { RUNSC_PREFLIGHT_ERROR_CODES, RUNSC_REQUIRED_BLOCKED_CIDRS, RUNSC_UNPROVEN_SECURITY_FACTS, type RunscHostCommand, type RunscHostCommandResult, type RunscHostCommandRunner, type RunscPreflightConfig, RunscPreflightError, type RunscPreflightErrorCode, type RunscPreflightErrorRecord, type RunscPreflightResult, type RunscStructuralObservations, type RunscUnprovenSecurityFacts, RuntimeIsolationDigest, RuntimeIsolationEvidenceV1, RuntimeIsolationEvidenceVerification, createRuntimeIsolationEvidence, digestRuntimeIsolationValue, preflightRunsc, validateRunscPreflightConfig, verifyRuntimeIsolationEvidence };
@@ -270,11 +270,206 @@ function normalizeError(error) {
270
270
  if (error instanceof RunscPreflightError) return error;
271
271
  return new RunscPreflightError(RUNSC_PREFLIGHT_ERROR_CODES.commandFailed, "runsc preflight failed");
272
272
  }
273
+
274
+ // src/shared/runtimeIsolation.ts
275
+ var RUNTIME_ISOLATION_PROBE_IDS = [
276
+ "sibling-filesystem-traversal",
277
+ "proc-pid-enumeration",
278
+ "cross-sandbox-signal",
279
+ "cross-sandbox-ptrace",
280
+ "mount-access",
281
+ "device-access",
282
+ "process-escape",
283
+ "cross-workspace-network",
284
+ "secret-access",
285
+ "resource-ceilings",
286
+ "teardown"
287
+ ];
288
+ var RUNTIME_ISOLATION_ERROR_CODES = {
289
+ invalidInput: "RUNSC_ISOLATION_INVALID_INPUT",
290
+ probeFailed: "RUNSC_ISOLATION_PROBE_FAILED",
291
+ evidenceInvalid: "RUNSC_ISOLATION_EVIDENCE_INVALID",
292
+ profileDrift: "RUNSC_ISOLATION_PROFILE_DRIFT"
293
+ };
294
+
295
+ // src/providers/runsc/isolationEvidence.ts
296
+ import { createHash } from "crypto";
297
+ var DIGEST = /^sha256:[a-f0-9]{64}$/;
298
+ var SAFE_FACT = /^[a-zA-Z0-9][a-zA-Z0-9._+ -]{0,127}$/;
299
+ var PROFILE_KEYS = [
300
+ "schemaVersion",
301
+ "provider",
302
+ "kernelRelease",
303
+ "runtimeVersion",
304
+ "runtimeBinaryDigest",
305
+ "rootfsBinaryDigest",
306
+ "platformMode",
307
+ "privilegeModel",
308
+ "containerCapabilities",
309
+ "workloadIdentity",
310
+ "networkPolicy",
311
+ "cgroupPolicy",
312
+ "providerConfigDigest",
313
+ "hostPolicyDigest"
314
+ ];
315
+ function digestRuntimeIsolationValue(value) {
316
+ return `sha256:${createHash("sha256").update(canonicalJson(value)).digest("hex")}`;
317
+ }
318
+ function createRuntimeIsolationEvidence(input) {
319
+ const profile = parseProfile(input.profile);
320
+ const testSuiteDigest = parseDigest(input.testSuiteDigest);
321
+ const probes = parseProbes(input.probes);
322
+ const positiveControls = parsePositiveControls(input.positiveControls);
323
+ const withoutDigest = {
324
+ schemaVersion: 1,
325
+ domain: "boring-runtime-isolation-evidence:v1",
326
+ profile,
327
+ profileDigest: digestRuntimeIsolationValue(profile),
328
+ testSuiteDigest,
329
+ probes,
330
+ positiveControls,
331
+ redaction: {
332
+ containsHostPaths: false,
333
+ containsSecrets: false,
334
+ containsHostPids: false
335
+ }
336
+ };
337
+ return deepFreeze({ ...withoutDigest, evidenceDigest: digestRuntimeIsolationValue(withoutDigest) });
338
+ }
339
+ function verifyRuntimeIsolationEvidence(value, observedProfile, observedTestSuiteDigest) {
340
+ let evidence;
341
+ try {
342
+ evidence = parseEvidence(value);
343
+ } catch {
344
+ return rejected(RUNTIME_ISOLATION_ERROR_CODES.evidenceInvalid, "runtime isolation evidence is invalid");
345
+ }
346
+ try {
347
+ const profile = parseProfile(observedProfile);
348
+ const suiteDigest = parseDigest(observedTestSuiteDigest);
349
+ if (evidence.testSuiteDigest !== suiteDigest || evidence.profileDigest !== digestRuntimeIsolationValue(profile)) {
350
+ return rejected(RUNTIME_ISOLATION_ERROR_CODES.profileDrift, "runtime isolation qualification drifted");
351
+ }
352
+ if (canonicalJson(evidence.profile) !== canonicalJson(profile)) {
353
+ return rejected(RUNTIME_ISOLATION_ERROR_CODES.profileDrift, "runtime isolation qualification drifted");
354
+ }
355
+ const { evidenceDigest, ...withoutDigest } = evidence;
356
+ if (evidenceDigest !== digestRuntimeIsolationValue(withoutDigest)) {
357
+ return rejected(RUNTIME_ISOLATION_ERROR_CODES.evidenceInvalid, "runtime isolation evidence digest is invalid");
358
+ }
359
+ return { status: "accepted", evidenceDigest };
360
+ } catch {
361
+ return rejected(RUNTIME_ISOLATION_ERROR_CODES.profileDrift, "runtime isolation qualification drifted");
362
+ }
363
+ }
364
+ function parseEvidence(value) {
365
+ const record = strictRecord(value, [
366
+ "schemaVersion",
367
+ "domain",
368
+ "profile",
369
+ "profileDigest",
370
+ "testSuiteDigest",
371
+ "probes",
372
+ "positiveControls",
373
+ "redaction",
374
+ "evidenceDigest"
375
+ ]);
376
+ if (record.schemaVersion !== 1 || record.domain !== "boring-runtime-isolation-evidence:v1") invalid2();
377
+ const redaction = strictRecord(record.redaction, ["containsHostPaths", "containsSecrets", "containsHostPids"]);
378
+ if (redaction.containsHostPaths !== false || redaction.containsSecrets !== false || redaction.containsHostPids !== false) invalid2();
379
+ return {
380
+ schemaVersion: 1,
381
+ domain: "boring-runtime-isolation-evidence:v1",
382
+ profile: parseProfile(record.profile),
383
+ profileDigest: parseDigest(record.profileDigest),
384
+ testSuiteDigest: parseDigest(record.testSuiteDigest),
385
+ probes: parseProbes(record.probes),
386
+ positiveControls: parsePositiveControls(record.positiveControls),
387
+ redaction: { containsHostPaths: false, containsSecrets: false, containsHostPids: false },
388
+ evidenceDigest: parseDigest(record.evidenceDigest)
389
+ };
390
+ }
391
+ function parseProfile(value) {
392
+ const p = strictRecord(value, PROFILE_KEYS);
393
+ const limits = strictRecord(p.cgroupPolicy, ["version", "cpuQuotaMicros", "cpuPeriodMicros", "memoryBytes", "pidsMax"]);
394
+ if (p.schemaVersion !== 1 || p.provider !== "runsc" || p.platformMode !== "systrap" || p.privilegeModel !== "sudo-root" || p.workloadIdentity !== "uid-65532-gid-65532" || p.networkPolicy !== "isolated-veth-no-default-route" || limits.version !== 2 || limits.cpuQuotaMicros !== 5e4 || limits.cpuPeriodMicros !== 1e5 || limits.memoryBytes !== 134217728 || limits.pidsMax !== 64 || !Array.isArray(p.containerCapabilities) || p.containerCapabilities.length !== 0) invalid2();
395
+ for (const fact of [p.kernelRelease, p.runtimeVersion]) {
396
+ if (typeof fact !== "string" || !SAFE_FACT.test(fact)) invalid2();
397
+ }
398
+ return deepFreeze({
399
+ schemaVersion: 1,
400
+ provider: "runsc",
401
+ kernelRelease: p.kernelRelease,
402
+ runtimeVersion: p.runtimeVersion,
403
+ runtimeBinaryDigest: parseDigest(p.runtimeBinaryDigest),
404
+ rootfsBinaryDigest: parseDigest(p.rootfsBinaryDigest),
405
+ platformMode: "systrap",
406
+ privilegeModel: "sudo-root",
407
+ containerCapabilities: [],
408
+ workloadIdentity: "uid-65532-gid-65532",
409
+ networkPolicy: "isolated-veth-no-default-route",
410
+ cgroupPolicy: { version: 2, cpuQuotaMicros: 5e4, cpuPeriodMicros: 1e5, memoryBytes: 134217728, pidsMax: 64 },
411
+ providerConfigDigest: parseDigest(p.providerConfigDigest),
412
+ hostPolicyDigest: parseDigest(p.hostPolicyDigest)
413
+ });
414
+ }
415
+ function parseProbes(value) {
416
+ const p = strictRecord(value, RUNTIME_ISOLATION_PROBE_IDS);
417
+ for (const id of RUNTIME_ISOLATION_PROBE_IDS) if (p[id] !== "passed") invalid2();
418
+ return deepFreeze(Object.fromEntries(RUNTIME_ISOLATION_PROBE_IDS.map((id) => [id, "passed"])));
419
+ }
420
+ function parsePositiveControls(value) {
421
+ const keys = [
422
+ "ownMarkerReadable",
423
+ "attackerEndpointReachableBeforeHostileCalls",
424
+ "attackerEndpointReachableAfterHostileCalls",
425
+ "siblingEndpointReachableFromSibling",
426
+ "siblingCanaryReadableFromSibling",
427
+ "siblingAliveBeforeHostileCalls",
428
+ "siblingAliveAfterHostileCalls"
429
+ ];
430
+ const controls = strictRecord(value, keys);
431
+ for (const key of keys) if (controls[key] !== true) invalid2();
432
+ return deepFreeze(Object.fromEntries(keys.map((key) => [key, true])));
433
+ }
434
+ function strictRecord(value, keys) {
435
+ if (typeof value !== "object" || value === null || Array.isArray(value)) invalid2();
436
+ const record = value;
437
+ const actual = Object.keys(record);
438
+ if (actual.length !== keys.length || actual.some((key) => !keys.includes(key))) invalid2();
439
+ return record;
440
+ }
441
+ function parseDigest(value) {
442
+ if (typeof value !== "string" || !DIGEST.test(value)) invalid2();
443
+ return value;
444
+ }
445
+ function canonicalJson(value) {
446
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
447
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
448
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
449
+ }
450
+ function deepFreeze(value) {
451
+ if (typeof value === "object" && value !== null) {
452
+ for (const child of Object.values(value)) deepFreeze(child);
453
+ Object.freeze(value);
454
+ }
455
+ return value;
456
+ }
457
+ function invalid2() {
458
+ throw new Error("invalid runtime isolation evidence");
459
+ }
460
+ function rejected(code, message) {
461
+ return { status: "rejected", code, message };
462
+ }
273
463
  export {
274
464
  RUNSC_PREFLIGHT_ERROR_CODES,
275
465
  RUNSC_REQUIRED_BLOCKED_CIDRS,
276
466
  RUNSC_UNPROVEN_SECURITY_FACTS,
467
+ RUNTIME_ISOLATION_ERROR_CODES,
468
+ RUNTIME_ISOLATION_PROBE_IDS,
277
469
  RunscPreflightError,
470
+ createRuntimeIsolationEvidence,
471
+ digestRuntimeIsolationValue,
278
472
  preflightRunsc,
279
- validateRunscPreflightConfig
473
+ validateRunscPreflightConfig,
474
+ verifyRuntimeIsolationEvidence
280
475
  };
@@ -0,0 +1,65 @@
1
+ declare const RUNTIME_ISOLATION_PROBE_IDS: readonly ["sibling-filesystem-traversal", "proc-pid-enumeration", "cross-sandbox-signal", "cross-sandbox-ptrace", "mount-access", "device-access", "process-escape", "cross-workspace-network", "secret-access", "resource-ceilings", "teardown"];
2
+ type RuntimeIsolationProbeId = (typeof RUNTIME_ISOLATION_PROBE_IDS)[number];
3
+ type RuntimeIsolationDigest = `sha256:${string}`;
4
+ declare const RUNTIME_ISOLATION_ERROR_CODES: {
5
+ readonly invalidInput: "RUNSC_ISOLATION_INVALID_INPUT";
6
+ readonly probeFailed: "RUNSC_ISOLATION_PROBE_FAILED";
7
+ readonly evidenceInvalid: "RUNSC_ISOLATION_EVIDENCE_INVALID";
8
+ readonly profileDrift: "RUNSC_ISOLATION_PROFILE_DRIFT";
9
+ };
10
+ type RuntimeIsolationErrorCode = (typeof RUNTIME_ISOLATION_ERROR_CODES)[keyof typeof RUNTIME_ISOLATION_ERROR_CODES];
11
+ interface RuntimeIsolationProfileV1 {
12
+ readonly schemaVersion: 1;
13
+ readonly provider: "runsc";
14
+ readonly kernelRelease: string;
15
+ readonly runtimeVersion: string;
16
+ readonly runtimeBinaryDigest: RuntimeIsolationDigest;
17
+ readonly rootfsBinaryDigest: RuntimeIsolationDigest;
18
+ readonly platformMode: "systrap";
19
+ readonly privilegeModel: "sudo-root";
20
+ readonly containerCapabilities: readonly [];
21
+ readonly workloadIdentity: "uid-65532-gid-65532";
22
+ readonly networkPolicy: "isolated-veth-no-default-route";
23
+ readonly cgroupPolicy: {
24
+ readonly version: 2;
25
+ readonly cpuQuotaMicros: 50_000;
26
+ readonly cpuPeriodMicros: 100_000;
27
+ readonly memoryBytes: 134_217_728;
28
+ readonly pidsMax: 64;
29
+ };
30
+ readonly providerConfigDigest: RuntimeIsolationDigest;
31
+ readonly hostPolicyDigest: RuntimeIsolationDigest;
32
+ }
33
+ interface RuntimeIsolationEvidenceV1 {
34
+ readonly schemaVersion: 1;
35
+ readonly domain: "boring-runtime-isolation-evidence:v1";
36
+ readonly profile: RuntimeIsolationProfileV1;
37
+ readonly profileDigest: RuntimeIsolationDigest;
38
+ readonly testSuiteDigest: RuntimeIsolationDigest;
39
+ readonly probes: Readonly<Record<RuntimeIsolationProbeId, "passed">>;
40
+ readonly positiveControls: {
41
+ readonly ownMarkerReadable: true;
42
+ readonly attackerEndpointReachableBeforeHostileCalls: true;
43
+ readonly attackerEndpointReachableAfterHostileCalls: true;
44
+ readonly siblingEndpointReachableFromSibling: true;
45
+ readonly siblingCanaryReadableFromSibling: true;
46
+ readonly siblingAliveBeforeHostileCalls: true;
47
+ readonly siblingAliveAfterHostileCalls: true;
48
+ };
49
+ readonly redaction: {
50
+ readonly containsHostPaths: false;
51
+ readonly containsSecrets: false;
52
+ readonly containsHostPids: false;
53
+ };
54
+ readonly evidenceDigest: RuntimeIsolationDigest;
55
+ }
56
+ type RuntimeIsolationEvidenceVerification = {
57
+ readonly status: "accepted";
58
+ readonly evidenceDigest: RuntimeIsolationDigest;
59
+ } | {
60
+ readonly status: "rejected";
61
+ readonly code: RuntimeIsolationErrorCode;
62
+ readonly message: string;
63
+ };
64
+
65
+ export { RUNTIME_ISOLATION_ERROR_CODES as R, RUNTIME_ISOLATION_PROBE_IDS as a, type RuntimeIsolationDigest as b, type RuntimeIsolationErrorCode as c, type RuntimeIsolationEvidenceV1 as d, type RuntimeIsolationEvidenceVerification as e, type RuntimeIsolationProbeId as f, type RuntimeIsolationProfileV1 as g };
@@ -1,3 +1,5 @@
1
+ export { R as RUNTIME_ISOLATION_ERROR_CODES, a as RUNTIME_ISOLATION_PROBE_IDS, b as RuntimeIsolationDigest, c as RuntimeIsolationErrorCode, d as RuntimeIsolationEvidenceV1, e as RuntimeIsolationEvidenceVerification, f as RuntimeIsolationProbeId, g as RuntimeIsolationProfileV1 } from '../runtimeIsolation-Bn8t1ADl.js';
2
+
1
3
  type ProviderFilesystemCapability = "none" | "readonly" | "readwrite";
2
4
  type ProviderNetworkIsolation = "none" | "process" | "container" | "microvm" | "provider";
3
5
  type ProviderSourceOfTruth = "sandbox-primary" | "storage-primary";
@@ -105,9 +105,32 @@ var MODE_TO_PROVIDER = {
105
105
  "vercel-sandbox": "vercel-sandbox",
106
106
  "remote-worker": "remote-worker"
107
107
  };
108
+
109
+ // src/shared/runtimeIsolation.ts
110
+ var RUNTIME_ISOLATION_PROBE_IDS = [
111
+ "sibling-filesystem-traversal",
112
+ "proc-pid-enumeration",
113
+ "cross-sandbox-signal",
114
+ "cross-sandbox-ptrace",
115
+ "mount-access",
116
+ "device-access",
117
+ "process-escape",
118
+ "cross-workspace-network",
119
+ "secret-access",
120
+ "resource-ceilings",
121
+ "teardown"
122
+ ];
123
+ var RUNTIME_ISOLATION_ERROR_CODES = {
124
+ invalidInput: "RUNSC_ISOLATION_INVALID_INPUT",
125
+ probeFailed: "RUNSC_ISOLATION_PROBE_FAILED",
126
+ evidenceInvalid: "RUNSC_ISOLATION_EVIDENCE_INVALID",
127
+ profileDrift: "RUNSC_ISOLATION_PROFILE_DRIFT"
128
+ };
108
129
  export {
109
130
  MODE_TO_PROVIDER,
110
131
  PROVIDER_CAPABILITIES,
111
132
  PROVIDER_CAPABILITY_ERROR_CODES,
112
- PROVIDER_CONTRACT_VERSION
133
+ PROVIDER_CONTRACT_VERSION,
134
+ RUNTIME_ISOLATION_ERROR_CODES,
135
+ RUNTIME_ISOLATION_PROBE_IDS
113
136
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hachej/boring-sandbox",
3
- "version": "0.1.83",
3
+ "version": "0.1.85",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Sandbox provider contracts and implementations for Boring runtimes.",
@@ -44,6 +44,7 @@
44
44
  "typecheck": "tsc --noEmit",
45
45
  "check:invariants": "node ./scripts/check-invariants.mjs",
46
46
  "lint": "pnpm run typecheck && pnpm run check:invariants",
47
+ "qualify:runsc:isolation": "node ./scripts/qualify-runsc-isolation.mjs",
47
48
  "test": "vitest run --passWithNoTests",
48
49
  "clean": "rm -rf dist .tsbuildinfo"
49
50
  }