oven-sh/bun · critical · CertError

CERT_REVOKED

CERT_REVOKED

Error message

CERT_REVOKED

What it means

CertError::CERT_REVOKED maps BoringSSL X509 verify code 23 (X509_V_ERR_CERT_REVOKED) via get_cert_error_from_no() in src/http/lib.rs:1542. During path validation a CRL covering the certificate listed its serial as revoked, so the TLS connection is rejected. JS error.code is CERT_REVOKED with message 'certificate revoked' (FetchTasklet.rs:1437).

Source

Thrown at src/http/error.rs:167

    #[error("ERROR_IN_CERT_NOT_AFTER_FIELD")]
    ERROR_IN_CERT_NOT_AFTER_FIELD,
    #[error("ERROR_IN_CRL_LAST_UPDATE_FIELD")]
    ERROR_IN_CRL_LAST_UPDATE_FIELD,
    #[error("ERROR_IN_CRL_NEXT_UPDATE_FIELD")]
    ERROR_IN_CRL_NEXT_UPDATE_FIELD,
    #[error("OUT_OF_MEM")]
    OUT_OF_MEM,
    #[error("DEPTH_ZERO_SELF_SIGNED_CERT")]
    DEPTH_ZERO_SELF_SIGNED_CERT,
    #[error("SELF_SIGNED_CERT_IN_CHAIN")]
    SELF_SIGNED_CERT_IN_CHAIN,
    #[error("UNABLE_TO_GET_ISSUER_CERT_LOCALLY")]
    UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
    #[error("UNABLE_TO_VERIFY_LEAF_SIGNATURE")]
    UNABLE_TO_VERIFY_LEAF_SIGNATURE,
    #[error("CERT_CHAIN_TOO_LONG")]
    CERT_CHAIN_TOO_LONG,
    #[error("CERT_REVOKED")]
    CERT_REVOKED,
    #[error("INVALID_CA")]
    INVALID_CA,
    #[error("PATH_LENGTH_EXCEEDED")]
    PATH_LENGTH_EXCEEDED,
    #[error("INVALID_PURPOSE")]
    INVALID_PURPOSE,
    #[error("CERT_UNTRUSTED")]
    CERT_UNTRUSTED,
    #[error("CERT_REJECTED")]
    CERT_REJECTED,
    #[error("SUBJECT_ISSUER_MISMATCH")]
    SUBJECT_ISSUER_MISMATCH,
    #[error("AKID_SKID_MISMATCH")]
    AKID_SKID_MISMATCH,
    #[error("AKID_ISSUER_SERIAL_MISMATCH")]
    AKID_ISSUER_SERIAL_MISMATCH,
    #[error("KEYUSAGE_NO_CERTSIGN")]

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Check the CA's revocation status page / crt.sh for the cert serial, then request and install a fresh certificate
  2. If an intermediate was revoked, get the server reissued under a different intermediate and serve the new chain
  3. Confirm it is not a stale-CRL artifact: openssl verify -crl_check -CRLfile crl.pem leaf.pem
  4. Only for throwaway test endpoints: tls: { rejectUnauthorized: false } — never in production

Example fix

// before
await fetch("https://revoked.example.com");
// after (test only): acknowledge revocation explicitly
await fetch("https://revoked.example.com", {
  tls: { rejectUnauthorized: false }, // test env only
});
Defensive patterns

Strategy: try-catch

Validate before calling

import tls from "node:tls";
function ocspOk(host: string, port = 443): Promise<boolean> {
  return new Promise((resolve) => {
    const s = tls.connect({ host, port, servername: host }, () => { resolve(s.authorized); s.destroy(); });
    s.on("error", (err: any) => resolve(err?.code !== "CERT_REVOKED"));
  });
}
const ok = await ocspOk("partner.example.com");

Type guard

function isCertRevoked(e: unknown): e is Error & { code: "CERT_REVOKED" } {
  return e instanceof Error && (e as any).code === "CERT_REVOKED";
}

Try / catch

try { return await fetch(url); } catch (e) { if (isCertRevoked(e)) { quarantineHost(new URL(url).host); throw new Error(`refusing revoked endpoint: ${url}`); } throw e; }

Prevention

When it happens

Trigger: TLS handshake against a server whose certificate (or an intermediate in its chain) was revoked by the CA's CRL; CRL data supplied in the verification context matches the cert's serial number.

Common situations: CA revoked the cert after compromise or mis-issuance and the operator missed the notice; test/lab CA with a stale CRL that accidentally lists the serial; revocation of an intermediate taking down all leafs under it.

Understand the failure class

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/5720a479f1f669fb. Report an issue: GitHub.