Ray 2.58.0은 8월 23일 UTC 05:42에 배포됐습니다. Ray Serve의 수정 항목에는 Serve 복제본 ASGIService가 토큰 인증을 우회하던 문제를 고친다는 한 줄이 들어 있습니다. 보안 공지는 첨부되지 않았고, CVE도 요청되지 않았으며, 심각도도 제시되지 않았습니다.
풀 리퀘스트가 밝히는 내용
PR #65189는 변경 로그보다 훨씬 더 구체적입니다. Serve 복제본의 내부 gRPC 서버는 “raw grpc.aio.server()로 만들어졌고 add_insecure_port로 바인딩됐다”고 적혀 있으며, 작성자 표현에 따르면 이는 Ray의 두 전송 제어를 모두 건너뛴 Ray의 유일한 Python 측 gRPC 서버였습니다. RAY_AUTH_MODE=token에서는 서비스가 유효한 자격 증명 없이 들어온 요청을 받아들였고, 어떤 검증도 수행하기 전에 pickle.loads(request.pickled_request_metadata)에 도달했습니다. RAY_USE_TLS=1 아래에서 Ray의 다른 Python gRPC 서버들이 mTLS를 사용하는 것과 달리, 이 포트는 암호화되지 않은 상태로 남아 있었습니다.
검증 전에 pickle.loads에 도달한 것이 핵심 문제입니다
공격자가 공급한 pickle을 역직렬화하는 것은 설계상 임의 코드 실행입니다. Python의 자체 문서도 이를 분명히 밝힙니다. 여기서 중요한 것은 순서입니다. 신뢰할 수 없는 페이로드가 먼저 unpickle되고, 그다음에 인증이 이뤄졌기 때문에, 이 경로에서는 인증이 약한 정도가 아니라 사실상 무의미해집니다.
왜곡: 새로운 구멍이 아니라 5개 릴리스의 공백
Ray는 2.52.0에서 모든 Ray 구성요소를 포괄한다고 설명된 토큰 인증을 도입했습니다. 그러나 이 포트는 그 적용 범위에 포함되지 않았습니다. 해당 릴리스 노트를 믿고 RAY_AUTH_MODE=token을 켠 사람들은 그때부터 모든 Serve 복제본에서 인증되지 않은 역직렬화 엔드포인트를 운영해 온 셈입니다. 이번 수정은 새로운 보호를 더한 것이 아니라, 문서에 적힌 내용과 실제 사이의 거리를 메운 것입니다.
수정은 릴리스보다 18일 앞서 이뤄졌습니다
PR #65189는 8월 5일에 병합됐습니다. 그리고 2.58.0이 배포된 8월 23일에 운영자들에게 전달됐습니다. 그 18일 동안 패치는 공개 저장소에서 읽을 수 있는 상태로 남아 있었지만 어떤 릴리스에도 포함되지 않았습니다. 이는 비공개 공개 없이 오픈 상태에서 보안 이슈를 수정할 때 드는 통상적인 비용이며, 변경 로그의 그 한 줄이 겉보기보다 더 중요한 이유이기도 합니다.
운영자가 확인해야 할 사항
노출 여부는 네트워크 도달성에 달려 있습니다. 이 포트는 임시 포트에서 인터페이스 전반에 걸쳐 바인딩되기 때문입니다. 중요한 클러스터는 Serve 복제본이 신뢰할 수 없는 호출자가 접근할 수 있는 네트워크에 놓인 경우입니다. 업그레이드를 하면 클라이언트와 서버가 모두 Ray의 공유 gRPC 헬퍼를 사용하게 되며, 이는 Ray의 나머지 구성요소가 이미 사용하던 인터셉터와 TLS 설정을 적용합니다.
