golang/go · error
tls: session supported extended_master_secret but client doe
Error message
tls: session supported extended_master_secret but client does not
What it means
During session resumption the server found that the cached session used extended_master_secret (RFC 7627) but the current ClientHello does not advertise it. This is an EMS downgrade — the spec mandates aborting because silently accepting would weaken the security of the resumed session.
Source
Thrown at src/crypto/tls/handshake_server.go:536
}
opts := x509.VerifyOptions{
CurrentTime: c.config.time(),
Roots: c.config.ClientCAs,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
if sessionHasClientCerts && c.config.ClientAuth >= VerifyClientCertIfGiven &&
!anyValidVerifiedChain(sessionState.verifiedChains, opts) {
return nil
}
// RFC 7627, Section 5.3
if !sessionState.extMasterSecret && hs.clientHello.extendedMasterSecret {
return nil
}
if sessionState.extMasterSecret && !hs.clientHello.extendedMasterSecret {
// Aborting is somewhat harsh, but it's a MUST and it would indicate a
// weird downgrade in client capabilities.
return errors.New("tls: session supported extended_master_secret but client does not")
}
if !sessionState.extMasterSecret && fips140tls.Required() {
if fips140ems.Value() != "0" {
// FIPS 140-3 requires the use of Extended Master Secret.
return nil
}
fips140ems.IncNonDefault()
}
c.peerCertificates = sessionState.peerCertificates
c.ocspResponse = sessionState.ocspResponse
c.scts = sessionState.scts
c.verifiedChains = sessionState.verifiedChains
c.extMasterSecret = sessionState.extMasterSecret
hs.sessionState = sessionState
hs.suite = suite
c.curveID = sessionState.curveID
c.didResume = trueView on GitHub (pinned to b6b368adc5)
Solutions
- Ensure the client consistently advertises extended_master_secret on every connection (most modern stacks do by default).
- Investigate middleware/proxies that strip EMS — they create exactly this downgrade.
- Invalidate and rotate session tickets if the client legitimately changed capabilities, so stale EMS-flagged tickets are not reused.
- Update the client TLS library to a version that always offers EMS.
Example fix
// Most modern Go/Rust/OpenSSL clients always advertise EMS. // If using a custom stack, ensure the extension is present: // - OpenSSL: enabled by default since 1.1.0 // - Go: always sent for TLS 1.2 // - Do not set any 'disable_extended_master_secret' flags
Defensive patterns
Strategy: validation
Validate before calling
// Client: always advertise extended_master_secret for TLS 1.2. // Go clients do this automatically. If using a custom stack, include the // extension and never disable it for sessions previously negotiated with EMS.
Try / catch
// Server: catch during resumption and force a full handshake instead.
if err != nil && strings.Contains(err.Error(), "session supported extended_master_secret but client does not") {
// invalidate cached ticket and require full handshake
sessionCache.Put(sessionKey, nil)
} Prevention
- Always advertise EMS consistently across all client connections.
- Rotate session tickets when client capabilities legitimately change.
- Audit middleboxes for EMS-stripping behavior.
When it happens
Trigger: In the server's session-resumption path: sessionState.extMasterSecret is true but hs.clientHello.extendedMasterSecret is false. The session was originally negotiated with EMS; the new ClientHello dropped the extension.
Common situations: A client that previously connected with EMS but is now configured (or downgraded) to omit it — possibly due to a library change, a middlebox stripping the extension, or a different client process reusing a cached ticket. Also a possible rollback attack vector.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: FIPS 140-3 requires the use of Extended Master Secret
- tls: downgrade attempt detected, possibly due to a MitM atta
- tls: server selected an invalid PSK
- tls: server selected an invalid PSK and cipher suite pair
- tls: received new session ticket from a client
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/95e7e3c8829a22b0.
Report an issue: GitHub.