TECH 으로 돌아가기
TECH HACKER NEWS 8분 읽기 34 READS

클라우드플레어 GLM 5.3 KV 캐시 유출 사고가 남긴 교훈

클라우드플레어 GLM 5.3 KV 캐시 유출 사고가 남긴 교훈
SOURCE IMAGE · HACKER NEWS

클라우드플레어는 Workers AI에서 제공하던 GLM 5.3 모델(@cf/zai-org/glm-5.3)에서 서로 다른 사용자의 요청 데이터가 섞여 응답에 노출되는 테넌트 격리 문제가 있었다고 공개했다. 문제는 2026년 8월 27일 모델 출시 시점부터 존재했고, 9월 8일 Knostic 소속 보안 연구원 가디 에브론(Gadi Evron)이 HackerOne 프로그램을 통해 제보하면서 드러났다. 클라우드플레어는 다음 날 아침 문제를 재현했고 사고를 선언한 지 40분 만에 모델을 비공개 전환한 뒤, 같은 날 수정 설정과 패치된 추론 엔진을 배포해 9월 9일 서비스를 복구했다. 영향받은 응답은 총 155건으로 모두 681,280토큰을 넘는 긴 프롬프트였으며, 회사는 다른 모델은 영향받지 않았고 고의적 악용 정황도 발견하지 못했다고 밝혔다.

설정 불일치와 엔진 버그가 겹친 구조

이번 사고는 두 가지 문제가 겹쳐 발생했다. 첫째는 오픈소스 추론 엔진 SGLang의 설정 불일치다. 클라우드플레어는 GLM 5.3을 1,048,576토큰 컨텍스트 윈도로 배포했지만, 프리필(prefill) GPU의 KV 캐시 풀은 681,280토큰만 수용할 수 있었다. 회사는 출시 전 이 불일치를 인지하고 있었으나, 처리할 수 없는 프롬프트에 대해 엔진이 오류를 반환할 것이라 기대했고 장문맥 테스트에서 성공 응답이 나왔기 때문에 문제로 보지 않았다.

둘째는 프리필과 디코드를 분리한 분산(disaggregated) 모드에서 SGLang이 길이 초과 요청을 처리하는 방식의 버그였다. 풀에 들어가지 않는 프롬프트는 내부적으로 거부 처리되어 1토큰짜리 자리표시자로 교체되는데, 요청을 중단하고 클라이언트 오류를 반환하는 대신 프리필이 이 자리표시자의 KV 캐시를 생성해 디코드 노드로 전송했다. 디코드 노드는 '전송 완료' 메시지를 받고 이전 요청의 캐시가 새 프롬프트로 덮어씌워졌다고 가정했지만, 실제로는 과거 상태 대부분이 그대로 남아 있었다. 결국 디코드 노드는 다른 사용자의 데이터가 담긴 낡은 캐시 페이지를 참조하며 응답을 생성했다.

왜 테스트에서 걸러지지 않았나

SGLang은 KV 캐시 풀 크기를 설정값으로 받지 않고, 모델 가중치를 올린 뒤 남은 GPU 메모리에서 시작 시점에 자동으로 산정한다. 반면 모델의 컨텍스트 길이는 별개의 설정값이라 둘이 일치한다는 보장이 없고, 이를 확인하는 것은 운영자의 몫이다. 클라우드플레어는 사전 테스트에서 HTTP 응답 코드와 성능만 검증했을 뿐 실제 출력의 정합성은 확인하지 않았다. 스트리밍 응답에 오류 프레임이 없었기에 엔진이 차이를 알아서 처리한다고 가정한 것이 핵심적인 공백이었다. 회사는 이제 분산 배포를 변경하기 전에 실행 중인 엔진에서 KV 풀 크기와 컨텍스트 길이를 직접 대조하도록 절차를 바꿨다.

