{"record":{"id":"d49e23fa6233a841","repo":"fatedier/frp","slug":"selected-crypto-algorithm-was-not-advertised-by-cl","errorCode":null,"errorMessage":"selected crypto algorithm was not advertised by client: %s","messagePattern":"selected crypto algorithm was not advertised by client: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proto/wire/crypto.go","lineNumber":110,"sourceCode":"func ValidateServerHelloForClient(clientHello ClientHello, serverHello ServerHello) error {\n\tif serverHello.Selected.Message.Codec != MessageCodecJSON {\n\t\treturn fmt.Errorf(\"unsupported selected message codec: %s\", serverHello.Selected.Message.Codec)\n\t}\n\tudpPacketCodec := serverHello.Selected.Message.UDPPacketCodec\n\tif udpPacketCodec != \"\" {\n\t\tif udpPacketCodec != UDPPacketCodecBinary {\n\t\t\treturn fmt.Errorf(\"unsupported selected UDP packet codec: %s\", udpPacketCodec)\n\t\t}\n\t\tif !Supports(clientHello.Capabilities.Message.UDPPacketCodecs, udpPacketCodec) {\n\t\t\treturn fmt.Errorf(\"selected UDP packet codec was not advertised by client: %s\", udpPacketCodec)\n\t\t}\n\t}\n\tcryptoSelection := serverHello.Selected.Crypto\n\tif !IsSupportedAEADAlgorithm(cryptoSelection.Algorithm) {\n\t\treturn fmt.Errorf(\"unknown selected crypto algorithm: %s\", cryptoSelection.Algorithm)\n\t}\n\tif !Supports(clientHello.Capabilities.Crypto.Algorithms, cryptoSelection.Algorithm) {\n\t\treturn fmt.Errorf(\"selected crypto algorithm was not advertised by client: %s\", cryptoSelection.Algorithm)\n\t}\n\tif len(cryptoSelection.ServerRandom) != CryptoRandomSize {\n\t\treturn fmt.Errorf(\"invalid crypto server random length %d, want %d\", len(cryptoSelection.ServerRandom), CryptoRandomSize)\n\t}\n\treturn nil\n}\n\nfunc selectUDPPacketCodec(codecs []string) string {\n\tif Supports(codecs, UDPPacketCodecBinary) {\n\t\treturn UDPPacketCodecBinary\n\t}\n\treturn \"\"\n}\n\nfunc NewCryptoContext(algorithm string, clientHelloPayload, serverHelloPayload []byte) *CryptoContext {\n\treturn &CryptoContext{\n\t\tAlgorithm:      algorithm,\n\t\tTranscriptHash: HashCryptoTranscript(clientHelloPayload, serverHelloPayload),","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/proto/wire/crypto.go#L92-L128","documentation":"Thrown by ValidateServerHelloForClient when the server selects a crypto algorithm that, while known, was never offered by this client in ClientHello.Capabilities.Crypto.Algorithms. It is an anti-downgrade / anti-surprise guard: the server must pick from what the client advertised.","triggerScenarios":"Client advertises only [\"xchacha20-poly1305\"] but the server responds with Selected.Crypto.Algorithm = \"aes-256-gcm\" — the algorithm is valid but Supports(clientHello.Capabilities.Crypto.Algorithms, ...) is false.","commonSituations":"Server-side selection logic that ignores client capabilities (e.g. always preferring aes-256-gcm on hardware with AES-NI); test fixtures where client and server hellos are constructed separately; a tampering middlebox changing the algorithm field.","solutions":["On the server, always select through SelectAEADAlgorithm(clientHello.Capabilities.Crypto.Algorithms) which iterates the client's own list.","On the client, send the full PreferredAEADAlgorithms() list so any reasonable server choice is covered.","Regenerate paired hello fixtures from a single handshake helper in tests."],"exampleFix":"// before (client, restrictive)\nhello.Capabilities.Crypto.Algorithms = []string{\"xchacha20-poly1305\"}\n\n// after\nhello.Capabilities.Crypto.Algorithms = wire.PreferredAEADAlgorithms()","handlingStrategy":"validation","validationCode":"offered := clientHello.Capabilities.Crypto.Algorithms\nselected := serverHello.Selected.Crypto.Algorithm\nif !wire.Supports(offered, selected) {\n    return fmt.Errorf(\"server selected %q which client never offered\", selected)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clients: send the full PreferredAEADAlgorithms() list so any server preference is valid.","Servers: never let local config override client-advertised capabilities."],"tags":["crypto","handshake","capabilities","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}