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.

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.

Appendix: 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)