agent.libx.js 0.94.12 → 0.94.13

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
@@ -1387,6 +1387,58 @@ var init_JailedFilesystem = __esm({
1387
1387
  }
1388
1388
  });
1389
1389
 
1390
+ // src/shell.sandbox.ts
1391
+ function writable(cwd, o, tmpDir) {
1392
+ const set = /* @__PURE__ */ new Set([cwd, "/tmp", "/private/tmp", "/private/var/folders", "/dev", ...tmpDir ? [tmpDir] : [], ...o.writePaths]);
1393
+ return [...set];
1394
+ }
1395
+ function seatbeltProfile(cwd, o, tmpDir) {
1396
+ const allows = writable(cwd, o, tmpDir).map((p) => `(subpath ${sbQuote(p)})`).join(" ");
1397
+ return [
1398
+ "(version 1)",
1399
+ "(allow default)",
1400
+ ...o.network ? [] : ["(deny network*)"],
1401
+ "(deny file-write*)",
1402
+ `(allow file-write* ${allows})`
1403
+ ].join("\n");
1404
+ }
1405
+ function sandboxArgv(command, cwd, opts = {}, platform = process.platform, tmpDir) {
1406
+ const o = { ...new OsSandboxOptions(), ...opts };
1407
+ if (platform === "darwin") {
1408
+ return { bin: "/usr/bin/sandbox-exec", args: ["-p", seatbeltProfile(cwd, o, tmpDir), "/bin/sh", "-c", command] };
1409
+ }
1410
+ if (platform === "linux") {
1411
+ const binds = writable(cwd, o, tmpDir).filter((p) => p !== "/dev" && !p.startsWith("/private")).flatMap((p) => ["--bind-try", p, p]);
1412
+ return {
1413
+ bin: "bwrap",
1414
+ args: ["--ro-bind", "/", "/", ...binds, "--dev", "/dev", "--proc", "/proc", "--die-with-parent", ...o.network ? [] : ["--unshare-net"], "/bin/sh", "-c", command]
1415
+ };
1416
+ }
1417
+ return null;
1418
+ }
1419
+ async function findSandboxWrapper(platform = process.platform) {
1420
+ const { existsSync } = await import("fs");
1421
+ if (platform === "darwin") return existsSync("/usr/bin/sandbox-exec") ? "/usr/bin/sandbox-exec" : null;
1422
+ if (platform === "linux") {
1423
+ for (const dir of (process.env.PATH ?? "/usr/bin:/bin").split(":")) if (dir && existsSync(`${dir}/bwrap`)) return `${dir}/bwrap`;
1424
+ return null;
1425
+ }
1426
+ return null;
1427
+ }
1428
+ var OsSandboxOptions, sbQuote;
1429
+ var init_shell_sandbox = __esm({
1430
+ "src/shell.sandbox.ts"() {
1431
+ "use strict";
1432
+ OsSandboxOptions = class {
1433
+ /** Allow outbound network. Default OFF (Tier-1: no network unless granted). */
1434
+ network = false;
1435
+ /** Extra absolute paths writable beyond cwd + tmp (e.g. a build cache). */
1436
+ writePaths = [];
1437
+ };
1438
+ sbQuote = (p) => `"${p.replace(/(["\\])/g, "\\$1")}"`;
1439
+ }
1440
+ });
1441
+
1390
1442
  // src/tools.shell.ts
1391
1443
  var tools_shell_exports = {};
1392
1444
  __export(tools_shell_exports, {
@@ -1394,6 +1446,14 @@ __export(tools_shell_exports, {
1394
1446
  makeRealShellTool: () => makeRealShellTool,
1395
1447
  makeShellJobTools: () => makeShellJobTools
1396
1448
  });
1449
+ async function spawnArgvFor(command, cwd, osSandbox) {
1450
+ if (!osSandbox) return { bin: "/bin/sh", args: ["-c", command] };
1451
+ const opts = osSandbox === true ? {} : osSandbox;
1452
+ const wrapper = await findSandboxWrapper();
1453
+ const wrapped = wrapper ? sandboxArgv(command, cwd, opts, process.platform, process.env.TMPDIR) : null;
1454
+ if (!wrapped) throw new Error(`OS sandbox requested but no wrapper available on ${process.platform} (need sandbox-exec or bwrap)`);
1455
+ return wrapped;
1456
+ }
1397
1457
  function childEnv(opts) {
1398
1458
  const base = {};
1399
1459
  const redact = opts.redactEnv !== false;
@@ -1426,6 +1486,14 @@ function makeRealShellTool(options) {
1426
1486
  return `Started background job ${id}. Poll output with ShellOutput({id:"${id}"}), check ShellStatus({id:"${id}"}), stop with ShellKill({id:"${id}"}).`;
1427
1487
  }
1428
1488
  const spawn = options.spawn ?? await nodeSpawn();
1489
+ let argv = { bin: "/bin/sh", args: ["-c", cmd] };
1490
+ if (options.osSandbox) {
1491
+ try {
1492
+ argv = await spawnArgvFor(cmd, options.cwd, options.osSandbox);
1493
+ } catch (e) {
1494
+ return `[exit 1] ${e?.message ?? e}`;
1495
+ }
1496
+ }
1429
1497
  const ctl = new AbortController();
1430
1498
  const onAbort = () => ctl.abort();
1431
1499
  if (ctx.signal) {
@@ -1460,7 +1528,7 @@ function makeRealShellTool(options) {
1460
1528
  };
1461
1529
  let proc;
1462
1530
  try {
1463
- proc = spawn("/bin/sh", ["-c", cmd], { cwd: options.cwd, env: childEnv(options), signal: ctl.signal });
1531
+ proc = spawn(argv.bin, argv.args, { cwd: options.cwd, env: childEnv(options), signal: ctl.signal });
1464
1532
  } catch (e) {
1465
1533
  return finish(`[exit 1] failed to spawn shell: ${e?.message ?? e}`);
1466
1534
  }
@@ -1546,6 +1614,7 @@ var init_tools_shell = __esm({
1546
1614
  init_tools();
1547
1615
  init_redact();
1548
1616
  init_logging();
1617
+ init_shell_sandbox();
1549
1618
  log4 = forComponent("shell");
1550
1619
  clean = (s) => truncateOutput(redactSecrets(s.replace(/\n+$/, "")));
1551
1620
  SECRET_ENV_RE = /(_API_KEY|_TOKEN|_SECRET|_PASSWORD|_PRIVATE_KEY|^AWS_|^GITHUB_TOKEN$|^OPENAI_|^ANTHROPIC_|^GOOGLE_|^GEMINI_|^GROQ_|^NPM_TOKEN$)/i;
@@ -1567,7 +1636,8 @@ var init_tools_shell = __esm({
1567
1636
  };
1568
1637
  try {
1569
1638
  const spawn = this.cfg.spawn ?? await nodeSpawn();
1570
- const proc = spawn("/bin/sh", ["-c", command], { cwd: this.cfg.cwd, env: childEnv(this.cfg) });
1639
+ const argv = this.cfg.osSandbox ? await spawnArgvFor(command, this.cfg.cwd, this.cfg.osSandbox) : { bin: "/bin/sh", args: ["-c", command] };
1640
+ const proc = spawn(argv.bin, argv.args, { cwd: this.cfg.cwd, env: childEnv(this.cfg) });
1571
1641
  job.proc = proc;
1572
1642
  proc.stdout?.on("data", append);
1573
1643
  proc.stderr?.on("data", append);