Summary
The certificate-transparency-go operator tooling (sctcheck, certcheck, crlcheck, and the fixchain preloader) fetches URLs from certificate extensions (AIA CA Issuers, CRL Distribution Points) without any SSRF protection.
Vulnerable Code
Root cause: x509util/files.go:97-115 — GetIssuer() fetches AIA URL with no validation
func GetIssuer(cert *x509.Certificate, client *http.Client) (*x509.Certificate, error) {
issuerURL := cert.IssuingCertificateURL[0] // raw string from cert's AIA extension
rsp, err := client.Get(issuerURL) // HTTP GET with no scheme/host/IP validation
body, err := io.ReadAll(rsp.Body) // no response size limit — OOM possible
Same vulnerability in five additional callsites:
ctutil/sctcheck/sctcheck.go:131 — triggers GetIssuer() during SCT checking
x509util/crlcheck/crlcheck.go:170-174 — directly calls client.Get(crldp) on CRL Distribution Points
x509util/files.go:48-56 — ReadPossiblePEMURL uses bare http.Get() with no timeout
x509util/certcheck/certcheck.go:226-227 — checkRevocation() calls ReadPossiblePEMURL on CRL Distribution Points
fixchain/url_cache.go:67 — fixchain preloader calls client.Get(url) on AIA URLs from every cert in a CT log
Additionally, InsecureSkipVerify: true is set in tooling (sctcheck, certcheck), disabling TLS certificate validation.
Attack Scenario
An attacker submits a certificate with an AIA CA Issuers URL of http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token to a CT log operator who then runs sctcheck, certcheck --check_revocation, or crlcheck. The tool makes an outbound HTTP request to the GCP instance metadata endpoint from the operator's cloud VM.
Suggested Fix
Add URL validation before fetching AIA/CRL URLs: reject private IP ranges, cloud metadata endpoints, and loopback addresses. Add response size limits to io.ReadAll calls. Add timeouts to http.Get calls.
Summary
The
certificate-transparency-gooperator tooling (sctcheck,certcheck,crlcheck, and thefixchainpreloader) fetches URLs from certificate extensions (AIA CA Issuers, CRL Distribution Points) without any SSRF protection.Vulnerable Code
Root cause:
x509util/files.go:97-115—GetIssuer()fetches AIA URL with no validationSame vulnerability in five additional callsites:
ctutil/sctcheck/sctcheck.go:131— triggersGetIssuer()during SCT checkingx509util/crlcheck/crlcheck.go:170-174— directly callsclient.Get(crldp)on CRL Distribution Pointsx509util/files.go:48-56—ReadPossiblePEMURLuses barehttp.Get()with no timeoutx509util/certcheck/certcheck.go:226-227—checkRevocation()callsReadPossiblePEMURLon CRL Distribution Pointsfixchain/url_cache.go:67—fixchainpreloader callsclient.Get(url)on AIA URLs from every cert in a CT logAdditionally,
InsecureSkipVerify: trueis set in tooling (sctcheck,certcheck), disabling TLS certificate validation.Attack Scenario
An attacker submits a certificate with an AIA CA Issuers URL of
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/tokento a CT log operator who then runssctcheck,certcheck --check_revocation, orcrlcheck. The tool makes an outbound HTTP request to the GCP instance metadata endpoint from the operator's cloud VM.Suggested Fix
Add URL validation before fetching AIA/CRL URLs: reject private IP ranges, cloud metadata endpoints, and loopback addresses. Add response size limits to
io.ReadAllcalls. Add timeouts tohttp.Getcalls.