@smthrs/platform-node 1.0.0-rc.3 → 1.0.0-rc.4

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 (47) hide show
  1. package/bin/darwin-arm64/smithers-jj-export +0 -0
  2. package/bin/darwin-x64/smithers-jj-export +0 -0
  3. package/bin/linux-arm64/smithers-jj-export +0 -0
  4. package/bin/linux-x64/smithers-jj-export +2 -2
  5. package/bin/win32-x64/smithers-jj-export.exe +0 -0
  6. package/dist/cjs/ProcessConfinement.d.ts.map +1 -1
  7. package/dist/cjs/ProcessConfinement.js +6 -1
  8. package/dist/cjs/ProcessConfinement.js.map +2 -2
  9. package/dist/cjs/ProcessSandbox.d.ts +16 -2
  10. package/dist/cjs/ProcessSandbox.d.ts.map +1 -1
  11. package/dist/cjs/ProcessSandbox.js +17 -2
  12. package/dist/cjs/ProcessSandbox.js.map +2 -2
  13. package/dist/cjs/ScopedProcess.d.ts +2 -1
  14. package/dist/cjs/ScopedProcess.d.ts.map +1 -1
  15. package/dist/cjs/ScopedProcess.js.map +2 -2
  16. package/dist/cjs/internal/ProcessSupervisor.d.ts +2 -0
  17. package/dist/cjs/internal/ProcessSupervisor.d.ts.map +1 -1
  18. package/dist/cjs/internal/ProcessSupervisor.js +5 -2
  19. package/dist/cjs/internal/ProcessSupervisor.js.map +2 -2
  20. package/dist/cjs/internal/SupervisorProgram.d.ts.map +1 -1
  21. package/dist/cjs/internal/SupervisorProgram.js +23 -3
  22. package/dist/cjs/internal/SupervisorProgram.js.map +2 -2
  23. package/dist/esm/ProcessConfinement.d.ts.map +1 -1
  24. package/dist/esm/ProcessConfinement.js.map +1 -1
  25. package/dist/esm/ProcessSandbox.d.ts +16 -2
  26. package/dist/esm/ProcessSandbox.d.ts.map +1 -1
  27. package/dist/esm/ProcessSandbox.js +33 -4
  28. package/dist/esm/ProcessSandbox.js.map +1 -1
  29. package/dist/esm/ScopedProcess.d.ts +2 -1
  30. package/dist/esm/ScopedProcess.d.ts.map +1 -1
  31. package/dist/esm/ScopedProcess.js +2 -1
  32. package/dist/esm/ScopedProcess.js.map +1 -1
  33. package/dist/esm/internal/ProcessSupervisor.d.ts +2 -0
  34. package/dist/esm/internal/ProcessSupervisor.d.ts.map +1 -1
  35. package/dist/esm/internal/ProcessSupervisor.js +9 -2
  36. package/dist/esm/internal/ProcessSupervisor.js.map +1 -1
  37. package/dist/esm/internal/SupervisorProgram.d.ts.map +1 -1
  38. package/dist/esm/internal/SupervisorProgram.js +23 -3
  39. package/dist/esm/internal/SupervisorProgram.js.map +1 -1
  40. package/docs/api.md +2 -1
  41. package/docs/concepts/process-containment.md +8 -0
  42. package/package.json +4 -4
  43. package/src/ProcessConfinement.ts +10 -3
  44. package/src/ProcessSandbox.ts +38 -4
  45. package/src/ScopedProcess.ts +2 -1
  46. package/src/internal/ProcessSupervisor.ts +8 -2
  47. package/src/internal/SupervisorProgram.ts +23 -3
