Go — x509 certificate signed by unknown authority

`x509: certificate signed by unknown authority` means Go could not find a trusted root for the certificate a server presented. Unlike Python, Go does read the operating system trust store, so the cause is nearly always that there is no trust store to read — a container built `FROM scratch` or a bare `alpine` image ships no CA certificates at all. Install the `ca-certificates` package, or copy `/etc/ssl/certs/ca-certificates.crt` into the image. If the chain ends at a corporate root, install that root instead.

Updated August 19, 2026 Verified against OpenSSL 3.5.7

Step 1 — does the image have a trust store? #

docker run --rm your-image ls -la /etc/ssl/certs/ca-certificates.crt

No such file or directory is the answer in most cases. A scratch image contains only your binary; a bare alpine ships without CA certificates too.

Fixing it in a Dockerfile #

RUN apk add --no-cache ca-certificates
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*

Copy the bundle from a builder stage — there is no package manager to install it with:

FROM golang:1.23-alpine AS build
RUN apk add --no-cache ca-certificates
COPY . /src
WORKDIR /src
RUN CGO_ENABLED=0 go build -o /app

FROM scratch
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /app /app
ENTRYPOINT ["/app"]

gcr.io/distroless/static already includes a CA bundle. If you are seeing this error on distroless, the cause is a corporate root rather than a missing store — see below.

A corporate root #

If the chain ends at a root your organisation controls, the bundle exists but does not contain it. Find out what the top of the chain actually is:

openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
| grep -E "^ *[0-9]+ s:"

Then add it:

COPY corporate-root.crt /usr/local/share/ca-certificates/
RUN update-ca-certificates

Or without rebuilding, by pointing Go at a bundle:

export SSL_CERT_FILE=/etc/ssl/certs/corporate-bundle.crt

A missing intermediate #

Less common with Go, but check it before blaming the client. If the server sends only its own certificate, the chain is incomplete and every non-browser client fails:

openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
| grep -c "BEGIN CERTIFICATE"
Expected output
2

A count of 1 from a publicly trusted site means the server is at fault — see unable to get local issuer certificate.

Supplying a root in code #

When one client needs a root the rest of the system should not trust:

pool, err := x509.SystemCertPool()
if err != nil {
  pool = x509.NewCertPool()
}
pem, err := os.ReadFile("corporate-root.crt")
if err != nil {
  return err
}
if !pool.AppendCertsFromPEM(pem) {
  return errors.New("no certificates found in corporate-root.crt")
}

client := &http.Client{
  Transport: &http.Transport{
      TLSClientConfig: &tls.Config{RootCAs: pool},
  },
}

Starting from SystemCertPool keeps every normal root working; starting from an empty pool would trust only the corporate root and break everything else.

Frequently asked questions

Why does this only happen in my container?
Because your development machine has a populated trust store and the image does not. Minimal base images ship no CA certificates, so every TLS connection from inside them fails until you add them.
Does Go use the system trust store?
Yes, on every platform. That is why this error usually points at the environment rather than the code. SSL_CERT_FILE and SSL_CERT_DIR override it if you need a specific bundle.
Can I skip verification for testing?
Setting InsecureSkipVerify on a tls.Config does it, and it disables authentication entirely for that client. It is a diagnostic, not a fix, and it should never reach production code.
How do I add a root for a Go program without rebuilding the image?
Set SSL_CERT_FILE to a bundle containing it. Go reads that variable, so a mounted file plus an environment variable is enough.

References