oven-sh/bun · error · CertError
CERT_REJECTED
CERT_REJECTED
Error message
CERT_REJECTED
What it means
CertError::CERT_REJECTED maps BoringSSL X509 verify code 28 (X509_V_ERR_CERT_REJECTED) via get_cert_error_from_no() in src/http/lib.rs:1547. The root CA itself is trusted in the store but is not accepted for the requested purpose (TLS), so the chain is rejected at the anchor check. JS error.code is CERT_REJECTED with message 'certificate rejected' (FetchTasklet.rs:1463).
Source
Thrown at src/http/error.rs:177
#[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")]
KEYUSAGE_NO_CERTSIGN,
#[error("UNABLE_TO_GET_CRL_ISSUER")]
UNABLE_TO_GET_CRL_ISSUER,
#[error("UNHANDLED_CRITICAL_EXTENSION")]
UNHANDLED_CRITICAL_EXTENSION,
#[error("KEYUSAGE_NO_CRL_SIGN")]
KEYUSAGE_NO_CRL_SIGN,
#[error("UNHANDLED_CRITICAL_CRL_EXTENSION")]
UNHANDLED_CRITICAL_CRL_EXTENSION,
#[error("INVALID_NON_CA")]View on GitHub (pinned to 8c5296ac45)
Solutions
- Identify the anchor: openssl s_client -connect host:443 -showcerts — the last self-signed cert
- Replace the TLS chain with one rooted in a CA intended for SSL/TLS server auth
- If it is your own root, reissue the root with keyUsage=keyCertSign,cRLSign and no EKU restriction that excludes serverAuth
- Add the root explicitly per-connection via tls: { ca } so purpose rules come from the cert, not a restricted store entry
Example fix
# before: chain terminates in a code-signing root (rejected for TLS) openssl verify -purpose sslserver -CAfile codesign-root.pem leaf.pem # after: reissue under a TLS-capable root openssl verify -purpose sslserver -CAfile tls-root.pem leaf.pem # must print OK
Defensive patterns
Strategy: try-catch
Validate before calling
import { execSync } from "node:child_process";
const ok = execSync(`openssl verify -purpose sslserver -CAfile anchor.pem leaf.pem`).toString();
if (!ok.includes(": OK")) throw new Error("anchor rejected for TLS server purpose"); Type guard
function isCertRejected(e: unknown): e is Error & { code: "CERT_REJECTED" } {
return e instanceof Error && (e as any).code === "CERT_REJECTED";
} Try / catch
try { await fetch(url); } catch (e) { if (isCertRejected(e)) { escalateToSecurityTeam(`anchor not permitted for TLS: ${url}`); throw e; } throw e; } Prevention
- Use TLS-purpose roots for TLS; keep signing roots in separate bundles
- Check anchors with openssl verify -purpose sslserver before deployment
- Maintain a registry of which root serves which purpose
When it happens
Trigger: A root whose trust-store entry limits it to code signing or S/MIME is used to terminate a TLS server chain; purpose-specific trust (e.g., emailProtection-only root) during X509 purpose checking of an SSL connection.
Common situations: Repurposing a code-signing root for internal HTTPS, CA bundles installed for package signing (e.g., some artifact-signing roots) mistakenly serving TLS, exotic private CAs created without any TLS-compatible purpose.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- CERT_UNTRUSTED
- UNABLE_TO_GET_ISSUER_CERT_LOCALLY
- UNABLE_TO_VERIFY_LEAF_SIGNATURE
- CERT_CHAIN_TOO_LONG
- CERT_REVOKED
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/29ccf391a2900627.
Report an issue: GitHub.