golang/go · error

tls: malformed key_share extension

Error message

tls: malformed key_share extension

What it means

In a normal ServerHello, the key_share extension carries the server's share but must NOT also include the selectedGroup field (that field is HRR-only per RFC 8446 §4.2.8). Go treats a non-zero selectedGroup here as a malformed message and sends `decode_error`. The server is encoding the extension incorrectly.

Source

Thrown at src/crypto/tls/handshake_client_tls13.go:427

	return nil
}

func (hs *clientHandshakeStateTLS13) processServerHello() error {
	c := hs.c

	if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) {
		c.sendAlert(alertUnexpectedMessage)
		return errors.New("tls: server sent two HelloRetryRequest messages")
	}

	if len(hs.serverHello.cookie) != 0 {
		c.sendAlert(alertUnsupportedExtension)
		return errors.New("tls: server sent a cookie in a normal ServerHello")
	}

	if hs.serverHello.selectedGroup != 0 {
		c.sendAlert(alertDecodeError)
		return errors.New("tls: malformed key_share extension")
	}

	if hs.serverHello.serverShare.group == 0 {
		c.sendAlert(alertIllegalParameter)
		return errors.New("tls: server did not send a key share")
	}
	if !slices.ContainsFunc(hs.hello.keyShares, func(ks keyShare) bool {
		return ks.group == hs.serverHello.serverShare.group
	}) {
		c.sendAlert(alertIllegalParameter)
		return errors.New("tls: server selected unsupported group")
	}

	if !hs.serverHello.selectedIdentityPresent {
		return nil
	}

	if int(hs.serverHello.selectedIdentity) >= len(hs.hello.pskIdentities) {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Report the malformed extension to the server operator.
  2. Verify with a packet capture which side injects selectedGroup into the ServerHello.
  3. Test against a reference Go tls.Server peer to localise the fault.
  4. Patch the server's key_share encoder to use the ServerHello shape (server_share only).
Defensive patterns

Strategy: try-catch

Try / catch

if err := conn.Handshake(); err != nil {
    if strings.Contains(err.Error(), "malformed key_share extension") {
        log.Printf("peer sent selected_group in a non-HRR ServerHello: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: ServerHello.selectedGroup != 0 in processServerHello. Means the server put the HRR-shaped key_share (with selected_group) into a normal ServerHello.

Common situations: Hand-rolled or buggy TLS 1.3 server, fuzz traffic, or a middlebox that rewrites the key_share extension. Stock compliant servers never produce this.

Understand the failure class

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/3ae1f5edceb4961c. Report an issue: GitHub.