knadh/listmonk · error
error getting SNS cert: %v
Error message
error getting SNS cert: %v
What it means
verifyNotif wraps any error from getCert when retrieving the SNS signing certificate referenced by the notification's SigningCertURL. getCert can fail for URL validation, HTTP fetch errors, non-200 responses, or PEM/x509 parse errors; all surface as this wrapped message. Without the certificate, the library cannot verify the notification's signature.
Source
Thrown at internal/bounce/webhooks/ses.go:205
}
b.WriteString("Timestamp" + "\n" + n.Timestamp + "\n")
if n.Token != "" {
b.WriteString("Token" + "\n" + n.Token + "\n")
}
b.WriteString("TopicArn" + "\n" + n.TopicArn + "\n")
b.WriteString("Type" + "\n" + n.Type + "\n")
return b.Bytes()
}
// verifyNotif verifies the signature on a notification payload.
func (s *SES) verifyNotif(n sesNotif) error {
// Get the message signing certificate.
cert, err := s.getCert(n.SigningCertURL)
if err != nil {
return fmt.Errorf("error getting SNS cert: %v", err)
}
sign, err := base64.StdEncoding.DecodeString(n.Signature)
if err != nil {
return err
}
return cert.CheckSignature(x509.SHA1WithRSA, s.buildSignature(n), sign)
}
// getCert takes the SNS certificate URL and fetches it and caches it for the first time,
// and returns the cached cert for subsequent calls.
func (s *SES) getCert(certURL string) (*x509.Certificate, error) {
// Ensure that the cert URL is Amazon's.
u, err := url.Parse(certURL)
if err != nil {
return nil, err
}View on GitHub (pinned to 670c01717d)
Solutions
- Unwrap the error to see the root cause (%v prints the inner getCert error, e.g. 'invalid SNS certificate URL' vs a network error).
- Verify outbound network access to the certificate host (curl the SigningCertURL from the server).
- Confirm the SES/SNS notification includes a valid SigningCertURL pointing at sns.<region>.amazonaws.com.
- If transient, SNS will redeliver the notification — ensure your endpoint returns 5xx on this error so SNS retries instead of swallowing it.
- Check the cert cache is not serving stale entries and that getCert's HTTP fetch and PEM parsing handle your region's cert format.
Example fix
// before: opaque wrap loses context for ops
return fmt.Errorf("error getting SNS cert: %v", err)
// after: return the error unwrapped and classify for retry
if err := ...; err != nil {
return fmt.Errorf("error getting SNS cert: %w", err) // use %w so errors.Is/As work
} Defensive patterns
Strategy: retry
Validate before calling
u, err := url.Parse(notif.SigningCertURL)
if err != nil || u.Host == "" {
return errors.New("notification missing SigningCertURL")
}
resp, err := http.Head(notif.SigningCertURL)
if err != nil || resp.StatusCode != http.StatusOK {
return fmt.Errorf("cert URL unreachable: %s", notif.SigningCertURL)
} Type guard
func hasValidCertURL(n sesNotif) bool {
u, err := url.Parse(n.SigningCertURL)
return err == nil && u.Scheme == "https" && strings.HasSuffix(u.Host, ".amazonaws.com")
} Try / catch
if err := ses.ProcessBounce(notif); err != nil {
if strings.Contains(err.Error(), "error getting SNS cert") {
// transient network/cert fetch issue: return 5xx so SNS redelivers
log.Error("cert fetch failed, will let SNS retry", "err", err)
http.Error(w, "temporary failure", http.StatusServiceUnavailable)
return
}
http.Error(w, "bad request", http.StatusBadRequest)
} Prevention
- Verify outbound HTTPS access to sns.<region>.amazonaws.com from the webhook host
- Monitor egress failures — this error is often the first sign of network/DNS trouble
- Return 5xx (not 2xx) on this error so SNS retries the delivery
- Keep the in-memory cert cache warm; pre-fetch region certs at startup if possible
When it happens
Trigger: Called from ProcessSubscription or ProcessBounce when the notification's SigningCertURL is malformed or not an Amazon URL (invalid SNS certificate URL), the HTTPS fetch to sns.amazonaws.com fails (network/DNS outage), Amazon returns non-200, or the body is not a valid PEM certificate.
Common situations: Corporate egress firewall blocking outbound HTTPS to sns.<region>.amazonaws.com; forged/spoofed webhook posts with attacker-controlled SigningCertURL (rejected here); Amazon rotating/cert URL 404ing transiently; empty SigningCertURL in hand-crafted test payloads.
Related errors
- error unmarshalling SNS notification: %v
- invalid SNS certificate URL: %v
- invalid timestamp in signature: %v
- invalid signature format
- error unmarshalling postmark notification: %v
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/8d9793c2458a2630.
Report an issue: GitHub.