Centralize encrypted bot profiles
Check / deno (pull_request) Successful in 36s

This commit is contained in:
Danny Kim
2026-09-24 04:56:11 +09:00
parent ba9e0c0787
commit 7bae0d7237
22 changed files with 1993 additions and 526 deletions
+108
View File
@@ -0,0 +1,108 @@
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 });
}
},
});