KV 캐시 페이지는 요청 사이에 0으로 초기화되지 않고 다음 요청이 그냥 덮어쓴다. 이는 성능을 위해 다수 추론 엔진이 쓰는 방식이지만, 그만큼 페이지 소유권과 수명 추적을 엔진이 정확히 책임져야 한다는 뜻이다. 특히 분산 구조에서는 원격 프리필 노드가 같은 페이지에 대한 쓰기 참조를 동시에 들고 있어 추적이 더 까다롭다.

설정과 엔진 양쪽을 모두 손보다

복구 과정에서 클라우드플레어는 두 갈래로 대응했다. 우선 GLM 5.3 설정을 GLM 5.2와 동일하게 맞춰 GPU 메모리를 확보했고, 그 결과 프리필 KV 풀이 약 204만 토큰까지 늘어 컨텍스트 길이의 두 배가 됐다. 유효한 요청이라면 항상 풀에 들어가므로 거부 경로 자체가 호출되지 않아 버그가 발현되지 않는다. 다만 양자화, 텐서 병렬화, CUDA 그래프 크기, 향후 모델 버전 변경 등으로 풀 크기는 쉽게 달라질 수 있어 풀 크기에만 의존하는 방식은 취약하다. 그래서 거부 대기 중인 요청이 부트스트랩이나 메모리 할당, KV 전송 이전 단계인 분산 수용 큐에서 원래 오류와 함께 폐기되도록 엔진을 패치하고 이를 업스트림 #38704로 제안했다. 디코드 노드가 예약한 토큰 수와 실제 전송된 토큰 수를 대조하는 검증도 포함됐다.

이 결함은 이미 다른 사용자가 7월 6일 이슈 #30233으로 보고한 바 있으며, 클라우드플레어는 조사 과정에서 이를 확인했다. 관련 수정은 SGLang v0.5.20에 반영됐고 v0.5.21, v0.5.22에서 후속 보완이 이뤄졌다. 회사는 SGLang에 의존하는 모든 운영자에게 v0.5.22 이상으로 업데이트할 것을 강력히 권고했다.

실무자가 눈여겨볼 지점

이번 사고는 LLM 추론 인프라를 직접 운영하는 조직에 몇 가지 분명한 시사점을 준다. 첫째, 설정 불일치를 인지하고도 '엔진이 알아서 막아줄 것'이라고 가정한 지점이 사고의 출발점이었다는 사실이다. 둘째, HTTP 200과 정상 스트리밍만으로는 응답의 정합성을 보장할 수 없으며, 특히 멀티테넌트 환경에서는 출력 내용 자체를 카나리 마커 등으로 검증해야 한다. 셋째, 성능을 위해 메모리를 초기화하지 않고 재사용하는 설계는 격리 책임을 엔진 로직에 전가하는 만큼, 경계 조건과 오류·중단 경로가 테넌트 간 데이터를 섞지 않는지 집중적으로 점검해야 한다.

클라우드플레어는 이 버그가 페이지가 아직 사용 중인데 해제·재사용·읽히는 KV 캐시 메모리 안전성 문제군에 속하며, 노드 내 페이지 수명 문제와 노드 간 경쟁 상태라는 두 유형을 수개월째 다뤄왔다고 설명했다. 이번 사례는 타이밍상의 우연이 아니라 거부된 요청이 매번 전달 경로를 통과했다는 점에서 기존 유형들과 달랐지만, 디코드가 자기 요청이 쓰지 않은 페이지를 읽는다는 결과는 동일했다. 다만 이번 보고서는 사내 조사와 연구원 재현에 기반한 것으로, 155건이라는 수치는 확인된 영향 범위이며 공격이 전혀 없었다는 단정이라기보다 '고의적 악용 증거를 찾지 못했다'는 정도로 읽는 편이 정확하다. 자체 추론 스택을 운영하는 팀이라면 SGLang 버전 점검과 더불어 배포 전 KV 풀·컨텍스트 길이 대조를 상시 절차로 두는 것이 현실적인 교훈이다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://blog.cloudflare.com/kv-cache-exposure-remediation/
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...