golang/go · error

tls: received new session ticket from a client

Error message

tls: received new session ticket from a client

What it means

A TLS server received a NewSessionTicket message, which is a client-to-server-only artifact in TLS 1.3. Servers never process inbound NST messages; only clients do. The peer (which should be a client) sent the wrong message direction, indicating a malformed or malicious implementation. The server alerts unexpected_message.

Source

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

	}

	c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret)

	if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != nil {
		c.resumptionSecret = hs.masterSecret.ResumptionMasterSecret(hs.transcript)
	}

	if c.quic != nil {
		c.quicSetWriteSecret(QUICEncryptionLevelApplication, hs.suite.id, hs.trafficSecret)
	}

	return nil
}

func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error {
	if !c.isClient {
		c.sendAlert(alertUnexpectedMessage)
		return errors.New("tls: received new session ticket from a client")
	}

	if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil {
		return nil
	}

	// See RFC 8446, Section 4.6.1.
	if msg.lifetime == 0 {
		return nil
	}
	lifetime := time.Duration(msg.lifetime) * time.Second
	if lifetime > maxSessionTicketLifetime {
		c.sendAlert(alertIllegalParameter)
		return errors.New("tls: received a session ticket with invalid lifetime")
	}

	if len(msg.label) == 0 {
		c.sendAlert(alertDecodeError)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Treat as a peer implementation bug; disconnect and log the peer address for investigation.
  2. If a TLS-terminating proxy sits in front, verify it is not injecting or forwarding handshake messages incorrectly.
  3. If fuzzing, this is an expected rejection — assert it and move on.
  4. Upgrade or replace the offending peer TLS stack.
Defensive patterns

Strategy: validation

Validate before calling

// No caller-side validation possible; the message direction is enforced by
// the peer's TLS stack. Ensure you are not operating as a server expecting
// inbound NSTs.

Try / catch

// In a server handler, log and close the connection on this error.
if err := conn.Read(...); err != nil {
    if strings.Contains(err.Error(), "received new session ticket from a client") {
        log.Warn("peer sent server-only message; likely malicious or buggy",
            "remote", conn.RemoteAddr())
        conn.Close()
    }
}

Prevention

When it happens

Trigger: handleNewSessionTicket is invoked on a Conn where c.isClient is false — i.e. the server-side connection received a newSessionTicketMsgTLS13 from the network peer. This requires the peer to actively transmit an NST on a server-facing connection.

Common situations: A buggy or malicious TLS client sending server-only messages, a misbehaving TLS proxy/terminator that forwards messages in the wrong direction, or a fuzz tester hitting the server with arbitrary handshake messages. Legitimate TLS clients never send NSTs.

Understand the failure class

Related errors


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