← Files OpsTruthARCHIVED FILE

test/github-verification-auth.test.js

8.45 KB · Oct 2, 2026 · 00:31 UTC

↓ Download file

import assert from "node:assert/strict";
import { generateKeyPairSync } from "node:crypto";
import test from "node:test";
import { loadCommitVerificationEvidence } from "../src/github.js";

const BASE = "1".repeat(40);
const HEAD = "2".repeat(40);
const CONTENT = "# selected verification evidence";
const githubAppPrivateKey = generateKeyPairSync("rsa", { modulusLength: 2048 }).privateKey;

function appEnv(overrides = {}) {
  return {
    OPSTRUTH_GITHUB_APP_ID: "123456",
    OPSTRUTH_GITHUB_APP_INSTALLATION_ID: "987654",
    OPSTRUTH_GITHUB_APP_PRIVATE_KEY_PEM: githubAppPrivateKey.export({ type: "pkcs8", format: "pem" }).toString(),
    OPSTRUTH_GITHUB_APP_ALLOWED_REPOSITORY: "Example/project",
    OPSTRUTH_GITHUB_APP_ALLOWED_REPOSITORY_ID: "424242",
    ...overrides,
  };
}

function installVerificationFetch(options = {}) {
  const original = globalThis.fetch;
  const observations = { apiAuthorizations: [], rawRequests: 0, tokenMints: 0, tokenBody: null };
  globalThis.fetch = async (request) => {
    const url = new URL(typeof request === "string" ? request : request.url);
    if (url.hostname === "raw.githubusercontent.com") {
      observations.rawRequests += 1;
      return new Response("anonymous raw access is prohibited", { status: 500 });
    }
    if (url.hostname !== "api.github.com") return new Response("unexpected host", { status: 500 });
    if (url.pathname === "/app/installations/987654/access_tokens") {
      observations.tokenMints += 1;
      observations.tokenBody = await request.json();
      return Response.json({
        token: "installation-token-sentinel",
        expires_at: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
        permissions: { checks: "read", contents: "read", metadata: "read", statuses: "read" },
        repository_selection: "selected",
        repositories: [{ id: 424242, full_name: "Example/project", private: false, visibility: "public" }],
      });
    }
    observations.apiAuthorizations.push(request.headers.get("authorization"));
    if (url.pathname === "/repos/Example/project") {
      return Response.json({
        id: 424242,
        full_name: "Example/project",
        html_url: "https://github.com/Example/project",
        visibility: "public",
        private: false,
        ...options.metadata,
      });
    }
    if (url.pathname === `/repos/Example/project/commits/${HEAD}`) {
      return Response.json({ sha: HEAD, html_url: `https://github.com/Example/project/commit/${HEAD}` });
    }
    if (url.pathname === `/repos/Example/project/git/trees/${HEAD}`) {
      return Response.json({ sha: "tree", truncated: false, tree: [{ path: "README.md", type: "blob", size: Buffer.byteLength(CONTENT), sha: "readme-sha" }] });
    }
    if (url.pathname === `/repos/Example/project/compare/${BASE}...${HEAD}`) {
      return Response.json({ status: "ahead", ahead_by: 1, behind_by: 0, files: [{ filename: "README.md", status: "modified" }] });
    }
    if (url.pathname === `/repos/Example/project/commits/${HEAD}/check-runs`) {
      if (options.checksResponse) return options.checksResponse();
      return Response.json({ total_count: 1, check_runs: [{ name: "CI", status: "completed", conclusion: "success" }] });
    }
    if (url.pathname === `/repos/Example/project/commits/${HEAD}/status`) {
      return Response.json({ state: "success", statuses: [{ context: "CI", state: "success" }] });
    }
    if (url.pathname === "/repos/Example/project/contents/README.md") {
      assert.equal(url.searchParams.get("ref"), HEAD);
      return Response.json(options.contentPayload || {
        type: "file",
        path: "README.md",
        sha: "readme-sha",
        size: Buffer.byteLength(CONTENT),
        encoding: "base64",
        content: Buffer.from(CONTENT).toString("base64"),
      });
    }
    return new Response("unexpected path", { status: 500 });
  };
  return { observations, restore: () => { globalThis.fetch = original; } };
}

function rejectVerificationCacheAccess() {
  const previous = Object.getOwnPropertyDescriptor(globalThis, "caches");
  Object.defineProperty(globalThis, "caches", {
    configurable: true,
    value: {
      default: {
        async match() { assert.fail("authenticated verification requests must not enter the Cache API"); },
        async put() { assert.fail("authenticated verification responses must not enter the Cache API"); },
      },
    },
  });
  return () => {
    if (previous) Object.defineProperty(globalThis, "caches", previous);
    else delete globalThis.caches;
  };
}

