COMMENTS (0)
댓글은 익명으로 작성되며, 삭제 비밀번호를 설정하면 본인만 삭제할 수 있습니다. 비밀번호를 설정하지 않은 댓글은 누구나 삭제할 수 있습니다.
Hugging Face 로봇 프레임워크 LeRobot에서 CVSS 9.8의 unauthenticated RCE(CVE-2026-25874)가 공개됐다. 메인테이너가 1월에 위험을 인정한 뒤 약 4개월간 미패치 상태가 이어진 disclosure 거버넌스 실패 사례다.
댓글은 익명으로 작성되며, 삭제 비밀번호를 설정하면 본인만 삭제할 수 있습니다. 비밀번호를 설정하지 않은 댓글은 누구나 삭제할 수 있습니다.
2026년 1월 7일, Hugging Face의 오픈소스 로봇 프레임워크 LeRobot 메인테이너는 GitHub 이슈에 짧은 응답을 남겼다. "this does pose a security risk." 비공개 보고를 받은 지 약 한 달 만이었다. 그 후 약 4개월 동안 패치는 나오지 않았고, 4월 23일 CVSS 9.8의 unauthenticated RCE 취약점 CVE-2026-25874가 공개됐다.
| 항목 | 값 |
|---|---|
| CVE | |
| CVSS 3.1 | 9.8 (Critical) |
| 영향 버전 | LeRobot ≤ 0.5.1, 2026-04-29 시점 미패치 |
| 근본 원인 | 인증 없는 gRPC 채널의 pickle.loads() (CWE-502) |
LeRobot은 GitHub에서 약 2만 4천 개의 별을 받은 로봇 학습·제어 프레임워크다. 정책 서버와 로봇 클라이언트가 네트워크로 추론 결과를 주고받는 구조에서, 양쪽 모두 입력 데이터를 pickle.loads()로 역직렬화하고 있었다. 이 사건은 단순한 버그 보고가 아니라, ML 인프라의 보안 거버넌스가 어떻게 멈춰 설 수 있는지 보여주는 disclosure 실패 사례다.
LeRobot은 Hugging Face가 공개한 로보틱스 프레임워크로, 모방 학습과 강화 학습 정책을 실제 로봇 팔이나 모바일 베이스에서 실행하는 것을 목표로 한다. 핵심은 비동기 추론 파이프라인이다. GPU가 달린 별도 서버가 정책 추론을 담당하고, 로봇 본체는 관측값을 보내고 행동 명령을 받는다.
이 통신은 gRPC 위에서 동작한다. LeRobot 0.5.1까지의 코드는 이 채널을 add_insecure_port()로 열어두었다. TLS도, 토큰 인증도 없다. 운영자가 GPU 분리를 위해 정책 서버를 0.0.0.0으로 노출하면, 도달 가능한 누구든 RPC를 호출할 수 있다.
첫 보고는 2025년 12월경 비공개 채널로 이루어졌다. 연구자 별칭 chenpinji가 GitHub Security 탭을 통해 LeRobot 메인테이너에게 직접 알렸다. 응답이 없자 연구자는 2026년 1월 공개 이슈로 사안을 끌어냈고, 그 자리에서 메인테이너는 위험을 인정했다.
같은 스레드에서 메인테이너는 한 가지를 더 인정했다. "that part of the codebase needs to be almost entirely refactored as its original implementation was more experimental." 즉 비동기 추론 코드 자체가 실험적이었으며 거의 전면 재작성이 필요하다는 자평이었다. 1월 12일을 마지막으로 그 스레드는 더 이상 갱신되지 않았다.
2026년 2월 11일, VulnCheck 소속 연구원 Valentin Lobstein이 같은 결함을 독자적으로 발견했다. 그는 작동하는 익스플로잇을 작성한 뒤 CVE 신청을 진행했고, 2월 27일 공개 이슈 #3047과 수정 PR #3048이 게시됐다.
PR은 pickle을 safetensors와 JSON으로 교체하는 안이었다. 그러나 4월 29일 시점에도 머지되지 않은 채 0.6.0 릴리스 로드맵에 머물러 있었다. 1월 인정에서 4월 공개까지, 핵심 기간만 따져도 약 3.5개월이 지나갔다.
코드 레벨로 들어가면 결함은 단순하다. src/lerobot/async_inference/policy_server.py에는 pickle.loads() 호출이 세 군데 있고, robot_client.py에 한 군데 더 있다. 모두 네트워크에서 받은 바이트를 그대로 처리한다. Lobstein의 분석에 따르면 코드 옆에는 정적 분석 경고를 묵살하는 # nosec 주석이 달려 있었다.
취약 RPC는 세 가지로 정리된다.
SendPolicyInstructionsSendObservationsGetActions어느 RPC든 공격자가 __reduce__() 매직 메서드를 정의한 객체를 직렬화해 보내면, 서버 측 pickle.loads()는 역직렬화 과정에서 그 메서드를 호출한다. 그 안에 os.system이든 subprocess.Popen이든 임의 함수를 끼워 넣을 수 있다. 코드에 있는 isinstance 타입 검증은 역직렬화가 끝난 뒤에야 실행되므로 의미가 없다.
Python 공식 문서는 이 패턴에 대해 분명히 경고한다. "The pickle module is not secure. Only unpickle data you trust. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling." 인증되지 않은 네트워크 입력에 pickle.loads()를 직접 적용한 코드는 처음부터 이 경고를 정면으로 위반한 셈이다.
CISA의 알려진 악용 취약점(KEV) 카탈로그에는 4월 29일 시점까지 등재되지 않았다. 활성 익스플로잇 보고도 확인되지 않았다. 다만 PoC가 연구자 블로그에 공개돼 있고, GitHub에서 노출된 LeRobot 인스턴스를 찾아내는 일은 어렵지 않다. 운영자가 GPU 서버를 외부로 노출한 환경에서는 사실상 즉시 RCE가 가능한 상태가 약 6개월 가까이 지속된 것으로 정리할 수 있다.
LeRobot 리포지토리의 보안 권고 페이지는 4월 29일 기준 여전히 비어 있다. *"There aren't any published security advisories"*가 표시된 상태다. NVD 항목은 갱신됐지만, GitHub 권고문 형식의 공식 발표는 따로 나오지 않았다.
Hugging Face는 pickle 기반 모델 포맷의 위험을 가장 강하게 지적해 온 회사 중 하나다. 2022년 safetensors 포맷을 공개하고 외부 보안 감사를 받았으며, 자사 Hub에서 pickle 파일에 unsafe 라벨을 부여하는 정책을 운영해 왔다. 그런 회사가 자사 로보틱스 프레임워크의 네트워크 입력단에서는 pickle.loads()를 직접 호출하고 있었다는 점이 이번 사건의 첫 번째 아이러니다.
두 번째는 disclosure 거버넌스다. 메인테이너가 1월에 위험을 명시적으로 인정했음에도, 사실상 동일한 결함이 다시 외부에서 발견되고 CVE가 발급될 때까지 패치는 미뤄졌다. ML 인프라가 빠르게 프로덕션으로 내려가는 시점에, "실험적 구현"이라는 자평이 실제 사용자 보호로 연결되지 않은 사례다.
마지막으로 이 결함은 서버 RCE에 그치지 않는다. LeRobot이 제어하는 대상은 물리 로봇이다. 정책 서버를 장악한 공격자는 모터 명령을 보낼 수 있는 위치에 서게 된다.
이번 보고에서 실제 물리 사고는 확인되지 않았다. 그러나 AI 추론 파이프라인의 결함이 사이버 공간에만 머무르지 않을 수 있다는 점은 분명하다. ML과 로봇이 결합된 환경 전반의 위협 모델을 다시 점검해야 하는 이유다.
AI 활용 안내 이 글은 AI(Claude)의 도움을 받아 작성되었습니다. 인용된 통계와 사례는 참고 자료에 명시된 출처에 근거하며, 설명을 위한 일부 표현은 각색되었습니다.
면책 조항 본 글은 보안 인식 제고를 위한 교육 목적으로 작성되었습니다. 언급된 공격 기법을 실제로 시도하는 행위는 「정보통신망법」, 「형법」 등에 따라 처벌받을 수 있으며, 본 블로그는 이에 대한 법적 책임을 지지 않습니다.
KW_PROTECT_0