import { assert, assertEquals, assertNotEquals } from "jsr:@std/assert@1"; import { prepareRuntime } from "./runtime.ts"; const MASTER_KEY = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8"; const ENCRYPTED = "v1:ICEiIyQlJicoKSor:oV_FAgnsN3p1FyegJxwGVdyjfyPio6qDeSUwbA"; Deno.test({ name: "prepares root-only reviewer and isolated profile credentials", permissions: { read: true, write: true, run: true, sys: ["uid"] }, async fn() { if (Deno.uid() !== 0) return; const root = await Deno.makeTempDir(); await Deno.chmod(root, 0o711); const action = await Deno.makeTempDir(); try { await Deno.writeTextFile( `${action}/profiles.yml`, `reviewer-token: ${ENCRYPTED}\nprofiles:\n - type: claude\n token: ${ENCRYPTED}\n - type: codex\n`, ); const manifest = await prepareRuntime(action, root, MASTER_KEY); const serialized = await Deno.readTextFile(manifest.manifestPath); assert(!serialized.includes("secret-token")); assertEquals( await Deno.readTextFile(manifest.reviewerFile), "secret-token", ); assertEquals( (await Deno.stat(manifest.reviewerFile)).mode! & 0o777, 0o600, ); assertEquals((await Deno.stat(manifest.reviewerFile)).uid, 0); const [claude, codex] = manifest.profiles; assertNotEquals(claude.uid, codex.uid); assertEquals((await Deno.stat(claude.home)).uid, claude.uid); assertEquals((await Deno.stat(claude.home)).mode! & 0o777, 0o700); assert(claude.tokenFile !== null); assertEquals(await Deno.readTextFile(claude.tokenFile), "secret-token"); assertEquals((await Deno.stat(claude.tokenFile)).uid, claude.uid); assertEquals((await Deno.stat(claude.tokenFile)).mode! & 0o777, 0o600); assertEquals((await Deno.stat(codex.home)).uid, codex.uid); assertEquals(codex.tokenFile, null); const ownToken = await new Deno.Command("/bin/cat", { args: [claude.tokenFile], cwd: "/", uid: claude.uid, gid: claude.gid, }).output(); assertEquals(ownToken.success, true); assertEquals(new TextDecoder().decode(ownToken.stdout), "secret-token"); const reviewerToken = await new Deno.Command("/bin/cat", { args: [manifest.reviewerFile], cwd: "/", uid: claude.uid, gid: claude.gid, }).output(); assertEquals(reviewerToken.success, false); const siblingHome = await new Deno.Command("/bin/ls", { args: [codex.home], cwd: "/", uid: claude.uid, gid: claude.gid, }).output(); assertEquals(siblingHome.success, false); } finally { await Deno.remove(root, { recursive: true }); await Deno.remove(action, { recursive: true }); } }, }); Deno.test({ name: "removes prepared credentials when output publication fails", permissions: "inherit", async fn() { if (Deno.uid() !== 0) return; const root = await Deno.makeTempDir(); const action = await Deno.makeTempDir(); try { await Deno.writeTextFile( `${action}/profiles.yml`, `reviewer-token: ${ENCRYPTED}\nprofiles:\n - type: claude\n token: ${ENCRYPTED}\n`, ); const result = await new Deno.Command(Deno.execPath(), { args: ["run", "-A", new URL("./prepare.ts", import.meta.url).pathname], env: { ACTION_PATH: action, RUNNER_TEMP: root, BOT_AGENTS_MASTER_KEY: MASTER_KEY, GITHUB_OUTPUT: action, }, clearEnv: true, }).output(); assertEquals(result.success, false); const entries = []; for await (const entry of Deno.readDir(root)) entries.push(entry.name); assertEquals(entries, []); } finally { await Deno.remove(root, { recursive: true }); await Deno.remove(action, { recursive: true }); } }, });