Binary file
Binary file
Binary file
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/bin/linux-x64/smithers-jj-export
3
- size: 53554632 bytes
4
- sha256: 93dabf60cf9ebb1ad7e19b0ebab48df7183970c329eeeb8c67a14deeff179b86
3
+ size: 53554360 bytes
4
+ sha256: 082aad5f9ca4c16a4bf1ad78225e1c0e1677141913c3a5601c586f8a8a5fdb08
@@ -1 +1 @@
1
- {"version":3,"file":"ProcessConfinement.d.ts","sourceRoot":"","sources":["../../src/ProcessConfinement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,wBAAwB,MAAM,mCAAmC,CAAA;AAE7E,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAOrC,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,GAAG,YAAY,GAAG,SAAS,CAAA;IAC1D,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,IAAI,GAAG,SAAS,CAAA;IAC/C,uGAAuG;IACvG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACjD;AA0FD;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,UAAS,OAAY,KAAG,wBAAwB,CAAC,OAoMrE,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,UAAS,OAAY,KAAG,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,kBAAkB,CAC1B,CAAA"}
1
+ {"version":3,"file":"ProcessConfinement.d.ts","sourceRoot":"","sources":["../../src/ProcessConfinement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,wBAAwB,MAAM,mCAAmC,CAAA;AAE7E,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAOrC,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,GAAG,YAAY,GAAG,SAAS,CAAA;IAC1D,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,IAAI,GAAG,SAAS,CAAA;IAC/C,uGAAuG;IACvG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACjD;AA0FD;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,UAAS,OAAY,KAAG,wBAAwB,CAAC,OA2MrE,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,UAAS,OAAY,KAAG,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,kBAAkB,CAC1B,CAAA"}
@@ -246,7 +246,12 @@ const make = (options = {}) => {
246
246
  );
247
247
  const targetArgv = ["/usr/bin/env", "-i", "/bin/sh", script, launch.program, ...originalArgv.slice(1)];
248
248
  const wrapped = yield* Effect.try({
249
- try: () => ProcessSandbox.wrap({ ...confinement, externalReads: [...confinement.externalReads, ...launch.reads, script] }, targetArgv, targetEnvironment, hostFacts),
249
+ try: () => ProcessSandbox.wrap(
250
+ { ...confinement, externalReads: [...confinement.externalReads, ...launch.reads, script] },
251
+ targetArgv,
252
+ targetEnvironment,
253
+ hostFacts
254
+ ),
250
255
  catch: (cause) => failure("Unknown", command, `could not render the confinement: ${messageOf(cause)}`, cause)
251
256
  });
252
257
  let [executable, ...args] = wrapped.argv;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/ProcessConfinement.ts"],
4
- "sourcesContent": ["/**\n * The kernel's `ProcessConfinement` seam, filled with this host's native\n * sandbox: bubblewrap on Linux, seatbelt on macOS.\n *\n * `@smthrs/kernel`'s `ChildProcessSpawner.layer` hands every stage that passed\n * its `proc:spawn` check to the confinement in its context, together with the\n * `ProcessConfinement.Profile` the grants in force admit. This module turns\n * that profile into a {@link ProcessSandbox.Request}, plans it against the\n * workspace, and wraps the stage's argv in the mechanism the host has, so an\n * approved `bash` can write only where an `fs:write` grant says and reach the\n * network only when a `net:*` grant says. A stage that asked for the platform\n * shell is spelled out as `/bin/sh -c <line>` first: wrapping a `shell: true`\n * command line would otherwise leave its redirections and pipes to a shell\n * outside the sandbox.\n *\n * A host with no mechanism is the one decision this module leaves to its\n * caller: {@link Options.unavailable} either refuses the spawn, so nothing\n * runs that the profile would not have confined, or runs it unconfined with\n * a warning, the way every host did before this seam existed. A write set\n * the mechanism cannot enforce safely, a symbolic link below the workspace\n * root, is always refused.\n *\n * @since 1.0.0-rc.1\n */\n\nimport * as KernelProcessConfinement from \"@smthrs/kernel/ProcessConfinement\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport * as PlatformError from \"effect/PlatformError\"\nimport type * as Scope from \"effect/Scope\"\nimport * as ChildProcess from \"effect/unstable/process/ChildProcess\"\nimport * as NodeFs from \"node:fs\"\nimport * as NodeOs from \"node:os\"\nimport * as NodePath from \"node:path\"\nimport * as ProcessSandbox from \"./ProcessSandbox.ts\"\n\n/**\n * How the confinement is built.\n *\n * @category models\n * @since 1.0.0-rc.1\n */\nexport interface Options {\n /**\n * What happens when this host has no mechanism to enforce a profile with.\n * `\"refuse\"` fails the spawn, so a command never runs with more than the\n * profile allows; `\"unconfined\"` runs it as given and logs a\n * warning naming what the host lacks.\n */\n readonly unavailable?: \"refuse\" | \"unconfined\" | undefined\n /** The host facts mechanism selection reads; defaults to the real host. */\n readonly host?: ProcessSandbox.Host | undefined\n /** Where each run's private temporary directory is created; defaults to the OS temporary directory. */\n readonly temporaryDirectory?: string | undefined\n}\n\nconst shellLine = (command: ChildProcess.StandardCommand): string => [command.command, ...command.args].join(\" \")\n\n/**\n * The argv a stage executes, with a shell request made explicit.\n *\n * Node runs a `shell: true` stage as `/bin/sh -c <line>` on POSIX, and a\n * string shell as `<shell> -c <line>`; the wrapper needs that program to be\n * the one it confines, so the shell becomes the argv's first token and the\n * spawned stage no longer asks for one.\n */\nconst argvOf = (command: ChildProcess.StandardCommand): ReadonlyArray<string> => {\n const shell = command.options.shell\n if (shell === undefined || shell === false) return [command.command, ...command.args]\n return [shell === true ? \"/bin/sh\" : shell, \"-c\", shellLine(command)]\n}\n\nconst failure = (\n tag: \"NotFound\" | \"PermissionDenied\" | \"Unknown\",\n command: ChildProcess.StandardCommand,\n description: string,\n cause: unknown\n): PlatformError.PlatformError =>\n PlatformError.systemError({\n _tag: tag,\n module: \"ProcessConfinement\",\n method: \"confine\",\n pathOrDescriptor: shellLine(command),\n description,\n cause\n })\n\nconst messageOf = (cause: unknown): string =>\n ProcessSandbox.isUnenforceable(cause)\n ? cause.message\n : cause instanceof Error\n ? cause.message\n : String(cause)\n\n/** Classic BPF for seccomp_data: deny host Unix sockets and io_uring, preserving stream socketpair.\n * Closed networking additionally denies every IP socket family.\n * Wrong ABI and x32 syscall encodings fail closed rather than bypassing socket(). */\nconst networkFilter = (architecture: string, network: \"none\" | \"open\"): Uint8Array => {\n const abi = architecture === \"x64\"\n ? { audit: 0xc000003e, socket: 41, socketpair: 53 }\n : architecture === \"arm64\"\n ? { audit: 0xc00000b7, socket: 198, socketpair: 199 }\n : undefined\n if (abi === undefined) throw new Error(`native-network seccomp is unavailable on ${architecture}`)\n const instructions: Array<readonly [number, number, number, number]> = [\n [0x20, 0, 0, 4], // load audit architecture\n [0x15, 1, 0, abi.audit],\n [0x06, 0, 0, 0x80000000], // kill unsupported ABI\n [0x20, 0, 0, 0], // load syscall number\n [0x35, 0, 1, 0x40000000],\n [0x06, 0, 0, 0x80000000], // kill x32 / invalid high syscall numbers\n [0x15, 0, 1, 425], // io_uring_setup on both supported ABIs\n [0x06, 0, 0, 0x00050001], // io_uring can otherwise create sockets without socket()\n [0x15, 0, 6, abi.socketpair],\n [0x20, 0, 0, 16], // socketpair domain\n [0x15, 0, 4, 1], // AF_UNIX\n [0x20, 0, 0, 24], // socketpair type, low 32 bits of args[1]\n [0x54, 0, 0, 0xf], // strip SOCK_NONBLOCK and SOCK_CLOEXEC\n [0x15, 1, 0, 1], // only SOCK_STREAM; Linux aliases SOCK_RAW to datagram operations\n [0x06, 0, 0, 0x00050001],\n [0x20, 0, 0, 0] // reload syscall number before the socket() policy\n ]\n if (network === \"none\") {\n instructions.push([0x15, 0, 1, abi.socket], [0x06, 0, 0, 0x00050001]) // EPERM for every socket family\n } else {\n instructions.push(\n [0x15, 0, 3, abi.socket],\n [0x20, 0, 0, 16], // socket domain, low 32 bits of args[0]\n [0x15, 0, 1, 1], // AF_UNIX; IP families remain available\n [0x06, 0, 0, 0x00050001]\n )\n }\n instructions.push([0x06, 0, 0, 0x7fff0000]) // SECCOMP_RET_ALLOW\n const bytes = new Uint8Array(instructions.length * 8)\n const view = new DataView(bytes.buffer)\n for (const [index, [code, jt, jf, value]] of instructions.entries()) {\n view.setUint16(index * 8, code, true)\n view.setUint8(index * 8 + 2, jt)\n view.setUint8(index * 8 + 3, jf)\n view.setUint32(index * 8 + 4, value, true)\n }\n return bytes\n}\n\n/**\n * Builds the native confinement.\n *\n * @category constructors\n * @since 1.0.0-rc.1\n */\nexport const make = (options: Options = {}): KernelProcessConfinement.Service => {\n const hostFacts = options.host ?? ProcessSandbox.host()\n const temporaryRoot = options.temporaryDirectory ?? NodeOs.tmpdir()\n const unavailable = options.unavailable ?? \"refuse\"\n const confine = Effect.fn(\"ProcessConfinement.confine\")(function*(\n command: ChildProcess.StandardCommand,\n profile: KernelProcessConfinement.Profile\n ): Effect.fn.Return<ChildProcess.StandardCommand, PlatformError.PlatformError, Scope.Scope> {\n const request: ProcessSandbox.Request = {\n network: profile.network,\n unixSockets: false,\n strict: true,\n reads: profile.reads,\n writes: profile.writes,\n readOnly: profile.readOnly\n }\n const selected = ProcessSandbox.select(request, hostFacts)\n if (ProcessSandbox.isUnenforceable(selected)) {\n if (unavailable === \"refuse\") {\n return yield* failure(\n \"NotFound\",\n command,\n `${selected.message} This host refuses to spawn unconfined.`,\n selected\n )\n }\n yield* Effect.logWarning(`${selected.message} Running unconfined.`)\n return command\n }\n // The stage's directory is absolute: the kernel spawner roots it first.\n const cwd = command.options.cwd ?? profile.workspaceRoot\n const within = (root: string, path: string): boolean => {\n const relative = NodePath.relative(root, path)\n return relative !== \"..\" && !relative.startsWith(`..${NodePath.sep}`) && !NodePath.isAbsolute(relative)\n }\n if (!within(profile.workspaceRoot, cwd)) {\n return yield* failure(\"PermissionDenied\", command, \"command directory is outside the workspace\", undefined)\n }\n // A lexical workspace path can enter an unrelated host directory through\n // a symlink. Check the real directory before granting or preparing a run.\n const canonical = yield* Effect.try({\n try: () => {\n const root = NodeFs.realpathSync(profile.workspaceRoot)\n const directory = NodeFs.realpathSync(cwd)\n if (!within(root, directory)) throw new Error(\"command directory is outside the workspace\")\n for (const relative of profile.reads) {\n const lexical = NodePath.resolve(root, relative)\n if (!within(root, lexical)) continue\n // A read bind follows its source symlink. Refuse a grant that would\n // therefore mount unrelated host bytes inside the workspace.\n if (NodeFs.existsSync(lexical)) {\n const real = NodeFs.realpathSync(lexical)\n if (!within(root, real)) throw new Error(\"read grant resolves outside the workspace\")\n if (real !== lexical) throw new Error(\"read grant is a symbolic link\")\n }\n }\n return { root, cwd: directory }\n },\n catch: (cause) => failure(\"PermissionDenied\", command, messageOf(cause), cause)\n })\n // The private tmp lives as long as the spawn's scope, however preparation\n // ends; the declared write directories are created so the mechanism has\n // something to bind, which the grant that opened them already permits.\n const allocatedTmp = yield* Effect.acquireRelease(\n Effect.try({\n try: () => NodeFs.mkdtempSync(NodePath.join(temporaryRoot, \"smithers-confinement-\")),\n catch: (cause) => failure(\"Unknown\", command, `could not prepare the confinement: ${messageOf(cause)}`, cause)\n }),\n (directory) =>\n Effect.sync(() => {\n try {\n NodeFs.rmSync(directory, { recursive: true, force: true })\n } catch {\n // Cleanup is best-effort when the host refuses directory removal.\n }\n })\n )\n const tmp = yield* Effect.try({\n try: () => NodeFs.realpathSync(allocatedTmp),\n catch: (cause) => failure(\"Unknown\", command, `could not prepare the confinement: ${messageOf(cause)}`, cause)\n })\n const planned = yield* Effect.try({\n try: () => ProcessSandbox.plan(request, { workspaceRoot: canonical.root, cwd: canonical.cwd, tmp }, hostFacts),\n catch: (cause) => failure(\"Unknown\", command, `could not plan the confinement: ${messageOf(cause)}`, cause)\n })\n if (ProcessSandbox.isUnenforceable(planned)) {\n return yield* failure(\"PermissionDenied\", command, planned.message, planned)\n }\n // Build outputs may grant their parent directory. An agent grant must\n // never inherit that widening when a requested tree is already a file.\n const exactWrites = profile.writes.map((relative) => NodePath.resolve(planned.workspaceRoot, relative))\n if (planned.writes.some((write) => !exactWrites.includes(write))) {\n return yield* failure(\"PermissionDenied\", command, \"write grant is not a directory tree\", undefined)\n }\n // A workspace link does not grant authority to its target on the host.\n const confinement: ProcessSandbox.Plan = { ...planned, externalReads: [] }\n yield* Effect.try({\n try: () => {\n ProcessSandbox.validateWrites(confinement, hostFacts)\n NodeFs.mkdirSync(NodePath.join(tmp, \"home\"), { recursive: true })\n NodeFs.mkdirSync(NodePath.join(tmp, \"cache\"), { recursive: true })\n for (const write of planned.writes) NodeFs.mkdirSync(write, { recursive: true })\n },\n catch: (cause) => failure(\"Unknown\", command, `could not prepare the confinement: ${messageOf(cause)}`, cause)\n })\n // Only the target receives its requested environment. Dynamic-loader and\n // other startup variables must never configure the host sandbox launcher.\n const targetEnvironment: Record<string, string> = {}\n const inherited = command.options.env === undefined || command.options.extendEnv === true\n for (const [name, value] of Object.entries(inherited ? process.env : {})) {\n // Bash exports functions as names such as BASH_FUNC_which%%. These\n // ambient entries cannot be exported by the portable inner launcher.\n if (typeof value === \"string\" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) targetEnvironment[name] = value\n }\n for (const [name, value] of Object.entries(command.options.env ?? {})) {\n if (typeof value === \"string\") targetEnvironment[name] = value\n else delete targetEnvironment[name]\n }\n const privateEnvironment = ProcessSandbox.environment(confinement)\n const script = yield* Effect.try({\n try: () => {\n const quote = (value: string): string => `'${value.replaceAll(\"'\", \"'\\\\''\")}'`\n const exports: Array<string> = []\n for (const [name, value] of Object.entries({ ...targetEnvironment, ...privateEnvironment })) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) throw new Error(\"environment variable name is not portable\")\n if (value.includes(\"\\0\")) throw new Error(\"environment variable contains a null byte\")\n exports.push(`export ${name}=${quote(value)}`)\n }\n const file = NodePath.join(tmp, \"environment.sh\")\n // Values stay off argv and journal receipts; the script is private,\n // removed with the scope, and interpreted only inside confinement.\n NodeFs.writeFileSync(\n file,\n [\n \"#!/bin/sh\",\n \"unset ENV BASH_ENV CDPATH PWD OLDPWD SHLVL _\",\n ...exports,\n \"exec \\\"$@\\\"\",\n \"\"\n ].join(\"\\n\"),\n { flag: \"wx\", mode: 0o600 }\n )\n return file\n },\n catch: (cause) => failure(\"PermissionDenied\", command, messageOf(cause), cause)\n })\n // Resolve the actual program before wrapping it in the environment shell.\n // Otherwise the sandbox sees only /usr/bin/env and omits a native helper\n // installed outside its ordinary runtime paths.\n const originalArgv = argvOf(command)\n const launch = ProcessSandbox.launcher(\n originalArgv[0]!, targetEnvironment.PATH,\n [...confinement.reads, ...confinement.writes, ...confinement.externalReads],\n confinement.workspaceRoot, hostFacts\n )\n const targetArgv = [\"/usr/bin/env\", \"-i\", \"/bin/sh\", script, launch.program, ...originalArgv.slice(1)]\n const wrapped = yield* Effect.try({\n try: () =>\n ProcessSandbox.wrap({ ...confinement, externalReads: [...confinement.externalReads, ...launch.reads, script] }, targetArgv, targetEnvironment, hostFacts),\n catch: (cause) => failure(\"Unknown\", command, `could not render the confinement: ${messageOf(cause)}`, cause)\n })\n let [executable, ...args] = wrapped.argv\n if (selected._tag === \"bubblewrap\") {\n const filter = yield* Effect.try({\n try: () => {\n const file = NodePath.join(tmp, \"network.seccomp\")\n NodeFs.writeFileSync(file, networkFilter(process.arch, profile.network), { flag: \"wx\", mode: 0o600 })\n return file\n },\n catch: (cause) => failure(\"PermissionDenied\", command, messageOf(cause), cause)\n })\n let fd = 3\n while (command.options.additionalFds?.[`fd${fd}`] !== undefined) fd++\n // A regular file avoids a filter-input pipe whose early closure can\n // surface as an unhandled ECONNRESET before bwrap reports its refusal.\n args = [\n \"-c\",\n `exec ${fd}<\"$1\"; shift; exec \"$@\"`,\n \"smithers-seccomp\",\n filter,\n executable!,\n \"--seccomp\",\n String(fd),\n ...args\n ]\n executable = \"/bin/sh\"\n }\n return ChildProcess.make(executable!, args, {\n ...command.options,\n cwd: canonical.cwd,\n shell: false,\n env: { PATH: \"/usr/bin:/bin:/usr/sbin:/sbin\", LANG: \"C\", ...privateEnvironment },\n extendEnv: false\n })\n })\n return KernelProcessConfinement.ProcessConfinement.of({ confine })\n}\n\n/**\n * Provides the native confinement.\n *\n * @category layers\n * @since 1.0.0-rc.1\n */\nexport const layer = (options: Options = {}): Layer.Layer<KernelProcessConfinement.ProcessConfinement> =>\n Layer.succeed(KernelProcessConfinement.ProcessConfinement)(make(options))\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * The kernel's `ProcessConfinement` seam, filled with this host's native\n * sandbox: bubblewrap on Linux, seatbelt on macOS.\n *\n * `@smthrs/kernel`'s `ChildProcessSpawner.layer` hands every stage that passed\n * its `proc:spawn` check to the confinement in its context, together with the\n * `ProcessConfinement.Profile` the grants in force admit. This module turns\n * that profile into a {@link ProcessSandbox.Request}, plans it against the\n * workspace, and wraps the stage's argv in the mechanism the host has, so an\n * approved `bash` can write only where an `fs:write` grant says and reach the\n * network only when a `net:*` grant says. A stage that asked for the platform\n * shell is spelled out as `/bin/sh -c <line>` first: wrapping a `shell: true`\n * command line would otherwise leave its redirections and pipes to a shell\n * outside the sandbox.\n *\n * A host with no mechanism is the one decision this module leaves to its\n * caller: {@link Options.unavailable} either refuses the spawn, so nothing\n * runs that the profile would not have confined, or runs it unconfined with\n * a warning, the way every host did before this seam existed. A write set\n * the mechanism cannot enforce safely, a symbolic link below the workspace\n * root, is always refused.\n *\n * @since 1.0.0-rc.1\n */\n\nimport * as KernelProcessConfinement from \"@smthrs/kernel/ProcessConfinement\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport * as PlatformError from \"effect/PlatformError\"\nimport type * as Scope from \"effect/Scope\"\nimport * as ChildProcess from \"effect/unstable/process/ChildProcess\"\nimport * as NodeFs from \"node:fs\"\nimport * as NodeOs from \"node:os\"\nimport * as NodePath from \"node:path\"\nimport * as ProcessSandbox from \"./ProcessSandbox.ts\"\n\n/**\n * How the confinement is built.\n *\n * @category models\n * @since 1.0.0-rc.1\n */\nexport interface Options {\n /**\n * What happens when this host has no mechanism to enforce a profile with.\n * `\"refuse\"` fails the spawn, so a command never runs with more than the\n * profile allows; `\"unconfined\"` runs it as given and logs a\n * warning naming what the host lacks.\n */\n readonly unavailable?: \"refuse\" | \"unconfined\" | undefined\n /** The host facts mechanism selection reads; defaults to the real host. */\n readonly host?: ProcessSandbox.Host | undefined\n /** Where each run's private temporary directory is created; defaults to the OS temporary directory. */\n readonly temporaryDirectory?: string | undefined\n}\n\nconst shellLine = (command: ChildProcess.StandardCommand): string => [command.command, ...command.args].join(\" \")\n\n/**\n * The argv a stage executes, with a shell request made explicit.\n *\n * Node runs a `shell: true` stage as `/bin/sh -c <line>` on POSIX, and a\n * string shell as `<shell> -c <line>`; the wrapper needs that program to be\n * the one it confines, so the shell becomes the argv's first token and the\n * spawned stage no longer asks for one.\n */\nconst argvOf = (command: ChildProcess.StandardCommand): ReadonlyArray<string> => {\n const shell = command.options.shell\n if (shell === undefined || shell === false) return [command.command, ...command.args]\n return [shell === true ? \"/bin/sh\" : shell, \"-c\", shellLine(command)]\n}\n\nconst failure = (\n tag: \"NotFound\" | \"PermissionDenied\" | \"Unknown\",\n command: ChildProcess.StandardCommand,\n description: string,\n cause: unknown\n): PlatformError.PlatformError =>\n PlatformError.systemError({\n _tag: tag,\n module: \"ProcessConfinement\",\n method: \"confine\",\n pathOrDescriptor: shellLine(command),\n description,\n cause\n })\n\nconst messageOf = (cause: unknown): string =>\n ProcessSandbox.isUnenforceable(cause)\n ? cause.message\n : cause instanceof Error\n ? cause.message\n : String(cause)\n\n/** Classic BPF for seccomp_data: deny host Unix sockets and io_uring, preserving stream socketpair.\n * Closed networking additionally denies every IP socket family.\n * Wrong ABI and x32 syscall encodings fail closed rather than bypassing socket(). */\nconst networkFilter = (architecture: string, network: \"none\" | \"open\"): Uint8Array => {\n const abi = architecture === \"x64\"\n ? { audit: 0xc000003e, socket: 41, socketpair: 53 }\n : architecture === \"arm64\"\n ? { audit: 0xc00000b7, socket: 198, socketpair: 199 }\n : undefined\n if (abi === undefined) throw new Error(`native-network seccomp is unavailable on ${architecture}`)\n const instructions: Array<readonly [number, number, number, number]> = [\n [0x20, 0, 0, 4], // load audit architecture\n [0x15, 1, 0, abi.audit],\n [0x06, 0, 0, 0x80000000], // kill unsupported ABI\n [0x20, 0, 0, 0], // load syscall number\n [0x35, 0, 1, 0x40000000],\n [0x06, 0, 0, 0x80000000], // kill x32 / invalid high syscall numbers\n [0x15, 0, 1, 425], // io_uring_setup on both supported ABIs\n [0x06, 0, 0, 0x00050001], // io_uring can otherwise create sockets without socket()\n [0x15, 0, 6, abi.socketpair],\n [0x20, 0, 0, 16], // socketpair domain\n [0x15, 0, 4, 1], // AF_UNIX\n [0x20, 0, 0, 24], // socketpair type, low 32 bits of args[1]\n [0x54, 0, 0, 0xf], // strip SOCK_NONBLOCK and SOCK_CLOEXEC\n [0x15, 1, 0, 1], // only SOCK_STREAM; Linux aliases SOCK_RAW to datagram operations\n [0x06, 0, 0, 0x00050001],\n [0x20, 0, 0, 0] // reload syscall number before the socket() policy\n ]\n if (network === \"none\") {\n instructions.push([0x15, 0, 1, abi.socket], [0x06, 0, 0, 0x00050001]) // EPERM for every socket family\n } else {\n instructions.push(\n [0x15, 0, 3, abi.socket],\n [0x20, 0, 0, 16], // socket domain, low 32 bits of args[0]\n [0x15, 0, 1, 1], // AF_UNIX; IP families remain available\n [0x06, 0, 0, 0x00050001]\n )\n }\n instructions.push([0x06, 0, 0, 0x7fff0000]) // SECCOMP_RET_ALLOW\n const bytes = new Uint8Array(instructions.length * 8)\n const view = new DataView(bytes.buffer)\n for (const [index, [code, jt, jf, value]] of instructions.entries()) {\n view.setUint16(index * 8, code, true)\n view.setUint8(index * 8 + 2, jt)\n view.setUint8(index * 8 + 3, jf)\n view.setUint32(index * 8 + 4, value, true)\n }\n return bytes\n}\n\n/**\n * Builds the native confinement.\n *\n * @category constructors\n * @since 1.0.0-rc.1\n */\nexport const make = (options: Options = {}): KernelProcessConfinement.Service => {\n const hostFacts = options.host ?? ProcessSandbox.host()\n const temporaryRoot = options.temporaryDirectory ?? NodeOs.tmpdir()\n const unavailable = options.unavailable ?? \"refuse\"\n const confine = Effect.fn(\"ProcessConfinement.confine\")(function*(\n command: ChildProcess.StandardCommand,\n profile: KernelProcessConfinement.Profile\n ): Effect.fn.Return<ChildProcess.StandardCommand, PlatformError.PlatformError, Scope.Scope> {\n const request: ProcessSandbox.Request = {\n network: profile.network,\n unixSockets: false,\n strict: true,\n reads: profile.reads,\n writes: profile.writes,\n readOnly: profile.readOnly\n }\n const selected = ProcessSandbox.select(request, hostFacts)\n if (ProcessSandbox.isUnenforceable(selected)) {\n if (unavailable === \"refuse\") {\n return yield* failure(\n \"NotFound\",\n command,\n `${selected.message} This host refuses to spawn unconfined.`,\n selected\n )\n }\n yield* Effect.logWarning(`${selected.message} Running unconfined.`)\n return command\n }\n // The stage's directory is absolute: the kernel spawner roots it first.\n const cwd = command.options.cwd ?? profile.workspaceRoot\n const within = (root: string, path: string): boolean => {\n const relative = NodePath.relative(root, path)\n return relative !== \"..\" && !relative.startsWith(`..${NodePath.sep}`) && !NodePath.isAbsolute(relative)\n }\n if (!within(profile.workspaceRoot, cwd)) {\n return yield* failure(\"PermissionDenied\", command, \"command directory is outside the workspace\", undefined)\n }\n // A lexical workspace path can enter an unrelated host directory through\n // a symlink. Check the real directory before granting or preparing a run.\n const canonical = yield* Effect.try({\n try: () => {\n const root = NodeFs.realpathSync(profile.workspaceRoot)\n const directory = NodeFs.realpathSync(cwd)\n if (!within(root, directory)) throw new Error(\"command directory is outside the workspace\")\n for (const relative of profile.reads) {\n const lexical = NodePath.resolve(root, relative)\n if (!within(root, lexical)) continue\n // A read bind follows its source symlink. Refuse a grant that would\n // therefore mount unrelated host bytes inside the workspace.\n if (NodeFs.existsSync(lexical)) {\n const real = NodeFs.realpathSync(lexical)\n if (!within(root, real)) throw new Error(\"read grant resolves outside the workspace\")\n if (real !== lexical) throw new Error(\"read grant is a symbolic link\")\n }\n }\n return { root, cwd: directory }\n },\n catch: (cause) => failure(\"PermissionDenied\", command, messageOf(cause), cause)\n })\n // The private tmp lives as long as the spawn's scope, however preparation\n // ends; the declared write directories are created so the mechanism has\n // something to bind, which the grant that opened them already permits.\n const allocatedTmp = yield* Effect.acquireRelease(\n Effect.try({\n try: () => NodeFs.mkdtempSync(NodePath.join(temporaryRoot, \"smithers-confinement-\")),\n catch: (cause) => failure(\"Unknown\", command, `could not prepare the confinement: ${messageOf(cause)}`, cause)\n }),\n (directory) =>\n Effect.sync(() => {\n try {\n NodeFs.rmSync(directory, { recursive: true, force: true })\n } catch {\n // Cleanup is best-effort when the host refuses directory removal.\n }\n })\n )\n const tmp = yield* Effect.try({\n try: () => NodeFs.realpathSync(allocatedTmp),\n catch: (cause) => failure(\"Unknown\", command, `could not prepare the confinement: ${messageOf(cause)}`, cause)\n })\n const planned = yield* Effect.try({\n try: () => ProcessSandbox.plan(request, { workspaceRoot: canonical.root, cwd: canonical.cwd, tmp }, hostFacts),\n catch: (cause) => failure(\"Unknown\", command, `could not plan the confinement: ${messageOf(cause)}`, cause)\n })\n if (ProcessSandbox.isUnenforceable(planned)) {\n return yield* failure(\"PermissionDenied\", command, planned.message, planned)\n }\n // Build outputs may grant their parent directory. An agent grant must\n // never inherit that widening when a requested tree is already a file.\n const exactWrites = profile.writes.map((relative) => NodePath.resolve(planned.workspaceRoot, relative))\n if (planned.writes.some((write) => !exactWrites.includes(write))) {\n return yield* failure(\"PermissionDenied\", command, \"write grant is not a directory tree\", undefined)\n }\n // A workspace link does not grant authority to its target on the host.\n const confinement: ProcessSandbox.Plan = { ...planned, externalReads: [] }\n yield* Effect.try({\n try: () => {\n ProcessSandbox.validateWrites(confinement, hostFacts)\n NodeFs.mkdirSync(NodePath.join(tmp, \"home\"), { recursive: true })\n NodeFs.mkdirSync(NodePath.join(tmp, \"cache\"), { recursive: true })\n for (const write of planned.writes) NodeFs.mkdirSync(write, { recursive: true })\n },\n catch: (cause) => failure(\"Unknown\", command, `could not prepare the confinement: ${messageOf(cause)}`, cause)\n })\n // Only the target receives its requested environment. Dynamic-loader and\n // other startup variables must never configure the host sandbox launcher.\n const targetEnvironment: Record<string, string> = {}\n const inherited = command.options.env === undefined || command.options.extendEnv === true\n for (const [name, value] of Object.entries(inherited ? process.env : {})) {\n // Bash exports functions as names such as BASH_FUNC_which%%. These\n // ambient entries cannot be exported by the portable inner launcher.\n if (typeof value === \"string\" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) targetEnvironment[name] = value\n }\n for (const [name, value] of Object.entries(command.options.env ?? {})) {\n if (typeof value === \"string\") targetEnvironment[name] = value\n else delete targetEnvironment[name]\n }\n const privateEnvironment = ProcessSandbox.environment(confinement)\n const script = yield* Effect.try({\n try: () => {\n const quote = (value: string): string => `'${value.replaceAll(\"'\", \"'\\\\''\")}'`\n const exports: Array<string> = []\n for (const [name, value] of Object.entries({ ...targetEnvironment, ...privateEnvironment })) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) throw new Error(\"environment variable name is not portable\")\n if (value.includes(\"\\0\")) throw new Error(\"environment variable contains a null byte\")\n exports.push(`export ${name}=${quote(value)}`)\n }\n const file = NodePath.join(tmp, \"environment.sh\")\n // Values stay off argv and journal receipts; the script is private,\n // removed with the scope, and interpreted only inside confinement.\n NodeFs.writeFileSync(\n file,\n [\n \"#!/bin/sh\",\n \"unset ENV BASH_ENV CDPATH PWD OLDPWD SHLVL _\",\n ...exports,\n \"exec \\\"$@\\\"\",\n \"\"\n ].join(\"\\n\"),\n { flag: \"wx\", mode: 0o600 }\n )\n return file\n },\n catch: (cause) => failure(\"PermissionDenied\", command, messageOf(cause), cause)\n })\n // Resolve the actual program before wrapping it in the environment shell.\n // Otherwise the sandbox sees only /usr/bin/env and omits a native helper\n // installed outside its ordinary runtime paths.\n const originalArgv = argvOf(command)\n const launch = ProcessSandbox.launcher(\n originalArgv[0]!,\n targetEnvironment.PATH,\n [...confinement.reads, ...confinement.writes, ...confinement.externalReads],\n confinement.workspaceRoot,\n hostFacts\n )\n const targetArgv = [\"/usr/bin/env\", \"-i\", \"/bin/sh\", script, launch.program, ...originalArgv.slice(1)]\n const wrapped = yield* Effect.try({\n try: () =>\n ProcessSandbox.wrap(\n { ...confinement, externalReads: [...confinement.externalReads, ...launch.reads, script] },\n targetArgv,\n targetEnvironment,\n hostFacts\n ),\n catch: (cause) => failure(\"Unknown\", command, `could not render the confinement: ${messageOf(cause)}`, cause)\n })\n let [executable, ...args] = wrapped.argv\n if (selected._tag === \"bubblewrap\") {\n const filter = yield* Effect.try({\n try: () => {\n const file = NodePath.join(tmp, \"network.seccomp\")\n NodeFs.writeFileSync(file, networkFilter(process.arch, profile.network), { flag: \"wx\", mode: 0o600 })\n return file\n },\n catch: (cause) => failure(\"PermissionDenied\", command, messageOf(cause), cause)\n })\n let fd = 3\n while (command.options.additionalFds?.[`fd${fd}`] !== undefined) fd++\n // A regular file avoids a filter-input pipe whose early closure can\n // surface as an unhandled ECONNRESET before bwrap reports its refusal.\n args = [\n \"-c\",\n `exec ${fd}<\"$1\"; shift; exec \"$@\"`,\n \"smithers-seccomp\",\n filter,\n executable!,\n \"--seccomp\",\n String(fd),\n ...args\n ]\n executable = \"/bin/sh\"\n }\n return ChildProcess.make(executable!, args, {\n ...command.options,\n cwd: canonical.cwd,\n shell: false,\n env: { PATH: \"/usr/bin:/bin:/usr/sbin:/sbin\", LANG: \"C\", ...privateEnvironment },\n extendEnv: false\n })\n })\n return KernelProcessConfinement.ProcessConfinement.of({ confine })\n}\n\n/**\n * Provides the native confinement.\n *\n * @category layers\n * @since 1.0.0-rc.1\n */\nexport const layer = (options: Options = {}): Layer.Layer<KernelProcessConfinement.ProcessConfinement> =>\n Layer.succeed(KernelProcessConfinement.ProcessConfinement)(make(options))\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -128,6 +128,12 @@ export interface Host {
128
128
  * paths. Read aliases are only collected when this probe is supplied.
129
129
  */
130
130
  readonly realpath?: ((path: string) => string | undefined) | undefined;
131
+ /**
132
+ * The program a package-manager shim script runs: the absolute path on the
133
+ * `# cmd-shim-target=` line pnpm's cmd-shim writes, or `undefined` for any
134
+ * other file. Optional: a host without it treats a shim as the program.
135
+ */
136
+ readonly shimTarget?: ((path: string) => string | undefined) | undefined;
131
137
  readonly uid: number | undefined;
132
138
  readonly gid: number | undefined;
133
139
  }
@@ -293,8 +299,6 @@ export declare const environment: (confinement: Plan, hostEnv?: Readonly<Record<
293
299
  /**
294
300
  * The program a confined run execs, made reachable inside its empty root.
295
301
  *
296
- * @internal
297
- *
298
302
  * Bubblewrap resolves a bare program name with `execvp` against `PATH` inside
299
303
  * the new root, and that root holds only the runtime paths and the declared
300
304
  * sets. A package manager installed outside them — pnpm under the
@@ -311,6 +315,16 @@ export declare const environment: (confinement: Plan, hostEnv?: Readonly<Record<
311
315
  * is bound read-only, because a script like `pnpm.cjs` loads its siblings.
312
316
  * With no package directory only the real file is bound. A name that resolves
313
317
  * nowhere is left for `execvp` to report.
318
+ *
319
+ * A package-manager shim script is followed like a link. `pnpm self-update`
320
+ * under `pnpm/action-setup` installs pnpm as a cmd-shim in `$PNPM_HOME/bin`
321
+ * that runs node on a package in pnpm's global store, a path relative to the
322
+ * script; binding the script alone left that package missing. When the
323
+ * program the shim names is executable, the run execs its real file and binds
324
+ * its package as above.
325
+ *
326
+ * @since 1.0.0
327
+ * @private
314
328
  */
315
329
  export declare const launcher: (program: string, searchPath: string | undefined, granted: ReadonlyArray<string>, workspaceRoot: string, hostFacts: Host) => {
316
330
  readonly program: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ProcessSandbox.d.ts","sourceRoot":"","sources":["../../src/ProcessSandbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ProcessSandbox.d.ts","sourceRoot":"","sources":["../../src/ProcessSandbox.ts"],"names":[],"mappings":"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"}
@@ -106,10 +106,23 @@ const host = (env = ambientEnvironment()) => {
106
106
  return void 0;
107
107
  }
108
108
  },
109
+ shimTarget,
109
110
  uid: typeof process.getuid === "function" ? process.getuid() : void 0,
110
111
  gid: typeof process.getgid === "function" ? process.getgid() : void 0
111
112
  };
112
113
  };
114
+ const shimLimit = 64 * 1024;
115
+ const shimTarget = (path) => {
116
+ try {
117
+ if (NodeFs.statSync(path).size > shimLimit) return void 0;
118
+ const text = NodeFs.readFileSync(path, "utf8");
119
+ if (!text.startsWith("#!")) return void 0;
120
+ const target = /^# cmd-shim-target=(.+)$/m.exec(text)?.[1];
121
+ return target !== void 0 && NodePath.isAbsolute(target) ? target : void 0;
122
+ } catch {
123
+ return void 0;
124
+ }
125
+ };
113
126
  const isExecutable = (path) => {
114
127
  try {
115
128
  NodeFs.accessSync(path, NodeFs.constants.X_OK);
@@ -460,8 +473,10 @@ const launcher = (program, searchPath, granted, workspaceRoot, hostFacts) => {
460
473
  if (program.includes("/") && !NodePath.isAbsolute(program)) return unchanged;
461
474
  const found = NodePath.isAbsolute(program) ? hostFacts.executable(program) : searchPath === void 0 ? hostFacts.executable(program) : searchPath.split(":").filter((entry) => NodePath.isAbsolute(entry)).map((entry) => hostFacts.executable(NodePath.join(entry, program))).find((candidate) => candidate !== void 0);
462
475
  if (found === void 0 || granted.some((parent) => insideRoot(parent, found))) return unchanged;
463
- const real = hostFacts.realpath?.(found) ?? found;
464
- if (insideRoot(workspaceRoot, found) || insideRoot(workspaceRoot, real)) return unchanged;
476
+ const resolved = hostFacts.realpath?.(found) ?? found;
477
+ const named = hostFacts.shimTarget?.(resolved);
478
+ const real = named === void 0 || hostFacts.executable(named) === void 0 ? resolved : hostFacts.realpath?.(named) ?? named;
479
+ if ([found, resolved, real].some((path) => insideRoot(workspaceRoot, path))) return unchanged;
465
480
  if (granted.some((parent) => insideRoot(parent, real))) return { program: real, reads: [] };
466
481
  let directory = NodePath.dirname(real);
467
482
  for (let level = 0; level < 3; level++) {