@sellable/install
Version:
One-command installer for Sellable MCP in Claude Code, Codex, and Hermes
473 lines (459 loc) • 15.3 kB
JavaScript
import {
chmodSync,
existsSync,
lstatSync,
mkdirSync,
readFileSync,
realpathSync,
writeFileSync,
} from "node:fs";
import { isAbsolute, join, relative, resolve } from "node:path";
import { runBoundedChildProcess } from "./provisioning-adapter.mjs";
const INPUT_KEYS = new Set([
"profileId",
"workerUid",
"runtimeUid",
"credentialReferences",
"oauthPrivateReference",
]);
const SAFE_ID = /^[A-Za-z0-9_-]{1,128}$/;
const FINGERPRINT = /^[a-f0-9]{64}$/;
const EXACT_EGRESS = [
"https://app.sellable.dev",
"https://slack.com",
"https://api.openai.com",
];
export const PINNED_CONTAINMENT_IMAGE =
"public.ecr.aws/supabase/postgres@sha256:af083ef64d0408c8f098ee6f5c364a59b26f36fbc0f3a334a62c5c1d57362e9b";
const CONTAINER_CHECK_KEYS = [
"runtimeUid",
"profileRead",
"controlDenied",
"credentialDenied",
"oauthDenied",
"siblingDenied",
"hostDenied",
"dockerDenied",
"rootReadOnly",
"noNewPrivileges",
"capabilitiesDropped",
"networkDisabled",
];
function validPrivateReference(value, scheme) {
return (
value &&
typeof value === "object" &&
!Array.isArray(value) &&
Object.keys(value).every((key) =>
["reference", "fingerprint", "purpose", "target", "owner"].includes(key)
) &&
typeof value.reference === "string" &&
value.reference.startsWith(`${scheme}://`) &&
FINGERPRINT.test(value.fingerprint)
);
}
export function buildContainmentContract(input) {
if (!input || typeof input !== "object" || Array.isArray(input)) {
return { ok: false, code: "invalid_input" };
}
if (Object.keys(input).some((key) => !INPUT_KEYS.has(key))) {
return { ok: false, code: "unknown_field" };
}
if (
!SAFE_ID.test(input.profileId) ||
!Number.isSafeInteger(input.workerUid) ||
input.workerUid < 1 ||
!Number.isSafeInteger(input.runtimeUid) ||
input.runtimeUid < 1 ||
input.workerUid === input.runtimeUid ||
!Array.isArray(input.credentialReferences) ||
!input.credentialReferences.every(
(reference) =>
validPrivateReference(reference, "secret") &&
["service-credential", "worker-credential"].includes(reference.purpose)
) ||
!validPrivateReference(input.oauthPrivateReference, "oauth-private")
) {
return { ok: false, code: "invalid_input" };
}
const profileBase = `/var/lib/sellable-agents/${input.profileId}`;
const manifest = {
profileId: input.profileId,
readOnlyRootFilesystem: true,
noNewPrivileges: true,
dockerSocket: false,
capabilities: [],
worker: {
name: `sellable-worker-${input.profileId}`,
uid: input.workerUid,
},
runtime: {
name: `sellable-runtime-${input.profileId}`,
uid: input.runtimeUid,
},
mounts: [
{
profileId: input.profileId,
source: `${profileBase}/control`,
target: "/control",
readOnly: false,
owner: "worker",
},
{
profileId: input.profileId,
source: `${profileBase}/profile`,
target: "/profile",
readOnly: false,
owner: "runtime",
},
],
credentials: input.credentialReferences.map((reference) => ({
purpose: reference.purpose,
reference: reference.reference,
fingerprint: reference.fingerprint,
target: `/run/credentials/${reference.purpose}`,
owner: "worker",
})),
oauthPrivateReference: {
reference: input.oauthPrivateReference.reference,
fingerprint: input.oauthPrivateReference.fingerprint,
owner: "worker",
},
oauth: {
privateExchangeOwner: "worker",
healthStatus: "NOT_PROBED",
auditStatus: "REQUIRED",
broaderRolloutBlocked: true,
},
authority: {
database: false,
migrations: false,
hostControl: false,
},
resources: { pids: 128, memoryMb: 1024, cpuQuota: 1 },
egress: [...EXACT_EGRESS],
};
const validated = validateContainmentContract(manifest);
return validated.ok ? { ok: true, manifest } : validated;
}
export function validateContainmentContract(manifest) {
if (
!manifest ||
typeof manifest !== "object" ||
!SAFE_ID.test(manifest.profileId)
) {
return { ok: false, code: "invalid_manifest" };
}
if (
manifest.readOnlyRootFilesystem !== true ||
manifest.noNewPrivileges !== true ||
manifest.dockerSocket !== false ||
!Array.isArray(manifest.capabilities) ||
manifest.capabilities.length !== 0
) {
return { ok: false, code: "privilege_boundary_failed" };
}
if (
!Number.isSafeInteger(manifest.worker?.uid) ||
manifest.worker.uid < 1 ||
!Number.isSafeInteger(manifest.runtime?.uid) ||
manifest.runtime.uid < 1 ||
manifest.worker.uid === manifest.runtime.uid
) {
return { ok: false, code: "identity_boundary_failed" };
}
const profileBase = `/var/lib/sellable-agents/${manifest.profileId}/`;
if (
!Array.isArray(manifest.mounts) ||
manifest.mounts.length !== 2 ||
manifest.mounts.some(
(mount) =>
mount.profileId !== manifest.profileId ||
typeof mount.source !== "string" ||
!mount.source.startsWith(profileBase) ||
!["/control", "/profile"].includes(mount.target) ||
!["worker", "runtime"].includes(mount.owner) ||
mount.source.includes("docker.sock")
) ||
manifest.mounts.find((mount) => mount.target === "/control")?.owner !==
"worker" ||
manifest.mounts.find((mount) => mount.target === "/profile")?.owner !==
"runtime"
) {
return { ok: false, code: "mount_boundary_failed" };
}
if (
!Array.isArray(manifest.credentials) ||
!manifest.credentials.every(
(reference) =>
validPrivateReference(reference, "secret") &&
typeof reference.target === "string" &&
reference.target.startsWith("/run/credentials/") &&
reference.owner === "worker"
) ||
!validPrivateReference(manifest.oauthPrivateReference, "oauth-private") ||
manifest.oauthPrivateReference.owner !== "worker"
) {
return { ok: false, code: "secret_boundary_failed" };
}
if (
manifest.oauth?.privateExchangeOwner !== "worker" ||
manifest.oauth?.healthStatus !== "NOT_PROBED" ||
manifest.oauth?.auditStatus !== "REQUIRED" ||
manifest.oauth?.broaderRolloutBlocked !== true
) {
return { ok: false, code: "oauth_readiness_boundary_failed" };
}
if (
manifest.authority?.database !== false ||
manifest.authority?.migrations !== false ||
manifest.authority?.hostControl !== false
) {
return { ok: false, code: "authority_boundary_failed" };
}
if (
manifest.resources?.pids !== 128 ||
manifest.resources?.memoryMb !== 1024 ||
manifest.resources?.cpuQuota !== 1 ||
JSON.stringify(manifest.egress) !== JSON.stringify(EXACT_EGRESS)
) {
return { ok: false, code: "resource_or_egress_boundary_failed" };
}
if (
/xox[bap]-|authorizationCode|authorization_code|accessToken|refreshToken/.test(
JSON.stringify(manifest)
)
) {
return { ok: false, code: "raw_secret_material" };
}
return { ok: true, code: "contained" };
}
export function isContainmentEgressAllowed(manifest, value) {
if (!validateContainmentContract(manifest).ok) return false;
try {
const url = new URL(value);
if (url.protocol !== "https:" || url.username || url.password) return false;
return manifest.egress.includes(url.origin);
} catch {
return false;
}
}
function containedRelative(root, target) {
const rel = relative(root, target);
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
}
export function materializeContainmentProfile(manifest, { root }) {
if (!validateContainmentContract(manifest).ok) {
return { ok: false, code: "invalid_manifest" };
}
try {
if (!isAbsolute(root) || !existsSync(root) || lstatSync(root).isSymbolicLink()) {
return { ok: false, code: "invalid_root" };
}
const realRoot = realpathSync(root);
const profileRoot = join(realRoot, manifest.profileId);
if (!containedRelative(realRoot, profileRoot)) {
return { ok: false, code: "path_confinement_failed" };
}
mkdirSync(join(profileRoot, "control"), { recursive: true, mode: 0o700 });
mkdirSync(join(profileRoot, "profile"), { recursive: true, mode: 0o750 });
mkdirSync(join(profileRoot, "credentials"), { recursive: true, mode: 0o700 });
writeFileSync(join(profileRoot, "profile", "probe.txt"), "sellable-agent-contained\n", {
mode: 0o444,
});
chmodSync(join(profileRoot, "profile", "probe.txt"), 0o444);
writeFileSync(
join(profileRoot, "containment.json"),
`${JSON.stringify(manifest, null, 2)}\n`,
{ mode: 0o600 }
);
return { ok: true, profileRoot };
} catch {
return { ok: false, code: "materialization_failed" };
}
}
export function buildContainerContainmentProbeSpec(
manifest,
{ root, runtimeUid, runtimeGid }
) {
const validation = validateContainmentContract(manifest);
if (!validation.ok) return { ok: false, code: validation.code };
try {
if (
!Number.isSafeInteger(runtimeUid) ||
runtimeUid < 1 ||
!Number.isSafeInteger(runtimeGid) ||
runtimeGid < 1 ||
!isAbsolute(root) ||
String(root).includes(",") ||
String(root).includes("\n")
) {
return { ok: false, code: "invalid_probe_runtime" };
}
const realRoot = realpathSync(root);
const materializedRoot = realpathSync(join(realRoot, manifest.profileId));
const profileData = realpathSync(join(materializedRoot, "profile"));
if (
!containedRelative(realRoot, materializedRoot) ||
!containedRelative(materializedRoot, profileData) ||
lstatSync(profileData).isSymbolicLink() ||
readFileSync(join(profileData, "probe.txt"), "utf8") !==
"sellable-agent-contained\n"
) {
return { ok: false, code: "invalid_materialized_profile" };
}
const script = [
`test "$(id -u)" = "${runtimeUid}"`,
'test "$(cat /profile/probe.txt)" = "sellable-agent-contained"',
'test ! -r /control/probe.txt',
'test ! -r /run/credentials/service-credential',
'test ! -r /run/credentials/oauth-private',
'test ! -r /siblings/profile-2/probe.txt',
'test ! -r /host/probe.txt',
'test ! -S /var/run/docker.sock',
'if touch /sellable-root-write-probe 2>/dev/null; then exit 31; fi',
"grep -Eq '^NoNewPrivs:[[:space:]]+1$' /proc/self/status",
"grep -Eq '^CapEff:[[:space:]]+0+$' /proc/self/status",
"test ! -e /sys/class/net/eth0",
`printf '%s\\n' '${JSON.stringify({
ok: true,
checks: Object.fromEntries(CONTAINER_CHECK_KEYS.map((key) => [key, true])),
})}'`,
].join("\n");
const args = [
"run",
"--rm",
"--label",
"sellable.containment.probe=1",
"--pull",
"never",
"--network",
"none",
"--read-only",
"--cap-drop",
"ALL",
"--security-opt",
"no-new-privileges",
"--pids-limit",
"128",
"--memory",
"1024m",
"--cpus",
"1",
"--user",
`${runtimeUid}:${runtimeGid}`,
"--tmpfs",
"/tmp:rw,noexec,nosuid,nodev,size=16m,mode=1777",
"--mount",
`type=bind,src=${profileData},dst=/profile,readonly`,
PINNED_CONTAINMENT_IMAGE,
"sh",
"-ceu",
script,
];
return {
ok: true,
command: "docker",
image: PINNED_CONTAINMENT_IMAGE,
args,
shell: false,
timeoutMs: 30_000,
maxOutputBytes: 8 * 1024,
};
} catch {
return { ok: false, code: "invalid_materialized_profile" };
}
}
export async function runContainerContainmentProbe(manifest, runtime) {
const spec = buildContainerContainmentProbeSpec(manifest, runtime);
if (!spec.ok) return { ...spec, checks: {} };
const output = await runBoundedChildProcess(spec);
if (
output.exitCode !== 0 ||
output.timedOut ||
output.outputLimitExceeded ||
output.terminated
) {
return { ok: false, code: "container_probe_failed", checks: {} };
}
try {
const parsed = JSON.parse(output.stdout);
if (
!parsed ||
parsed.ok !== true ||
Object.keys(parsed).sort().join("\0") !== ["checks", "ok"].sort().join("\0") ||
Object.keys(parsed.checks).sort().join("\0") !==
[...CONTAINER_CHECK_KEYS].sort().join("\0") ||
CONTAINER_CHECK_KEYS.some((key) => parsed.checks[key] !== true)
) {
throw new Error("invalid probe result");
}
return { ok: true, code: "contained", checks: parsed.checks };
} catch {
return { ok: false, code: "container_probe_failed", checks: {} };
}
}
function identityCanAccess(manifest, identity, target) {
if (identity !== "worker" && identity !== "runtime") return false;
if (target === "/") return false;
if (target === "/var/run/docker.sock") return false;
if (target.startsWith("/run/credentials/")) return identity === "worker";
const mount = manifest.mounts.find(
(candidate) => target === candidate.target || target.startsWith(`${candidate.target}/`)
);
return Boolean(mount && mount.owner === identity);
}
export function probeContainmentProfile(manifest, { root }) {
const validation = validateContainmentContract(manifest);
if (!validation.ok) return { ok: false, code: validation.code, checks: {} };
try {
const realRoot = realpathSync(root);
const profileRoot = realpathSync(join(realRoot, manifest.profileId));
const materializedManifest = JSON.parse(
readFileSync(join(profileRoot, "containment.json"), "utf8")
);
if (JSON.stringify(materializedManifest) !== JSON.stringify(manifest)) {
return { ok: false, code: "materialized_manifest_mismatch", checks: {} };
}
const checks = {
runtimeProfile: identityCanAccess(manifest, "runtime", "/profile"),
runtimeControlDenied: !identityCanAccess(manifest, "runtime", "/control"),
runtimeCredentialDenied: !identityCanAccess(
manifest,
"runtime",
"/run/credentials/service-credential"
),
runtimeOauthDenied: !identityCanAccess(
manifest,
"runtime",
"/run/credentials/oauth-private"
),
siblingDenied: !identityCanAccess(manifest, "runtime", "/siblings/profile-2"),
rootDenied: !identityCanAccess(manifest, "runtime", "/"),
dockerDenied: !identityCanAccess(manifest, "runtime", "/var/run/docker.sock"),
databaseDenied: manifest.authority.database === false,
migrationDenied: manifest.authority.migrations === false,
sellableAllowed: isContainmentEgressAllowed(
manifest,
"https://app.sellable.dev/api/v3/workspaces"
),
slackAllowed: isContainmentEgressAllowed(
manifest,
"https://slack.com/api/auth.test"
),
modelAllowed: isContainmentEgressAllowed(
manifest,
"https://api.openai.com/v1/responses"
),
extraEndpointDenied: !isContainmentEgressAllowed(
manifest,
"https://evil.example/collect"
),
};
return Object.values(checks).every(Boolean)
? { ok: true, code: "contained", checks }
: { ok: false, code: "probe_failed", checks };
} catch {
return { ok: false, code: "probe_failed", checks: {} };
}
}