cloudflare/pingora · error

Failed to parse certificate from DER format.

Error message

Failed to parse certificate from DER format.

What it means

The s2n-tls backend's twin of the rustls helper: get_organization_serial_bytes() parses a DER-encoded X509 certificate with x509-parser and expects success. It panics when the input bytes are not a complete valid DER certificate — PEM/base64 passed where raw DER is required, or truncated/corrupted bytes.

Source

Thrown at pingora-core/src/utils/tls/s2n.rs:57

    get_organization_x509(x509cert.borrow_cert())
}

/// Return the organization associated with the X509 certificate.
/// see https://en.wikipedia.org/wiki/X.509#Structure_of_a_certificate
pub fn get_organization_x509(x509cert: &X509Certificate<'_>) -> Option<String> {
    x509cert
        .subject
        .iter_organization()
        .filter_map(|a| a.as_str().ok())
        .map(|a| a.to_string())
        .reduce(|cur, next| cur + &next)
}

/// Return the organization associated with the X509 certificate (as bytes).
/// see https://en.wikipedia.org/wiki/X.509#Structure_of_a_certificate
pub fn get_organization_serial_bytes(cert: &[u8]) -> Result<(Option<String>, String)> {
    let (_, x509cert) = x509_parser::certificate::X509Certificate::from_der(cert)
        .expect("Failed to parse certificate from DER format.");

    get_organization_serial_x509(&x509cert)
}

/// Return the organization unit associated with the X509 certificate.
/// see https://en.wikipedia.org/wiki/X.509#Structure_of_a_certificate
pub fn get_organization_unit(x509cert: &WrappedX509) -> Option<String> {
    x509cert
        .borrow_cert()
        .subject
        .iter_organizational_unit()
        .filter_map(|a| a.as_str().ok())
        .map(|a| a.to_string())
        .reduce(|cur, next| cur + &next)
}

/// Get a combination of the common names for the given certificate
/// see https://en.wikipedia.org/wiki/X.509#Structure_of_a_certificate

View on GitHub (pinned to 0046038bd4)

Solutions

  1. Convert to DER first: `openssl x509 -in cert.pem -outform DER -out cert.der`
  2. Pre-check with `openssl x509 -inform DER -in cert.der -noout` before calling the helper
  3. If starting from PEM, decode the CERTIFICATE block payload yourself and pass those bytes
  4. Verify integrity (size/checksum) if the bytes travel through config systems

Example fix

// before: PEM bytes passed to the s2n helper — panics
let (org, serial) = get_organization_serial_bytes(&pem_bytes);

// after: pass the decoded DER contents of the PEM block
use x509_parser::pem::Pem;
let pem = Pem::iter_from_buffer(&pem_bytes).next().unwrap().unwrap();
let (org, serial) = get_organization_serial_bytes(&pem.contents);
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_der_cert(bytes: &[u8]) -> bool {
    x509_parser::certificate::X509Certificate::from_der(bytes).is_ok()
}

// gate the s2n helper call
anyhow::ensure!(
    is_valid_der_cert(&cert_bytes),
    "certificate is not valid DER (s2n get_organization_serial_bytes will panic)"
);

Type guard

fn is_der_cert(bytes: &[u8]) -> bool {
    bytes.first() == Some(&0x30)
        && x509_parser::certificate::X509Certificate::from_der(bytes).is_ok()
}

Try / catch

let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    get_organization_serial_bytes(&cert_bytes)
}));
if res.is_err() { /* log the offending cert and skip org/serial extraction */ }

Prevention

When it happens

Trigger: Calling pingora's s2n TLS utils get_organization_serial_bytes(cert_bytes) (cert org/serial extraction) with bytes that are PEM text, base64, truncated, or otherwise not strict DER. Only applies to builds using the s2n TLS feature.

Common situations: Same file fed to both DER- and PEM-expecting code paths; cert bytes sliced from the wrong offset in a chain buffer; corruption from secrets injection; empty file from a failed volume mount.

Understand the failure class

Related errors


AI-assisted analysis of cloudflare/pingora@0046038bd4 (2026-08-16). Data as JSON: /api/errors/f9ee7a3b89c49415. Report an issue: GitHub.