In June 2022, a vulnerability surfaced in the Go programming language’s TLS implementation (crypto/tls), tracked as CVE-2022-30629. This bug affected versions of Go released before 1.17.11 and 1.18.3. It’s a subtle but impactful flaw that lets an attacker link supposedly private, secure TLS sessions together. In this article, we’ll break down what CVE-2022-30629 is, how it can be exploited, and why it matters—even for everyday Go users.

What is CVE-2022-30629?

When a client connects to a server using TLS, sometimes both sides agree to resume an earlier session (for speed or convenience). The server sends a “ticket” with an associated random value called ticket_age_add. The client stores this, then, later, uses it to show how much time has passed since the ticket was issued (its “age”).

The problem in Go prior to versions 1.17.11 and 1.18.3 is that ticket_age_add wasn’t random — it was always the same for all session tickets on a given server startup. This broke a key privacy assumption: different session resumptions could be linked just by comparing ticket ages.

Why Should You Care?

This weakness enables attackers who can observe network traffic (like a coffee shop Wi-Fi eavesdropper, a state-level actor, or even your ISP) to connect the dots between your supposedly anonymous, distinct TLS sessions. That means:

Later, client reconnects and resumes session — sending back ticket, and its view of age.

4. Attacker watching both events can compare the ages sent, and try to deduce whether it's the "same" client.

Vulnerability trigger

If ticket_age_add is always the same, tickets from the same server instance will have correlated ages, which makes them linkable.

Code Example: The Flawed vs. Fixed Code

Here’s a simplified version of the Go bug. (Note: This is not the actual Go source, but it demonstrates the problem).

Vulnerable (Simplified)

// Older Go code before 1.17.11/1.18.3

type Server struct {
    ticketAgeAdd uint32 // BAD: not randomized per ticket
}

func (s *Server) IssueTLSTicket() SessionTicket {
    ticket := SessionTicket{}
    ticket.AgeAdd = s.ticketAgeAdd // always the same!
    // ...rest of ticket creation
    return ticket
}

Secure (After Patch)

import "crypto/rand"
import "encoding/binary"

type Server struct { }

func (s *Server) IssueTLSTicket() SessionTicket {
    ticket := SessionTicket{}
    randomBytes := make([]byte, 4)
    rand.Read(randomBytes)        // get 4 random bytes
    ticket.AgeAdd = binary.BigEndian.Uint32(randomBytes)  // now unique per ticket!
    // ...rest of ticket creation
    return ticket
}

Reference

- Go commit fixing the bug (GitHub)

Demonstration: Correlating TLS Sessions

Let’s say Alice connects twice to a Go server on a coffee shop’s Wi-Fi. Eve, on the same network, can do this:

Observe the first handshake: She sees a session ticket with ticket_age_add = xcafebabe.

2. Observe the second handshake: The client presents a ticket, and includes an age that’s offset by the same ticket_age_add.

If Eve observes many such sessions, she can start tagging them as “belonging to the same client,” even if Alice disconnects, reconnects, or gets a new IP.

Is this a Full-on Privacy Disaster?

It's not a catastrophic bug like Heartbleed, but it undercuts privacy promises TLS is supposed to make. Many sites and internal tools rely on Go's standard library for TLS—the issue affected anyone using session tickets without updating. For the privacy-conscious (think messaging apps, secure APIs, corporate single sign-on), that’s a big deal.


## How to Fix / Detect This Issue

Detecting it in code

Look for the creation of session tickets in custom TLS code. Ensure the value for ticket_age_add is a fresh, cryptographically random 4-byte integer for every ticket.

Official References

- Go Security Advisory - CVE-2022-30629
- NIST NVD Entry
- Go GitHub Commit Log

Conclusion

CVE-2022-30629 reminds us that even the smallest implementation mistakes can have real-world privacy impacts. While it didn’t let attackers immediately decrypt or modify your communications, it made linking separate sessions a breeze—and that’s enough to matter.

Patch your Go servers, audit your code, and keep an eye on your dependencies. One overlooked random value can punch a hole in your privacy armor.

Timeline

Published on: 08/10/2022 20:15:00 UTC
Last modified on: 08/19/2022 13:46:00 UTC