Files
AIPass/src/aipass/hooks/apps/modules/_srt_resolve.mjs
T
AIOSAIandClaude Opus 4.8 0b4ba63fae feat(sandbox): kernel filesystem boundary for agent containment (DPLAN-0202/FPLAN-0250)
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>
2026-06-10 13:16:22 -07:00

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);
}