ruvnet/ruflo · critical · ReleaseVerificationError

SHA256SUMS.sig failed Ed25519 verification — refusing to…

Error message

SHA256SUMS.sig failed Ed25519 verification — refusing to install

What it means

verifyRelease() first checks the Ed25519 signature over the SHA256SUMS manifest using the public key embedded in the CLI — per ADR-307 there is no partial-trust outcome, so any signature failure refuses the install outright. This is the root-of-trust check: per-file hashes are only consulted after it passes. A wrong key, tampered manifest, or corrupted download all produce this one error.

Solutions

  1. Update the ruflo CLI to the latest release — key rotations ship with an updated embedded public key
  2. Clear cached downloads and retry `ruflo proxy install` from a clean network path (in-transit corruption is common)
  3. If it persists on the latest CLI from a clean network, report it to maintainers immediately — consistent failure can indicate a genuine supply-chain compromise
  4. Never attempt to bypass it; there is intentionally no override flag
Defensive patterns

Strategy: try-catch

Type guard

const isReleaseVerification = (e: unknown): e is Error & { name: 'ReleaseVerificationError' } =>
  e instanceof Error && e.name === 'ReleaseVerificationError';

Try / catch

try {
  const { sha256 } = verifyRelease(input);
} catch (e) {
  if (isReleaseVerification(e)) {
    // NEVER bypass: report and abort. Signature failure on a current CLI
    // from a clean network is a supply-chain signal.
    securityLog.fatal('release signature invalid', { detail: e.message });
    process.exit(4);
  }
  throw e;
}

Prevention

When it happens

Trigger: A signature produced by a different key than the one embedded in this CLI version (upstream key rotation without updating ruflo); a modified SHA256SUMS or .sig in transit; a truncated download of either file failing crypto.verify.

Common situations: Upstream rotated the signing key while users run an older CLI; MITM/proxy rewriting downloads; interrupted downloads leaving truncated files; releases published with a mis-signed manifest.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/e855d7bd4e59a8bd. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/proxy/verify.ts:79

  sigBase64: string;
  assetBytes: Buffer;
  assetFilename: string;
  pubkeyPem?: string;
}

export interface VerifyReleaseResult {
  sha256: string;
}

/**
 * Full verification: signature over SHA256SUMS, then the asset's own hash
 * against the matching line. Throws `ReleaseVerificationError` on ANY
 * failure — there is no partial-trust outcome, matching ADR-307's "refuses
 * on any mismatch" requirement.
 */
export function verifyRelease(input: VerifyReleaseInput): VerifyReleaseResult {
  if (!verifySha256SumsSignature(input.sumsBytes, input.sigBase64, input.pubkeyPem)) {
    throw new ReleaseVerificationError('SHA256SUMS.sig failed Ed25519 verification — refusing to install');
  }

  const sums = parseSha256Sums(input.sumsBytes.toString('utf-8'));
  const expected = sums[input.assetFilename];
  if (!expected) {
    throw new ReleaseVerificationError(`SHA256SUMS has no entry for ${input.assetFilename}`);
  }

  const actual = sha256Hex(input.assetBytes);
  if (actual !== expected) {
    throw new ReleaseVerificationError(
      `sha256 mismatch for ${input.assetFilename}: expected ${expected.slice(0, 12)}…, got ${actual.slice(0, 12)}…`,
    );
  }

  return { sha256: actual };
}

View on GitHub (pinned to fa13ee4ad6)