{"record":{"id":"a564ff22b98a614c","repo":"shadow1ng/fscan","slug":"invalid-kafka-response-length-d","errorCode":null,"errorMessage":"invalid kafka response length: %d","messagePattern":"invalid kafka response length: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/kafka.go","lineNumber":191,"sourceCode":"\tbinary.BigEndian.PutUint16(buf[6:8], uint16(apiVersion))\n\tbinary.BigEndian.PutUint32(buf[8:12], uint32(corrID))\n\tbinary.BigEndian.PutUint16(buf[12:14], uint16(len(clientID)))\n\tcopy(buf[14:], clientID)\n\tcopy(buf[14+len(clientID):], body)\n\n\t_, err := conn.Write(buf)\n\treturn err\n}\n\nfunc kafkaRecv(conn io.Reader) ([]byte, error) {\n\t// 读取 4 字节长度\n\tlenBuf := make([]byte, 4)\n\tif _, err := io.ReadFull(conn, lenBuf); err != nil {\n\t\treturn nil, err\n\t}\n\tmsgLen := int(binary.BigEndian.Uint32(lenBuf))\n\tif msgLen < 4 {\n\t\treturn nil, fmt.Errorf(\"invalid kafka response length: %d\", msgLen)\n\t}\n\tif msgLen > maxKafkaResponseSize {\n\t\treturn nil, fmt.Errorf(\"kafka response too large: %d\", msgLen)\n\t}\n\t// 读取消息体\n\tmsg := make([]byte, msgLen)\n\tif _, err := io.ReadFull(conn, msg); err != nil {\n\t\treturn nil, err\n\t}\n\t// 跳过 correlation_id (4B)，返回 body\n\treturn msg[4:], nil\n}\n\nfunc kafkaString(s string) []byte {\n\tb := []byte(s)\n\tbuf := make([]byte, 2+len(b))\n\tbinary.BigEndian.PutUint16(buf, uint16(len(b)))\n\tcopy(buf[2:], b)","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/kafka.go#L173-L209","documentation":"kafkaRecv reads a 4-byte big-endian length prefix and rejects any declared message length below 4. A Kafka response frame must contain at least its own 4-byte correlation-id; anything smaller is a protocol violation or not a Kafka response at all. This protects the parser from garbage data.","triggerScenarios":"kafkaRecv (called by doKafkaAuth, identifyService, and unit tests): the connection returns a length prefix whose uint32 value is 0..3 — garbage banner from a non-Kafka service, desynced stream, or corrupt frame.","commonSituations":"Scanning a port that is not actually Kafka (HTTP server echoing short responses); reading a response mid-stream so the 4 bytes are misaligned with the frame boundary; a proxy mangling the framing.","solutions":["Verify the target port is a Kafka broker (run identifyService or a version probe first)","Re-sync the stream: if framing desync is suspected, reconnect instead of continuing to read","Log the raw 4 length bytes when this fires to diagnose non-Kafka responses","Keep this as a hard validation; do not loosen the <4 check"],"exampleFix":"// before\nmsgLen := int(binary.BigEndian.Uint32(lenBuf))\nif msgLen < 4 {\n    return nil, fmt.Errorf(\"invalid kafka response length: %d\", msgLen)\n}\n// after\nmsgLen := int(binary.BigEndian.Uint32(lenBuf))\nif msgLen < 4 {\n    return nil, fmt.Errorf(\"invalid kafka response length: %d (not a kafka response; raw=% x)\", msgLen, lenBuf)\n}","handlingStrategy":"type-guard","validationCode":"// Identify the service before parsing frames\nif !identifyService(conn) {\n    return fmt.Errorf(\"target does not speak the Kafka protocol\")\n}","typeGuard":"func isValidKafkaFrameLen(lenBuf []byte) bool {\n    l := binary.BigEndian.Uint32(lenBuf)\n    return l >= 4 && l <= maxKafkaResponseSize\n}","tryCatchPattern":"resp, err := kafkaRecv(conn)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid kafka response length\") {\n        log.Println(\"not a kafka response or desynced stream; reconnect and re-identify service\")\n        return\n    }\n    return err\n}","preventionTips":["Run service identification before Kafka frame parsing","Reconnect after any framing violation; never continue a desynced stream","Log the raw length bytes when validation fails for diagnosis","Scan only ports already identified as Kafka"],"tags":["kafka","protocol","framing","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}