Skip to content

crypto/tls: misleading "remote error: tls: certificate required" error when client cert CA not in server's accepted CAs list #75009

@Vinnie-V

Description

@Vinnie-V

Go version

go version go1.24.6 linux/amd64

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/ubuntu/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/ubuntu/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1329920774=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/ubuntu/repos/go-mtls-ticket/go.mod'
GOMODCACHE='/home/ubuntu/go/pkg/mod'
GONOPROXY='bitbucket.org/REDACTED/*'
GONOSUMDB='bitbucket.org/REDACTED/*'
GOOS='linux'
GOPATH='/home/ubuntu/go'
GOPRIVATE='bitbucket.org/REDACTED/*'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go-1.24'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/ubuntu/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go-1.24/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.6'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

package main

import (
	"crypto/tls"
	"fmt"
	"log"
	"net/http"
)

func main() {
	clientCert, err := tls.LoadX509KeyPair("certificate", "key")
	if err != nil {
		log.Fatalf("Failed to load client certificate: %v", err)
	}

	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{clientCert},
		ServerName:   "localhost",
	}
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: tlsConfig,
		},
	}
	resp, err := client.Get("https://localhost:8443/")
	if err != nil {
		log.Printf("TLS Error: %v", err)
		return
	}

	fmt.Printf("%v\n", resp.Status)
}

Example HAProxy configuration:

global
    daemon

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend mtls_frontend
    # Client certificate CA not present (remote error: tls: certificate required)
    bind *:8443 ssl crt /etc/ssl/certs/haproxy-server.pem verify required ca-file /etc/ssl/certs/USERTrust_RSA_Certification_Authority.pem
    # Client certificate CA present (success)
    #bind *:8443 ssl crt /etc/ssl/certs/haproxy-server.pem verify required ca-file /etc/ssl/certs/chain.pem
    default_backend web_servers

backend web_servers
    server web1 [127.0.0.1:8080](http://127.0.0.1:8080/) check

What did you see happen?

The crypto/tls library will not configure the client certificate if the signing certificate authority is not present in the list provided by the server in CertificateRequest. The current implementation causes the remote error: tls: certificate required error making debugging the underlying CA issue difficult.

What did you expect to see?

An error explaining the certificate is not in the list of trusted CAs provided by the server. This behaviour does not occur for mTLS with TLS v1.2. I raised this previously in the golang-nuts group:

https://groups.google.com/g/golang-nuts/c/Cyn1uulURkg

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions