{"record":{"id":"5b4de15f6e17e4c4","repo":"golang/go","slug":"tls-malformed-encrypted-client-hello-extension-5b4de1","errorCode":null,"errorMessage":"tls: malformed encrypted client hello extension","messagePattern":"tls: malformed encrypted client hello extension","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client_tls13.go","lineNumber":260,"sourceCode":"\ths.transcript.Reset()\n\ths.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))})\n\ths.transcript.Write(chHash)\n\tif err := transcriptMsg(hs.serverHello, hs.transcript); err != nil {\n\t\treturn err\n\t}\n\n\tvar isInnerHello bool\n\thello := hs.hello\n\tif hs.echContext != nil {\n\t\tchHash = hs.echContext.innerTranscript.Sum(nil)\n\t\ths.echContext.innerTranscript.Reset()\n\t\ths.echContext.innerTranscript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))})\n\t\ths.echContext.innerTranscript.Write(chHash)\n\n\t\tif hs.serverHello.encryptedClientHello != nil {\n\t\t\tif len(hs.serverHello.encryptedClientHello) != 8 {\n\t\t\t\ths.c.sendAlert(alertDecodeError)\n\t\t\t\treturn errors.New(\"tls: malformed encrypted client hello extension\")\n\t\t\t}\n\n\t\t\tconfTranscript := cloneHash(hs.echContext.innerTranscript, hs.suite.hash)\n\t\t\thrrHello := make([]byte, len(hs.serverHello.original))\n\t\t\tcopy(hrrHello, hs.serverHello.original)\n\t\t\thrrHello = bytes.Replace(hrrHello, hs.serverHello.encryptedClientHello, make([]byte, 8), 1)\n\t\t\tconfTranscript.Write(hrrHello)\n\t\t\th := hs.suite.hash.New\n\t\t\tprk, err := hkdf.Extract(h, hs.echContext.innerHello.random, nil)\n\t\t\tif err != nil {\n\t\t\t\tc.sendAlert(alertInternalError)\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tacceptConfirmation := tls13.ExpandLabel(h, prk, \"hrr ech accept confirmation\", confTranscript.Sum(nil), 8)\n\t\t\tif subtle.ConstantTimeCompare(acceptConfirmation, hs.serverHello.encryptedClientHello) == 1 {\n\t\t\t\thello = hs.echContext.innerHello\n\t\t\t\tc.serverName = c.config.ServerName\n\t\t\t\tisInnerHello = true","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client_tls13.go#L242-L278","documentation":"Thrown during HelloRetryRequest ECH processing when the encrypted_client_hello extension in the ServerHello/HRR is present but not exactly 8 bytes long. The ECH accept confirmation value in an HRR must be exactly 8 bytes.","triggerScenarios":"Triggered when hs.echContext is not nil, hs.serverHello.encryptedClientHello is not nil, and len(hs.serverHello.encryptedClientHello) != 8 during HRR processing. The client sends alertDecodeError.","commonSituations":"Server bug in ECH HRR handling producing wrong-length confirmation. Mismatched ECH specification draft versions between client and server. Corrupted handshake message altering the extension length.","solutions":["Verify the server's ECH implementation produces exactly 8-byte accept confirmation in HelloRetryRequest.","Ensure client and server implement compatible ECH draft versions.","If ECH is not required, remove config.EncryptedClientHelloConfigList to disable ECH entirely.","Report the malformed extension to the server's ECH implementation maintainer."],"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(), \"malformed encrypted client hello extension\") {\n        // Server ECH HRR bug — disable ECH and retry\n        config.EncryptedClientHelloConfigList = nil\n        conn, err = tls.Dial(\"tcp\", addr, config)\n    }\n}","preventionTips":["Verify ECH draft version compatibility between client and server.","Disable ECH if the server's implementation is non-compliant.","Test ECH HRR paths specifically, as they are less commonly exercised."],"tags":["tls","go","ech","tls13","hello-retry-request","malformed"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}