Safeguard
Security Guides•

What should you set in a Go tls.Config for a service?

For most Go services, set tls.Config MinVersion explicitly, leave CipherSuites nil, and never ship InsecureSkipVerify. Here is what each field does.

Safeguard Security Team
4 min read

For most Go services, set MinVersion in tls.Config explicitly, leave CipherSuites nil so Go chooses a safe list, and never ship InsecureSkipVerify. Go documents TLS 1.2 as the current default minimum, but writing it in code keeps behaviour stable across upgrades and makes review easy.

What the documentation says

The crypto/tls documentation states that "by default, TLS 1.2 is currently used as the minimum" and that TLS 1.0 is the lowest version the package supports. Because "currently" can change with a Go release, an explicit value documents your intent.

On cipher suites, the docs say the CipherSuites list covers TLS 1.0 to 1.2, that "the order of the list is ignored", and that "TLS 1.3 ciphersuites are not configurable". If the field is nil, "a safe default list is used". PreferServerCipherSuites is marked as a legacy field with no effect.

Field by field

FieldRecommendationReason
MinVersionSet to tls.VersionTLS12, or TLS 1.3 if all clients support itExplicit and reviewable
CipherSuitesLeave nilGo picks a safe list, and TLS 1.3 suites are fixed anyway
PreferServerCipherSuitesDo not setDocumented as ignored
InsecureSkipVerifyNever in productionDisables chain and hostname checks, enabling machine in the middle attacks
Certificates or GetCertificateUse GetCertificate for rotationLets you serve a new certificate without a restart

Choosing TLS 1.3 only is reasonable for internal service to service traffic where you control both ends. For public endpoints, check your client mix first. The related post on TLS 1.3 versus TLS 1.2 and what to disable covers that decision.

InsecureSkipVerify, the field to grep for

The docs warn that with InsecureSkipVerify set, "TLS is susceptible to machine-in-the-middle attacks unless custom verification is used", and that it should be used only for testing or together with VerifyConnection or VerifyPeerCertificate. A common failure is a test flag that quietly ships. Add a lint or code scan rule that fails the build on it. See also what to do instead of disabling TLS verification.

Example

cfg := &tls.Config{
    MinVersion: tls.VersionTLS12,
    GetCertificate: certReloader.GetCertificate,
}
srv := &http.Server{
    Addr:      ":8443",
    Handler:   mux,
    TLSConfig: cfg,
}

One more rule from the docs: after a Config has been passed to a TLS function it must not be modified. Build it fully first, and do not tweak fields on a live server.

Steps

  1. Set MinVersion in every server and client Config.
  2. Remove CipherSuites unless a compliance requirement forces a list.
  3. Search the repository for InsecureSkipVerify and remove or justify each hit.
  4. Use GetCertificate or a reloading wrapper so certificate rotation does not need a restart.
  5. Test the endpoint with an external TLS scanner and a client that offers only old versions.

Try it yourself

Click through it at your own pace, or open it full screen. See how a scan inspects a live endpoint from outside, including its TLS setup.

Quick check

Do I need to list TLS 1.3 cipher suites?

No. The Go docs say TLS 1.3 cipher suites are not configurable.

Is MinVersion needed if the default is already TLS 1.2?

It is not required today, but it documents intent and protects you if a future default changes or a dependency builds its own Config.

Safeguard's dependency scanning and SBOM generation cover the Go modules your service builds from, with reachability analysis to separate reachable findings, and the free scan is at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.