Skip to content

What DefaultConfig sets

DefaultConfig() returns a fresh *crypto/tls.Config with three fields set and everything else left at its zero value. Every config the package hands out — Pair.ServerConfig and ClientConfig — starts from this function, so these values apply to both ends of a connection.

Each call returns a new config. Mutating one does not affect another.

The three fields it sets

Field Value
MinVersion tls.VersionTLS12 (0x0303, decimal 771)
CipherSuites six ECDHE-AEAD suites, listed below
CurvePreferences tls.X25519, then tls.CurveP256

The cipher suite list, in the order the source declares it:

Suite Constant value
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xc02c
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xc030
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xc02b
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xc02f
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 0xcca9
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 0xcca8

The reasoning behind each choice is in the threat model.

Which TLS version actually gets negotiated

MaxVersion is left at zero, which crypto/tls reads as "the highest version this Go toolchain supports". Two configs built from DefaultConfig negotiate TLS 1.3; MinVersion only sets the floor for peers that cannot do 1.3.

At TLS 1.3 the CipherSuites list has no effect — the 1.3 suites are fixed by the protocol and chosen by the runtime. A connection between two DefaultConfig peers therefore uses TLS_AES_128_GCM_SHA256, which is not in the list above and is not meant to be. The list governs TLS 1.2 connections.

Go also picks the mutually preferred suite itself; the list says which suites are permitted, not a server-dictated order.

Which fields DefaultConfig deliberately leaves alone

Everything not in the table above is the crypto/tls zero value. The ones worth knowing:

Field Left at Consequence
MaxVersion 0 Highest supported version — TLS 1.3 today
Certificates empty ServerConfig and ApplyTo append; ClientConfig never does
RootCAs nil Client trusts the system root store, unless ClientConfig was given CA files
ClientCAs / ClientAuth nil / NoClientCert No client-certificate auth until a Pair supplies one
InsecureSkipVerify false Certificate verification is on, and this package offers no way to turn it off
NextProtos empty No ALPN advertised until you pass protocols to ServerConfig or ApplyTo
SessionTicketsDisabled false TLS 1.2 session tickets stay enabled; no ticket key rotation is configured
ClientSessionCache nil The package configures no client-side session resumption
Renegotiation RenegotiateNever Renegotiation refused, the crypto/tls default
VerifyPeerCertificate / VerifyConnection nil No extra verification hooks; add your own and merge with ApplyTo
GetCertificate nil One static certificate per config; no SNI selection and no reload

Key exchange is weaker than Go's own default

Setting CurvePreferences explicitly opts out of the post-quantum hybrid key exchange that Go enables by default. With a nil CurvePreferences, Go 1.26 negotiates X25519MLKEM768. A config from DefaultConfig negotiates plain X25519, because that list does not include the hybrid.

This matters for traffic an attacker can record now and decrypt later, once a cryptographically relevant quantum computer exists. If that is in your threat model, clear the field on the config you get back:

cfg := tls.DefaultConfig()
cfg.CurvePreferences = nil // let Go choose, including X25519MLKEM768

Everything else — the TLS 1.2 floor and the AEAD-only suite list — survives, because they are separate fields.

What it is worth compared with a zero-value config

Go's own defaults have moved a long way, and much of what a hardened config used to buy is now standard. On Go 1.26 a zero-value tls.Config already refuses TLS 1.0 and 1.1 on both sides, and already excludes static-RSA key exchange from the suites it will negotiate.

Three things DefaultConfig still adds:

  • No CBC suites. Go's default TLS 1.2 suite list still contains four ECDHE-CBC-SHA suites (TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA and relatives). DefaultConfig drops them, leaving AEAD only.
  • A floor no GODEBUG can lower. Go's TLS 1.2 default floor is a default: GODEBUG=tls10server=1 restores TLS 1.0 on a zero-value server config. An explicit MinVersion is unaffected by that setting.
  • A fixed posture across toolchains. The stdlib default suite list changes between Go releases. This one changes when this package changes.

And one thing it costs: the post-quantum key exchange described above.