Every autonomous agent can launch inside a kernel-enforced mount namespace (srt -> bwrap+seccomp): reads stay open (shared live FS preserved, bind-mount not isolation; own-tree writes land live), but rm/python/find/Write on .git or sibling trees hit EROFS. /tmp + own tree writable; .git RW devpulse, RO builders. Inert by default behind AIPASS_SANDBOX_ENABLED (off); flag-off path byte-identical to old. hooks: srt wrapper + per-role build_policy + broker_secret mask; rm_gate demoted. drone: out-of-sandbox broker (identity allowlist, openat2 RESOLVE_BENEATH, HMAC handshake over inherited fd, audit); drone rm via broker when sandboxed. ai_mail: dispatch gate + broker-fd wiring (fail-loud exit -4, never silent). aipass: doctor Sandbox group + setup.sh prereqs (LOUD on missing). Proven by a live 16-check red-team suite. seedgo 100% + 2859 tests green across all 5 touched branches. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
35 lines
1.3 KiB
JavaScript
35 lines
1.3 KiB
JavaScript
// _srt_resolve.mjs — Resolves bwrap command via @anthropic-ai/sandbox-runtime library.
|
|
// Called by sandbox.py. Reads config JSON from file (argv[1]), command string (argv[2]).
|
|
// Prints the shell-quoted bwrap command to stdout. Exits 0 on success, 1 on error.
|
|
//
|
|
// srt is installed globally (npm i -g). ESM resolution walks up from this file's
|
|
// directory, never reaching the global node_modules. We derive the path from the
|
|
// running Node binary instead.
|
|
|
|
import { readFileSync } from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { pathToFileURL } from 'node:url';
|
|
|
|
const nodePrefix = dirname(dirname(process.execPath));
|
|
const srtEntry = join(nodePrefix, 'lib/node_modules/@anthropic-ai/sandbox-runtime/dist/index.js');
|
|
const { SandboxManager } = await import(pathToFileURL(srtEntry).href);
|
|
|
|
const configPath = process.argv[2];
|
|
const command = process.argv[3];
|
|
|
|
if (!configPath || !command) {
|
|
process.stderr.write('usage: _srt_resolve.mjs <config.json> <command>\n');
|
|
process.exit(1);
|
|
}
|
|
|
|
try {
|
|
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
await SandboxManager.initialize(config);
|
|
const wrapped = await SandboxManager.wrapWithSandbox(command, '/bin/bash', config);
|
|
process.stdout.write(wrapped);
|
|
await SandboxManager.reset();
|
|
} catch (err) {
|
|
process.stderr.write(`srt-resolve error: ${err.message}\n`);
|
|
process.exit(1);
|
|
}
|