test("exact-commit verification uses only installation-authenticated API and Contents reads", async () => {
  const { observations, restore } = installVerificationFetch();
  const restoreCaches = rejectVerificationCacheAccess();
  try {
    const evidence = await loadCommitVerificationEvidence({
      repository: "Example/project",
      baseSha: BASE,
      headSha: HEAD,
      paths: ["README.md"],
    }, appEnv({ GITHUB_READ_TOKEN: "legacy-token-must-not-be-used" }));
    assert.equal(evidence.files[0].text, CONTENT);
    assert.equal(evidence.repository.providerRepositoryId, 424242);
    assert.equal(typeof evidence.repository.providerRepositoryId, "number");
    assert.deepEqual(evidence.repository.evidenceAuthority, {
      mode: "github_app_installation",
      scope: "selected_public_repository",
    });
    assert.equal(observations.tokenMints, 1);
    assert.deepEqual(observations.tokenBody, {
      repositories: ["project"],
      permissions: { checks: "read", contents: "read", statuses: "read" },
    });
    assert.ok(observations.apiAuthorizations.length >= 7);
    assert.ok(observations.apiAuthorizations.every((value) => value === "Bearer installation-token-sentinel"));
    assert.equal(observations.rawRequests, 0);
  } finally {
    restoreCaches();
    restore();
  }
});

test("verification fails before network access when the GitHub App broker is unconfigured", async () => {
  const original = globalThis.fetch;
  let requests = 0;
  globalThis.fetch = async () => { requests += 1; return new Response("unexpected"); };
  try {
    await assert.rejects(loadCommitVerificationEvidence({
      repository: "Example/project",
      baseSha: BASE,
      headSha: HEAD,
      paths: [],
    }, {}), { code: "GITHUB_APP_NOT_CONFIGURED" });
    assert.equal(requests, 0);
  } finally {
    globalThis.fetch = original;
  }
});

test("verification rejects private, redirected, or recreated repository metadata", async (t) => {
  for (const [name, metadata] of [
    ["private", { private: true, visibility: "private" }],
    ["redirected", { full_name: "Example/replacement" }],
    ["recreated identity", { id: 777777 }],
  ]) {
    await t.test(name, async () => {
      const { restore } = installVerificationFetch({ metadata });
      try {
        await assert.rejects(loadCommitVerificationEvidence({ repository: "Example/project", baseSha: BASE, headSha: HEAD }, appEnv()), { code: "GITHUB_APP_SCOPE_INVALID" });
      } finally {
        restore();
      }
    });
  }
});

test("verification rejects mismatched, unsupported, or oversized Contents API objects", async (t) => {
  const valid = {
    type: "file",
    path: "README.md",
    sha: "readme-sha",
    size: Buffer.byteLength(CONTENT),
    encoding: "base64",
    content: Buffer.from(CONTENT).toString("base64"),
  };
  for (const [name, contentPayload] of [
    ["blob mismatch", { ...valid, sha: "different-blob" }],
    ["non-file", { ...valid, type: "dir" }],
    ["unsupported encoding", { ...valid, encoding: "utf-8" }],
    ["oversized declaration", { ...valid, size: 1024 * 1024 + 1 }],
  ]) {
    await t.test(name, async () => {
      const { restore } = installVerificationFetch({ contentPayload });
      try {
        await assert.rejects(loadCommitVerificationEvidence({
          repository: "Example/project",
          baseSha: BASE,
          headSha: HEAD,
          paths: ["README.md"],
        }, appEnv()), { code: "GITHUB_APP_RESPONSE_INVALID" });
      } finally {
        restore();
      }
    });
  }
});

test("rate-limited optional exact-head evidence records a typed observation limitation", async () => {
  const { restore } = installVerificationFetch({
    checksResponse: () => Response.json({ message: "secondary rate limit" }, { status: 429, headers: { "retry-after": "60" } }),
  });
  try {
    const evidence = await loadCommitVerificationEvidence({ repository: "Example/project", baseSha: BASE, headSha: HEAD }, appEnv());
    assert.equal(evidence.checks.available, true);
    assert.equal(evidence.checks.reason, "rate_limited");
  } finally {
    restore();
  }
});

SHA-256: 8f9d7c3795b8615115da645730d3008530938044f0197ab071c52c4b1b126fed