grpc/grpc-java · error · CertificateParsingException

Invalid SAN entry

Error message

Invalid SAN entry

What it means

verifyOneSanInList inspects one entry of a certificate's subjectAltName list, expecting a [type, value] pair with at least two elements. Entries that are null or shorter than 2 elements cannot be interpreted, so it throws CertificateParsingException('Invalid SAN entry'). This guards against malformed SAN data returned from certificate parsing.

Source

Thrown at xds/src/main/java/io/grpc/xds/internal/security/trust/XdsX509TrustManager.java:180

        ? sanToVerifyExact.equalsIgnoreCase(altNameFromCert)
        : sanToVerifyExact.equals(altNameFromCert);
  }

  private static boolean verifyDnsNameInSanList(
      String altNameFromCert, List<StringMatcher> verifySanList) {
    for (StringMatcher verifySan : verifySanList) {
      if (verifyDnsNameInPattern(altNameFromCert, verifySan)) {
        return true;
      }
    }
    return false;
  }

  private static boolean verifyOneSanInList(List<?> entry, List<StringMatcher> verifySanList)
      throws CertificateParsingException {
    // from OkHostnameVerifier.getSubjectAltNames
    if (entry == null || entry.size() < 2) {
      throw new CertificateParsingException("Invalid SAN entry");
    }
    Integer altNameType = (Integer) entry.get(0);
    if (altNameType == null) {
      throw new CertificateParsingException("Invalid SAN entry: null altNameType");
    }
    switch (altNameType) {
      case ALT_DNS_NAME:
      case ALT_URI_NAME:
      case ALT_IPA_NAME:
        return verifyDnsNameInSanList((String) entry.get(1), verifySanList);
      default:
        return false;
    }
  }

  // logic from Envoy::Extensions::TransportSockets::Tls::ContextImpl::verifySubjectAltName
  private static void verifySubjectAltNameInLeaf(
      X509Certificate cert, List<StringMatcher> verifyList) throws CertificateException {

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Regenerate or replace the certificate so it contains well-formed SAN extensions (type+value pairs)
  2. Try a different security provider (e.g. switch JCE/conscrypt version) if the parser is producing malformed SAN lists
  3. Catch CertificateParsingException in the handshake path and fail verification cleanly with a diagnostic of the offending certificate
  4. Inspect the peer certificate with openssl x509 -text to confirm SAN structure before assuming a library bug

Example fix

// before: cert with malformed SAN extension (single-element entry)
// regenerate:
// after
openssl x509 -req -extfile <(printf "subjectAltName=DNS:foo.example.com") ...
Defensive patterns

Strategy: validation

Validate before calling

// Filter malformed SAN entries before verification
boolean wellFormedSan(List<?> entry) {
  return entry != null && entry.size() >= 2 && entry.get(0) instanceof Integer;
}

Type guard

static boolean isSanEntry(List<?> entry) {
  return entry != null && entry.size() >= 2 && entry.get(0) instanceof Integer;
}

Try / catch

try {
  verifySubjectAltNameInLeaf(certificate, sanList);
} catch (CertificateParsingException e) {
  logger.warn("Peer certificate has malformed SAN; treating as untrusted: " + e.getMessage());
  return false; // fail verification, do not crash handshake
}

Prevention

When it happens

Trigger: During SAN verification (verifySubjectAltNameInLeaf), iterating cert.getSubjectAlternativeNames() (or an equivalent list) and encountering a malformed entry: null entry or a list with fewer than 2 elements (e.g. a bare type without value); thrown before the altNameType switch.

Common situations: Certificates with unusual/legacy SAN encodings that some BouncyCastle/conscrypt parsers decode into short lists; hand-built test certificates; third-party security providers producing non-standard collection shapes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/92d1d1ad097c9993. Report an issue: GitHub.