From d80eeb9677b9cf49cb8f0d0aca680cda9f0098a0 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 5 Apr 2026 22:00:08 +0200 Subject: [PATCH] Parse out the poison extension in pre-certs --- internal/utils/utils.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/internal/utils/utils.go b/internal/utils/utils.go index ec593d4..ac5aab1 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -31,7 +31,10 @@ var ( issuerCacheMu sync.Mutex ) -var oidSCTList = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2} +var ( + oidSCTList = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2} + oidCTPoison = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3} +) // CTLogInfo holds details about a CT log from the log list. type CTLogInfo struct { @@ -91,6 +94,7 @@ type CertDetails struct { KeyUsage []string `json:"key_usage,omitempty"` ExtKeyUsage []string `json:"ext_key_usage,omitempty"` IsCA bool `json:"is_ca"` + PoisonExtension bool `json:"poison_extension,omitempty"` } var keyUsageNames = []struct { @@ -470,8 +474,10 @@ func fetchIssuer(logURL, fingerprint string) (*IssuerInfo, error) { // parseCertDetails extracts certificate fields not covered by TrimmedEntry. func parseCertDetails(certDER []byte) *CertDetails { - cert, err := x509.ParseCertificate(certDER) - if err != nil { + // Proceed as long as a cert was returned, even if there are unhandled + // critical extensions (e.g. the CT poison extension in precertificates). + cert, _ := x509.ParseCertificate(certDER) + if cert == nil { return nil } @@ -508,6 +514,12 @@ func parseCertDetails(certDER []byte) *CertDetails { d.ExtKeyUsage = append(d.ExtKeyUsage, name) } } + for _, ext := range cert.Extensions { + if ext.Id.Equal(oidCTPoison) { + d.PoisonExtension = true + break + } + } return d }