Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions scripts/verify-release-evidence.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { describe, it } from "node:test";

import {
Expand Down Expand Up @@ -164,6 +165,18 @@ void describe("release evidence manifest", () => {
});
});

void describe("subprocess capture", () => {
void it("bounds every captured subprocess above Node's 1 MiB default", () => {
// A cosign attestation carries the whole SPDX SBOM base64-encoded. Under the default cap the
// capture raises ENOBUFS, which failed a release after the images were already tagged.
const source = readFileSync(new URL("./verify-release-evidence.ts", import.meta.url), "utf8");
assert.match(source, /maxBuffer: CAPTURE_LIMIT_BYTES/);
const limit = /const CAPTURE_LIMIT_BYTES = (\d+) \* 1024 \* 1024;/.exec(source);
assert.ok(limit, "CAPTURE_LIMIT_BYTES must be declared in MiB");
assert.ok(Number(limit[1]) >= 64, "an SBOM attestation needs far more than the 1 MiB default");
});
});

void describe("release evidence bindings", () => {
void it("binds license and OCI index evidence to the immutable subject", () => {
const amd64 = subject("linux/amd64");
Expand Down
9 changes: 9 additions & 0 deletions scripts/verify-release-evidence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,19 @@ export function validateManifest(
return { schemaVersion: 1, subjects };
}

/**
* Node caps a captured subprocess at 1 MiB and raises ENOBUFS past it. A `cosign verify-attestation`
* envelope carries the whole SPDX SBOM base64-encoded, so the webapp's exceeds that cap and failed a
* release mid-verification. The bound belongs here rather than at a call site: every capture in this
* file reads an SBOM, an attestation or an image index, and none of them has a useful size limit.
*/
const CAPTURE_LIMIT_BYTES = 256 * 1024 * 1024;

function command(commandName: string, args: string[], capture = false): string {
const result = spawnSync(commandName, args, {
encoding: "utf8",
stdio: capture ? "pipe" : "inherit",
maxBuffer: CAPTURE_LIMIT_BYTES,
});
if (result.error) throw result.error;
if (result.status !== 0) {
Expand Down
Loading