{"record":{"id":"611506d5dc882964","repo":"golang/go","slug":"tls-server-sent-an-incorrect-legacy-version","errorCode":null,"errorMessage":"tls: server sent an incorrect legacy version","messagePattern":"tls: server sent an incorrect legacy version","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client_tls13.go","lineNumber":180,"sourceCode":"\n// checkServerHelloOrHRR does validity checks that apply to both ServerHello and\n// HelloRetryRequest messages. It sets hs.suite.\nfunc (hs *clientHandshakeStateTLS13) checkServerHelloOrHRR() error {\n\tc := hs.c\n\n\tif hs.serverHello.supportedVersion == 0 {\n\t\tc.sendAlert(alertMissingExtension)\n\t\treturn errors.New(\"tls: server selected TLS 1.3 using the legacy version field\")\n\t}\n\n\tif hs.serverHello.supportedVersion != VersionTLS13 {\n\t\tc.sendAlert(alertIllegalParameter)\n\t\treturn errors.New(\"tls: server selected an invalid version after a HelloRetryRequest\")\n\t}\n\n\tif hs.serverHello.vers != VersionTLS12 {\n\t\tc.sendAlert(alertIllegalParameter)\n\t\treturn errors.New(\"tls: server sent an incorrect legacy version\")\n\t}\n\n\tif hs.serverHello.ocspStapling ||\n\t\ths.serverHello.ticketSupported ||\n\t\ths.serverHello.extendedMasterSecret ||\n\t\ths.serverHello.secureRenegotiationSupported ||\n\t\tlen(hs.serverHello.secureRenegotiation) != 0 ||\n\t\tlen(hs.serverHello.alpnProtocol) != 0 ||\n\t\tlen(hs.serverHello.scts) != 0 {\n\t\tc.sendAlert(alertUnsupportedExtension)\n\t\treturn errors.New(\"tls: server sent a ServerHello extension forbidden in TLS 1.3\")\n\t}\n\n\tif !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {\n\t\tc.sendAlert(alertIllegalParameter)\n\t\treturn errors.New(\"tls: server did not echo the legacy session ID\")\n\t}\n","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client_tls13.go#L162-L198","documentation":"Thrown in checkServerHelloOrHRR() when the ServerHello's legacy_version field is not 0x0303 (TLS 1.2). RFC 8446 section 4.1.3 mandates that TLS 1.3 ServerHello messages use 0x0303 in the legacy_version field for backward compatibility with middleboxes.","triggerScenarios":"Triggered when hs.serverHello.vers != VersionTLS12 (0x0303). The client sends alertIllegalParameter. The server used an incorrect value such as 0x0301 (TLS 1.0), 0x0302 (TLS 1.1), or 0x0304 (TLS 1.3) in the legacy field.","commonSituations":"Non-compliant server using the actual negotiated version (0x0304) in the legacy field instead of 0x0303. Server implementation that doesn't follow RFC 8446 backward-compatibility requirements. Old server software updated partially for TLS 1.3.","solutions":["Server must set legacy_version to 0x0303 in TLS 1.3 ServerHello per RFC 8446 section 4.1.3.","Report as a server-side compliance bug.","If the server cannot be fixed, restrict the client to TLS 1.2.","Test with: openssl s_client -connect host:443 -tls1_3 to see if OpenSSL also rejects it."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"conn, err := tls.Dial(\"tcp\", addr, config)\nif err != nil {\n    if strings.Contains(err.Error(), \"incorrect legacy version\") {\n        // Server doesn't follow RFC 8446 — fall back to TLS 1.2\n        config.MaxVersion = tls.VersionTLS12\n        conn, err = tls.Dial(\"tcp\", addr, config)\n    }\n}","preventionTips":["Verify server compliance with RFC 8446 using TLS compliance scanners.","Report incorrect legacy_version usage to server vendors.","Keep a TLS 1.2 fallback path for legacy servers."],"tags":["tls","go","tls13","version-negotiation","protocol-violation","rfc8446"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}