{"record":{"id":"038de60bfd6f373f","repo":"caddyserver/caddy","slug":"invalid-kdf-id-d","errorCode":null,"errorMessage":"invalid KDF ID: %d","messagePattern":"invalid KDF ID: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/ech.go","lineNumber":1013,"sourceCode":"\tif !echCfg.KEMID.IsValid() {\n\t\treturn fmt.Errorf(\"invalid KEM ID: %d\", echCfg.KEMID)\n\t}\n\n\tvar err error\n\tif echCfg.PublicKey, err = echCfg.KEMID.Scheme().UnmarshalBinaryPublicKey(pk); err != nil {\n\t\treturn fmt.Errorf(\"parsing public_key: %w\", err)\n\t}\n\n\techCfg.CipherSuites = echCfg.CipherSuites[:0]\n\n\tfor !t.Empty() {\n\t\tvar hpkeKDF, hpkeAEAD uint16\n\t\tif !t.ReadUint16(&hpkeKDF) || !t.ReadUint16(&hpkeAEAD) {\n\t\t\t// we have already checked that the length is divisible by 4\n\t\t\tpanic(\"this must not happen\")\n\t\t}\n\t\tif !hpke.KDF(hpkeKDF).IsValid() {\n\t\t\treturn fmt.Errorf(\"invalid KDF ID: %d\", hpkeKDF)\n\t\t}\n\t\tif !hpke.AEAD(hpkeAEAD).IsValid() {\n\t\t\treturn fmt.Errorf(\"invalid AEAD ID: %d\", hpkeAEAD)\n\t\t}\n\t\techCfg.CipherSuites = append(echCfg.CipherSuites, hpkeSymmetricCipherSuite{\n\t\t\tKDFID:  hpke.KDF(hpkeKDF),\n\t\t\tAEADID: hpke.AEAD(hpkeAEAD),\n\t\t})\n\t}\n\n\tvar rawPublicName []byte\n\tif !content.ReadUint8(&echCfg.MaxNameLength) ||\n\t\t!content.ReadUint8LengthPrefixed(&t) ||\n\t\t!t.ReadBytes(&rawPublicName, len(t)) ||\n\t\t!content.ReadUint16LengthPrefixed(&t) ||\n\t\t!t.ReadBytes(&echCfg.RawExtensions, len(t)) ||\n\t\t!content.Empty() {\n\t\treturn errInvalidLen","sourceCodeStart":995,"sourceCodeEnd":1031,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/ech.go#L995-L1031","documentation":"ECH config decoding iterates the length-prefixed list of (KDF, AEAD) cipher suite pairs (each 4 bytes). Each KDF ID is validated with hpke.KDF(id).IsValid(); Caddy writes KDF_HKDF_SHA256 (0x0001) and KDF_HKDF_SHA512 may exist depending on the linked hpke version. An unrecognized numeric KDF ID aborts parsing with the offending value.","triggerScenarios":"UnmarshalBinary over data whose cipher-suite list contains a KDF ID unknown to the linked hpke package — corrupt bytes or an ECH config from an implementation using KDFs Go's hpke doesn't register.","commonSituations":"Corrupted storage blobs; consuming cross-implementation ECH configs that include HKDF-SHA384 or other KDFs; version skew between Caddy builds with different hpke versions.","solutions":["Remove the malformed stored ECH configs (ech/configs/*) to regenerate with the standard SHA-256 KDF.","Regenerate external configs restricting suites to HKDF-SHA256-based ones.","Upgrade Caddy so its hpke dependency recognizes the KDF if it's a legitimate newer ID."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"invalid KDF ID\") {\n    // prune stored configs; regenerate with standard HKDF-SHA256 suites\n}","preventionTips":["Don't hand-craft ECH config binaries; let Caddy generate them.","Keep the hpke dependency set consistent across builds."],"tags":["tls","ech","crypto","hpke","serialization"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}