JuliusBrussee/caveman · critical · Error

signature check failed for checksums.txt — refusing to insta

Error message

signature check failed for checksums.txt — refusing to install; partial download deleted

What it means

During binary install, after checksums.txt and its detached signature (checksums.txt.keysig) are fetched, verifyChecksumSignature() fails to validate the signature over the checksums text. The installer refuses to proceed rather than install binaries whose checksums cannot be trusted; any partial download is deleted. This is a supply-chain protection: unverified checksums means every artifact digest is untrusted.

Source

Thrown at packages/cli/src/index.ts:2211

    return;
  }

  const base = (process.env.CAVE_BINARY_RELEASE_BASE ?? BINARY_RELEASE_BASE_DEFAULT).replace(/\/+$/, "");
  const releaseBase = `${base}/${BINARY_RELEASE}`;
  let checksumsRaw: string;
  let signatureRaw: string;
  try {
    const [checksumsResponse, signatureResponse] = await Promise.all([
      fetchReleaseAsset(`${releaseBase}/checksums.txt`, timeoutSeconds),
      fetchReleaseAsset(`${releaseBase}/checksums.txt.keysig`, timeoutSeconds),
    ]);
    [checksumsRaw, signatureRaw] = await Promise.all([checksumsResponse.text(), signatureResponse.text()]);
  } catch (error) {
    setupInstallFailure(error, timeoutSeconds);
  }

  if (!verifyChecksumSignature(checksumsRaw!, signatureRaw!)) {
    throw new Error("signature check failed for checksums.txt — refusing to install; partial download deleted");
  }

  let checksums: Map<string, string>;
  try {
    checksums = parseSignedChecksums(checksumsRaw!);
  } catch {
    throw new Error("signature check failed for checksums.txt — refusing to install; partial download deleted");
  }

  const installed: InstalledBinary[] = [];
  const artifactDigests: Record<string, string> = {};
  for (const name of INSTALL_BINARIES) {
    const artifact = `${name}_${platform.os}_${platform.arch}`;
    const expected = checksums.get(artifact);
    if (!expected) {
      throw new Error(`signature check failed for ${artifact} — refusing to install; partial download deleted`);
    }
    const target = join(binDir, binaryInstallFilename(name, platform.os));

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Retry the install — transient CDN corruption is the most common cause
  2. If behind a TLS-inspection proxy, bypass it for the release download domain or verify what bytes are actually served (curl both files and inspect)
  3. Upgrade the caveman CLI package (npm i -g) so it carries the current signing key after a key rotation
  4. Report the mismatch to maintainers if it persists — do not attempt to skip signature verification
Defensive patterns

Strategy: validation

Type guard

function isChecksumSignatureError(e: unknown): boolean {
  return e instanceof Error && e.message.startsWith("signature check failed for checksums.txt");
}

Try / catch

try {
  await runCavemanSetupInstall();
} catch (e) {
  if (isChecksumSignatureError(e)) {
    // never bypass: retry once on a clean network, then escalate/report
    await runCavemanSetupInstall();
  } else throw e;
}

Prevention

When it happens

Trigger: `caveman setup --install` where the fetched checksums.txt was modified in transit (proxy/MITM rewriting content), the signature file is truncated or an HTML error page, or the pinned signing key embedded in the CLI does not match the release (key rotation or a tampered release).

Common situations: Corporate TLS-inspection proxy that rewrites response bodies; CDN cache poisoning serving stale/mismatched checksums vs signature; CLI version too old to know the current signing key after a key rotation; a genuinely compromised or corrupted release.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/7f71862ab5022b1a. Report an issue: GitHub.