ecdsa.com
Go crypto/x509Go

Error message

x509: certificate signed by unknown authority

Go crypto/x509 — returned by Certificate.Verify and TLS dials

What it means

Go tried to build a chain from the server's certificate to a root it trusts and failed: no path ends at a certificate in the configured root pool. The certificate may be perfectly valid — Go just has no reason to trust its issuer. This is the single most-hit TLS error in Go deployments.

Why it happens

How to fix it

  1. 1.

    Add the CA to the client's root pool

    Extend the system pool rather than replacing it, so public sites keep working alongside your internal CA.

    go
    roots, err := x509.SystemCertPool()
    if err != nil { roots = x509.NewCertPool() }
    pem, _ := os.ReadFile("internal-ca.pem")
    roots.AppendCertsFromPEM(pem)
    
    client := &http.Client{Transport: &http.Transport{
        TLSClientConfig: &tls.Config{RootCAs: roots},
    }}
  2. 2.

    Fix the server: serve the full chain

    Check what the server actually sends; if only one certificate appears, point the server at the full-chain file (for example Let's Encrypt's fullchain.pem).

    bash
    openssl s_client -connect api.example.com:443 -showcerts </dev/null \
      | grep -c "BEGIN CERTIFICATE"   # 1 = leaf only (broken), 2+ = chain present
  3. 3.

    Ship CA certs in the image

    For minimal images, copy a CA bundle in at build time. Never "solve" this with InsecureSkipVerify — that disables verification entirely.

    docker
    FROM alpine AS certs
    RUN apk add --no-cache ca-certificates
    
    FROM scratch
    COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

Related errors

← Browse the full signature error database