{"record":{"id":"57135ec3ceec2549","repo":"golang/go","slug":"tls-client-using-inappropriate-protocol-fallback","errorCode":null,"errorMessage":"tls: client using inappropriate protocol fallback","messagePattern":"tls: client using inappropriate protocol fallback","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_server.go","lineNumber":416,"sourceCode":"func (hs *serverHandshakeState) pickCipherSuite() error {\n\tc := hs.c\n\n\tpreferenceList := c.config.cipherSuites(isAESGCMPreferred(hs.clientHello.cipherSuites))\n\n\ths.suite = selectCipherSuite(preferenceList, hs.clientHello.cipherSuites, hs.cipherSuiteOk)\n\tif hs.suite == nil {\n\t\tc.sendAlert(alertHandshakeFailure)\n\t\treturn fmt.Errorf(\"tls: no cipher suite supported by both client and server; client offered: %x\",\n\t\t\ths.clientHello.cipherSuites)\n\t}\n\tc.cipherSuite = hs.suite.id\n\n\tfor _, id := range hs.clientHello.cipherSuites {\n\t\tif id == TLS_FALLBACK_SCSV {\n\t\t\t// The client is doing a fallback connection. See RFC 7507.\n\t\t\tif hs.clientHello.vers < c.config.maxSupportedVersion(roleServer, c.quic != nil) {\n\t\t\t\tc.sendAlert(alertInappropriateFallback)\n\t\t\t\treturn errors.New(\"tls: client using inappropriate protocol fallback\")\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (hs *serverHandshakeState) cipherSuiteOk(c *cipherSuite) bool {\n\tif c.flags&suiteECDHE != 0 {\n\t\tif !hs.ecdheOk {\n\t\t\treturn false\n\t\t}\n\t\tif c.flags&suiteECSign != 0 {\n\t\t\tif !hs.ecSignOk {\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else if !hs.rsaSignOk {","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_server.go#L398-L434","documentation":"The client included TLS_FALLBACK_SCSV in its cipher suites but offered a version lower than the server's maximum supported version. Per RFC 7507, this sentinel signals intentional protocol downgrade protection; a legitimate downgrade should not occur, so the server rejects with inappropriate_fallback.","triggerScenarios":"pickCipherSuite iterates hs.clientHello.cipherSuites; finding TLS_FALLBACK_SCSV and hs.clientHello.vers < server's max supported version triggers alertInappropriateFallback.","commonSituations":"A client library that automatically retries with a lower TLS version after a failure and incorrectly sends FALLBACK_SCSV, a misconfigured proxy forcing downgrade, or a MITM attempting version rollback. Browser-style fallback mechanisms must only send SCSV when the downgrade is intentional AND no higher version works against this specific server.","solutions":["Stop forcing the downgrade — connect at the highest mutually supported version (TLS 1.3).","If a downgrade retry is genuinely needed, ensure the server also lacks support for the higher version; otherwise do not send FALLBACK_SCSV.","Remove middleware or proxies that cap MaxVersion below what the server supports.","Update the client's retry logic to not inject FALLBACK_SCSV on the initial connection attempt."],"exampleFix":"// before: client forces TLS 1.2 and signals fallback\ncfg := &tls.Config{\n    MaxVersion: tls.VersionTLS12,\n    // somewhere FALLBACK_SCSV is appended\n}\n\n// after: let the client negotiate the highest version\ncfg := &tls.Config{\n    MinVersion: tls.VersionTLS12,\n    // MaxVersion unset — defaults to highest supported","handlingStrategy":"validation","validationCode":"// Client: do not inject TLS_FALLBACK_SCSV unless performing an intentional\n// downgrade retry, and only after confirming the server does not support a\n// higher version.\n// Standard libraries handle this correctly — avoid manual SCSV injection.","typeGuard":null,"tryCatchPattern":"// Client: catch and stop the downgrade loop.\nif err != nil && strings.Contains(err.Error(), \"inappropriate protocol fallback\") {\n    // do NOT retry at an even lower version; report the failure\n    return err\n}","preventionTips":["Never cap MaxVersion below what the server supports.","Audit retry logic that lowers TLS versions on failure.","Remove proxies/middleware that force downgrades."],"tags":["tls","server-handshake","fallback-scsv","rfc-7507","version-downgrade","mitm-detection"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}