fix: close release provenance and privacy gaps
This commit is contained in:
79
tests/security/release-authority.test.ts
Normal file
79
tests/security/release-authority.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import {
|
||||
canonicalJsonDigest,
|
||||
canonicalValueBytes,
|
||||
} from "../../src/security/canonical-digest.ts";
|
||||
import {
|
||||
verifySignedRelease,
|
||||
verifySignedReleaseForTest,
|
||||
} from "../../scripts/deploy/lib/release-common.mjs";
|
||||
|
||||
const h = (c: string) => c.repeat(64);
|
||||
|
||||
describe("protected release verification authority", () => {
|
||||
test("production seam rejects caller-selected verifier, policy path, and time", async () => {
|
||||
await expect(
|
||||
verifySignedRelease({
|
||||
signedManifestPath: "/not-used",
|
||||
authorityRoot: "/not-used",
|
||||
verifierModulePath: "/tmp/evil.mjs",
|
||||
trustPolicyPath: "/tmp/evil.json",
|
||||
now: "2000-01-01T00:00:00Z",
|
||||
protectedState: {},
|
||||
} as never),
|
||||
).rejects.toThrow(/unknown|caller|production/i);
|
||||
});
|
||||
|
||||
test("test seam still requires the protected trust-policy digest", async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), "portfolio-release-authority-"));
|
||||
await mkdir(join(root, ".control"));
|
||||
const signedManifestPath = join(root, "signed.json");
|
||||
const trustPolicyPath = join(root, ".control", "release-trust.json");
|
||||
const trustPolicy = {
|
||||
schema: "portfolio-trust-policy/v1",
|
||||
policyVersion: "test",
|
||||
};
|
||||
await writeFile(
|
||||
signedManifestPath,
|
||||
canonicalValueBytes({ schema: "signed" }),
|
||||
);
|
||||
await writeFile(trustPolicyPath, canonicalValueBytes(trustPolicy));
|
||||
const protectedState = {
|
||||
latestLedgerHeadHash: h("1"),
|
||||
latestLedgerRevision: 1,
|
||||
currentManifestDigest: null,
|
||||
publisherFence: 0,
|
||||
releaseTrustPolicyDigest: h("9"),
|
||||
};
|
||||
await expect(
|
||||
verifySignedReleaseForTest({
|
||||
signedManifestPath,
|
||||
trustPolicyPath,
|
||||
protectedState,
|
||||
now: "2026-09-02T01:00:00Z",
|
||||
verifySignedReleaseEnvelope: () => {
|
||||
throw new Error("must not reach verifier");
|
||||
},
|
||||
}),
|
||||
).rejects.toThrow(/trust.policy|authority|digest/i);
|
||||
protectedState.releaseTrustPolicyDigest = canonicalJsonDigest(
|
||||
"portfolio-trust-policy/v1",
|
||||
trustPolicy,
|
||||
);
|
||||
await expect(
|
||||
verifySignedReleaseForTest({
|
||||
signedManifestPath,
|
||||
trustPolicyPath,
|
||||
protectedState,
|
||||
now: "2026-09-02T01:00:00Z",
|
||||
verifySignedReleaseEnvelope: () => {
|
||||
throw new Error("reached-bound-verifier");
|
||||
},
|
||||
}),
|
||||
).rejects.toThrow("reached-bound-verifier");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user