SonarSource/sonarqube · error · IllegalStateException

Invalid certificate

Error message

Invalid certificate

What it means

SamlCertificateConverter.toX509Certificate() parses a Base64-encoded X.509 certificate string (PEM headers already stripped by sanitizeCertificateString) into a java.security.cert.X509Certificate. If CertificateFactory.generateCertificate() throws CertificateException, the bytes are not a valid DER-encoded X.509 certificate, so it wraps the failure in an IllegalStateException with this message. This is a fail-fast guard: the SAML plugin cannot work without a usable SP certificate.

Source

Thrown at server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlCertificateConverter.java:42

import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import org.sonar.api.server.ServerSide;

@ServerSide
class SamlCertificateConverter {

  public static final String SPACES = "\\s+";

  X509Certificate toX509Certificate(String certificateString) {
    String cleanedCertificateString = sanitizeCertificateString(certificateString);

    byte[] decoded = Base64.getDecoder().decode(cleanedCertificateString);
    try {
      CertificateFactory factory = CertificateFactory.getInstance("X.509");
      return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(decoded));
    } catch (CertificateException e) {
      throw new IllegalStateException("Invalid certificate", e);
    }
  }

  private static String sanitizeCertificateString(String certificateString) {
    return certificateString
      .replace("-----BEGIN CERTIFICATE-----", "")
      .replace("-----END CERTIFICATE-----", "")
      .replaceAll(SPACES, "");
  }
}

View on GitHub (pinned to 184c821202)

Solutions

  1. Verify the sonar.auth.saml.certificate value is the Base64 body of an X.509 certificate without the BEGIN/END lines, on a single logical Base64 stream
  2. Re-export the certificate with: openssl x509 -in cert.pem -outform PEM and paste only the Base64 body
  3. Check the field mapping — certificate field got the private key or vice versa (private key goes to sonar.auth.saml.privateKey)

Example fix

// before (invalid: full PEM with escaped newlines pasted into settings)
String cert = "-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----";
// after (Base64 body only, headers stripped)
String cert = "MIIDdzCCAl+gAwIBAgIE...";
Defensive patterns

Strategy: validation

Validate before calling

String cleaned = cert.replace("-----BEGIN CERTIFICATE-----", "").replace("-----END CERTIFICATE-----", "").replaceAll("\\s", "");
byte[] decoded = Base64.getDecoder().decode(cleaned);
try {
  new X509CertImpl(decoded); // or CertificateFactory dry-run
} catch (CertificateException | IOException e) {
  throw new IllegalArgumentException("Not a valid X.509 certificate");
}

Type guard

static boolean looksLikeX509Pem(String s) {
  return s != null && !s.contains("PRIVATE KEY") && s.matches("(?s).*[A-Za-z0-9+/=]{100,}.*");
}

Try / catch

try {
  X509Certificate cert = SamlCertificateConverter.toX509Certificate(cfg.certificate());
} catch (IllegalStateException e) {
  log.error("SAML certificate invalid, check sonar.auth.saml.certificate", e);
  throw new ConfigurationException("Fix the SAML certificate setting");
}

Prevention

When it happens

Trigger: Calling toX509Certificate() (directly or via SonarQube SAML settings loading) with a value that is not valid Base64-then-DER X.509 data: truncated certificate, HTML-escaped PEM, missing or wrong header (e.g. '-----BEGIN CERTIFICATE-----' kept but a private key body pasted, or a PKCS#7 'BEGIN CERTIFICATE' chain), or a value containing whitespace/newlines in the wrong place.

Common situations: Admins pasting the IdP metadata certificate incorrectly, copying the SP private key into the certificate field, copy/paste introducing smart quotes or HTML entities, or uploading a DER binary file pasted as text.

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 SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/201cfd329c26a470. Report an issue: GitHub.