FlawOpen

flawopen.com/Teardowns/cve-2026-105752-vllm-harmony-cache-salt-omission

● CVE-2026-105752 · CVSS 3.1 · 낮음
보안 연구 · FlawOpen

CVE-2026-105752: vLLM의 cache_salt 누락

vLLM Responses의 GPT-OSS 도구 후속 처리는 cache_salt를 누락해 salt 없는 prefix-cache 네임스페이스를 사용할 수 있었습니다. vLLM 0.30.0 이상으로 업데이트하고 모든 후속 처리에서 테넌트별 salt를 유지하세요.[1], [5]

💡 알기 쉬운 설명 (ELI5)

고객별 문서가 전용 색상표가 붙은 사물함에 있다고 상상해 보세요. 첫 요청에는 올바른 표가 붙지만 도구가 다음 단계를 위해 문서를 돌려줄 때 표가 빠집니다. 공유 선반은 캐시 적중으로 추측한 페이지 묶음의 존재를 알릴 수 있지만 페이지 자체를 주지는 않습니다.[1]

핵심 개념 및 용어

Prefix caching
같은 접두부의 모델 키/값 블록을 재사용하는 방식.[6]
cache_salt
서로 다른 salt의 캐시를 분리하도록 첫 블록 해시에 섞는 값.[6]
Harmony continuation
도구 호출 뒤를 포함해 Harmony 응답 후 구성되는 다음 모델 입력.[1]
Membership oracle
추측한 접두부의 존재를 알리지만 내용은 공개하지 않는 신호.[1]
CWE-524
민감 정보가 든 캐시의 사용; 권고의 주요 분류.[1]

프레임워크 매핑

  • 이 가이드에서 설명하는 약점의 CWE 참조: CWE-524

근본 원인 분석 (Root Cause)

vLLM 권고는 POST /v1/responses의 GPT-OSS Harmony 경로를 설명합니다. 최초 입력은 request.cache_salt를 tokens_input에 전달했지만 내장 또는 MCP 도구 호출 후 후속 처리는 salt 없이 tokens_input(token_ids)를 사용했습니다. helper는 salt를 전달받아야 저장합니다. 자동 prefix caching을 쓰는 공유 배포에서 후속 처리는 salt 없는 네임스페이스를 사용했습니다. 권고는 0.30.0 미만을 열거하고 0.25.1에서 확인했으며 더 낮은 경계는 확정되지 않았다고 밝힙니다. 결과는 cached_tokens_per_turn을 통한 캐시 구성원 신호이지 임의 프롬프트의 직접 공개가 아닙니다. CWE-200도 영향 분류로 제시되지만 여기서는 CWE-524만 주요 약점으로 사용합니다.[1], [3], [4]

단계별 공격 실행 흐름

단계 1

공유 서비스가 전제 조건을 충족한다

영향 버전, GPT-OSS Harmony Responses, prefix caching, 도구가 필요하며 피해 요청은 cache_salt를 설정하고 후속 처리에 도달해야 합니다.[1]

단계 2

첫 engine input에는 salt가 들어간다

첫 tokens_input 호출에는 request.cache_salt가 포함되어 접두부가 호출자의 salt 적용 네임스페이스에 들어갑니다.[1]

단계 3

도구 후속 처리에서 salt가 빠진다

도구 결과 뒤 후속 처리는 원래 salt 없이 tokens_input(token_ids)를 호출해 공유된 salt 없는 영역에 들어갈 수 있습니다.[1]

단계 4

캐시 수치가 구성원 여부를 드러낼 수 있다

다른 테넌트가 접두부를 재구성하면 cached_tokens_per_turn으로 존재를 추론할 수 있지만 임의 프롬프트 텍스트를 얻지는 못합니다.[1]

단계 5

renderer가 매 turn에서 salt를 유지한다

병합된 renderer 리팩터링은 Harmony 렌더링에서 cache_salt를 유지해 새 engine input마다 전달합니다. 0.30.0 이상으로 업데이트하세요.[1], [3], [7]

소스 코드 비교: 취약한 구현 vs 보안 패치

vLLM 권고는 POST /v1/responses의 GPT-OSS Harmony 경로를 설명합니다. 최초 입력은 request.cache_salt를 tokens_input에 전달했지만 내장 또는 MCP 도구 호출 후 후속 처리는 salt 없이 tokens_input(token_ids)를 사용했습니다. helper는 salt를 전달받아야 저장합니다. 자동 prefix caching을 쓰는 공유 배포에서 후속 처리는 salt 없는 네임스페이스를 사용했습니다. 권고는 0.30.0 미만을 열거하고 0.25.1에서 확인했으며 더 낮은 경계는 확정되지 않았다고 밝힙니다. 결과는 cached_tokens_per_turn을 통한 캐시 구성원 신호이지 임의 프롬프트의 직접 공개가 아닙니다. CWE-200도 영향 분류로 제시되지만 여기서는 CWE-524만 주요 약점으로 사용합니다. Upstream excerpts, not a literal line-by-line diff.[1], [3], [4], [7]

소스 코드 발췌: vLLM Responses Harmony renderer (서로 다른 리비전 발췌)

취약한 구현
# 초기 요청 경로에는 salt가 적용됐지만 도구 호출 후 이어지는 경로에는 적용되지 않았습니다.
engine_input = tokens_input(token_ids, cache_salt=request.cache_salt)

# 도구 결과를 받은 뒤 이어지는 경로는 입력을 다음과 같이 다시 구성했습니다:
engine_input = tokens_input(token_ids)
보안 강화 패치
# Harmony 렌더링 컨텍스트에서 요청 salt를 유지합니다.
cache_salt = cast(str | None, engine_input.get("cache_salt"))
engine_input = self.online_renderer.render_responses_harmony_messages(
    context.messages,
    cache_salt=cache_salt,
    tok_params=tok_params,
)

# 렌더러는 엔진 입력을 만들 때마다 salt를 전달합니다.
engine_input = tokens_input(prompt["prompt_token_ids"], cache_salt=cache_salt)

엔지니어링 및 시스템 보안 강화 체크리스트

출처