🇰🇷 한글 설명
Kafka Streams의 PunctuationSchedule.next()에서 타임스탬프 계산 시 오버플로우 검사가 없어, Long.MAX_VALUE 근처의 타임스탬프를 가진 레코드 하나로 StreamThread가 무한 루프에 빠져 처리가 중단됩니다. 해당 레코드가 토픽에 남아 있으면 재시작 후에도 문제가 반복됩니다.
💡 쉬운 설명
Kafka Streams 애플리케이션이 특정 시각값을 가진 메시지 하나를 만나면 처리 스레드가 멈춰버리는 결함입니다. 메시지가 토픽에 남아 있으면 재시작해도 같은 문제가 반복됩니다.
🇺🇸 원문 (English)
Kafka Streams derives its stream-time clock from record timestamps. PunctuationSchedule.next() computed the next punctuation time as timestamp + (intervalsMissed + 1) * interval with no overflow check. A record with a timestamp at or near Long.MAX_VALUE advances stream time to that value, so the next stream-time punctuation overflows to a negative time. PunctuationQueue then re-queues that time and loops on it indefinitely while holding a lock, stalling the StreamThread.
Impact:
A single record is enough. The affected StreamThread stops processing, and because the record stays in the topic the hang returns on restart; an application whose partitions are all affected becomes unresponsive. Only the Streams application is affected, not the brokers or the cluster. Triggering it needs write access to a source topic whose topology uses stream-time punctuation, and a broker that stores the record: brokers from Apache Kafka 4.0.0 reject such a timestamp by default (log.message.timestamp.after.max.ms, one hour), so it is reachable only on older brokers or where that bound has been relaxed.
Mitigation:
Upgrade Kafka Streams to 4.2.2, 4.3.2, or 4.4.0. As defense in depth, keep log.message.timestamp.after.max.ms bounded on source topics and restrict write access to them.
Resolution:
From Apache Kafka 4.2.2, 4.3.2, and 4.4.0: the next punctuation time is computed with overflow-checked arithmetic (clamped to Long.MAX_VALUE), and a rescheduled punctuation is re-queued only when its time moves forward.
📍 영향받는 시스템
Apache Kafka Streams 4.2.2 미만, 4.3.2 미만, 4.4.0 미만 버전 (스트림 시간 기반 punctuation을 사용하는 애플리케이션)
⚔️ 공격 벡터
소스 토픽에 쓰기 권한이 있는 공격자가 Long.MAX_VALUE 근처의 타임스탬프를 가진 레코드 하나를 기록하고, 브로커가 이를 거부하지 않을 때 발생합니다.
🛡️ 대응 방법
Kafka Streams를 4.2.2, 4.3.2, 4.4.0 이상으로 업그레이드하고, 소스 토픽의 log.message.timestamp.after.max.ms를 제한하며 쓰기 권한을 제한하세요.
🔧 검증 코드
출력된 jar 파일명의 버전이 4.2.2, 4.3.2, 4.4.0 이상이면 패치된 것이고, 그보다 낮은 버전이면 취약합니다. 출력이 없으면 해당 경로에 Kafka Streams가 설치되어 있지 않은 것입니다.
find / -name 'kafka-streams*.jar' 2>/dev/null | xargs -I{} basename {}