요약
React Server Component(RSC)의 Flight 프로토콜 처리과정에서의 비인가 원격 코드 실행 취약점 (CVSS 10.0)
React는 19 버전 이후부터 Server Function이라는 기능을 제공하기 시작했다. Server Function은 클라이언트 컴포넌트에서 서버에서 실행되는 비동기 함수를 직접 호출할 수 있도록 하는 기능으로, API endpoint와 같이 동작하는 것으로 볼 수 있다.
Server Function과 같은 React Server Components는 서버와 클라이언트 간 통신에 Flight 프로토콜을 사용하는데, 이때 발생하는 안전하지 않은 역직렬화가 취약점의 핵심으로 지적되었다.
Flight 프로토콜
본래 React는 DOM 구성을 클라이언트측에서 수행하는 Client-side Rendering(CSR)이다. 하지만 근래의 Frontend가 무거워지고 복잡해짐에 따라 서버측에서 Component를 실행하고 클라이언트에 결과를 전달해주는, CSR과 SSR의 결합된 방식의 React Server Components(RSC)를 도입하게 되었다.
즉, 서버에서는 React Component 형태까지만 랜더링하고, 클라이언트는 이 React Component를 HTML로 랜더링해서 클라이언트의 랜더링 부담을 줄이게 된 형태가 나온것이다.
이때, RSC는 복잡한 Component를 다루기 위해 JSON 등이 아닌 자체적인 프로토콜과 직렬화 포맷을 사용하게 되는데, 이것이 Flight 프로토콜인 것이다.
취약 버전 & Component
- react-server-dom-parcel : 19.0.0, 19.1.0, 19.1.1, 19.2.0
- react-server-dom-turbopack : 19.0.0, 19.1.0, 19.1.1, 19.2.0
- react-server-dom-webpack : 19.0.0, 19.1.0, 19.1.1, 19.2.0
- 취약점이 발생하는 ReactFlightReplyServer.js 파일
위와 같은 라이브러리를 사용하는 모든 컴포넌트들이 취약점에 영향을 받는것으로 확인되었는데, 여기에 Next.js도 포함되어 취약점 파급력이 더 확장되었다. (App Router를 사용하는 설정하에서)
React와 next.js는 워낙 유명하고 사용률도 높은 프론트엔드 프레임워크이기도 하고, RSC 구조 자체적으로 취약한 코드가 포함되어있기에 개발자들이 추가적인 설정을 하지 않은 기본설정에서 취약점이 발생한다는 점에서 Critical해졌다.
더불어 인증/인가 작업 없이 취약점을 비교적 쉽게 적용할 수 있고, RCE 계열의 치명적인 취약점인 만큼 Log4shell의 이름에서 따온 React2shell이라는 명칭도 부여받게 되었다.
분석
Next.js 서버를 대상으로 이 취약점을 분석해보도록 한다.
#1. Flight 프로토콜과 역직렬화
이번 취약점은 '클라이언트가 서버로 Server Function을 호출'하는 과정에서 발생하는데, 직접적인 Server Function 엔드포인트가 없어도 RSC가 지원되는 환경이기만 하면 취약하며, HTTP 요청 한 건 만으로도 원격으로 취약점 트리거 가능한 점이 핵심이다.
먼저, 클라이언트에서 RSC는 Flight 프로토콜을 통해 HTTP POST Request로 직렬화해서 서버로 전송하게 된다.
이때, Next.js 서버가 이 Request를 Server Action으로 인식하게 하기 위한 `Next-Action` Header가 포함된다.
POST / HTTP/1.1
Host: {{Hostname}}
Next-Action: x # RSC Server Action으로 라우팅
X-Nextjs-Request-Id: {{request-id}}
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
그리고 서버는 이 Request를 받고, Server Action으로 확인해 POST body(FormData)를 역직렬화한다.
이때 이 로직은 프레임워크 내부에서 자동으로 이뤄지기에 개발자가 Server Function을 이용해 endpoint를 구현하지 않더라도 취약점이 트리거될 수 있게된다.
즉, 악성 Payload와 `Next-Action` 헤더의 POST request를 전송하면, 서버가 이를 역직렬화하면서 악성 Payload가 서버측에서 실행(node.js)될 수 있는 구조가 완성되는 것이다.
#2. Prototype pollution
이제 악성 Payload가 서버(node.js)에서 실행되는 로직을 보는데, 여기에서는 Prototype Pollution이 이용된다고 한다.
실제 PoC에 사용된 Payload를 확인하면 아래와 같은 구조를 볼 수 있다.
const files = {
"0": json.dumps(`{
"then": "$1:__proto__:then", # 자기 참조 (순환된 구조로 인해 값이 아닌 chunk를 참조 가능)
"status": "resolved_model",
"reason": 0,
"_response": {
"_prefix": "console.log('Hacked!');//", # RCE 커맨드
"_formData": {
"get": "$1:then:constructor:constructor" # Function constructor 접근
}
},
"value": '{"then":"$B0"}' # blob 핸들러 (Function constructor를 통해 코드 실행을 위함)
}`),
"1": '"$@0"', # 자기 참조 (0번 chunk)
"2": [] # 빈 Map
};
이와 같은 2개의 chunk를 디코딩하는 서버의 동작을 포함해 React Server Components에서의 Prototype Pollution 과정을 설명한 write-up을 참조해서 디테일하게 확인할 수 있다.
PoC 환경 구성
아래 PoC Repo를 통해 테스트용 취약 환경 Next.js App을 구성한다.
GitHub - l4rm4nd/CVE-2025-55182: Docker poc lab for CVE-2025-55182 / CVE-2025-66478 (React2Shell) detection and exploitation
Docker poc lab for CVE-2025-55182 / CVE-2025-66478 (React2Shell) detection and exploitation - l4rm4nd/CVE-2025-55182
github.com

Exploit
앞서 살펴본 내용을 토대로 prototype pollution을 이용한 Payload를 Flight 프로토콜을 통해 전송한다.

Mitigation
취약점 패치 버전으로 업그레이드
- React Server Component : 19.0.1, 19.1.2, 19.2.1
- Next.js : 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7
프로젝트 로컬 상에서 `npm audit`을 통해 프로젝트내에 해당 취약점에 영향을 받는지 확인할 수 있다.

WAF 방면에서는 Server Function 트리거 헤더(`Next-Action`)나 악성 Payload 의심 String(`prototype`, `__proto__` 등)을 차단하는 Rule을 세울 수는 있다.
다만, 어디까지나 1차적인 방어고 다양한 방법으로 우회가 가능함으로 패치 버전을 적용해 원천봉쇄하는 것이 중요하다.
nuclei를 통해 스캐닝 가능 : CVE-2025-55182 scan template
React의 Server Function과 같이 외부입력으로부터 동적으로 서버의 함수를 실행하는 로직은 항상 주의해야한다.
항상 사용자 입력값을 의심해야하며, 반드시 검증 로직을 포함하도록 한다.
+) 12/11자로 2가지 CVE(CVE-2025-55183, CVE-2025-55184)가 추가로 등록되었다. 소스코드 노출과 DoS 계열 CVE로, 추가적인 버전 업그레이드가 필요하다
- 14.2.35
- 15.0.7
- 15.1.11
- 15.2.8
- 15.3.8
- 15.4.10
- 15.5.9
- 16.0.10