CVE-2025-55182 là một lỗ hổng nghiêm trọng cho phép thực thi mã từ xa trước khi xác thực trong React Server , với điểm CVSS là 10.0 – mức độ nghiêm trọng cao nhất có thể. Trong khuôn khổ Chương trình Học bổngOPSWAT , các thành viên của chúng tôi đã tiến hành phân tích kỹ thuật toàn diện về lỗ hổng này, xem xét nguyên nhân gốc rễ của nó trong giao thức giải mã React Flight, chuỗi khai thác đầy đủ và tác động rộng rãi của nó trên hệ sinh thái web hiện đại. Bài viết này trình bày các phát hiện của chúng tôi cùng với hướng dẫn thực tiễn dành cho các chuyên gia bảo mật.

React đã trở thành một trong những thư viện front-end được sử dụng rộng rãi nhất trên thế giới, hỗ trợ một phần đáng kể mobile web và mobile hiện đại. Các cuộc khảo sát dành cho nhà phát triển của Stack Overflow liên tục xếp React vào danh sách các framework web hàng đầu, với tỷ lệ sử dụng vượt quá 40% trong số các nhà phát triển chuyên nghiệp trên toàn cầu. Song song với sự phát triển này, nhóm phát triển React đã giới thiệu React Server (RSC) như một tính năng cốt lõi của React 19 - một sự thay đổi mô hình chuyển logic hiển thị từ phía client sang phía server, giúp tối ưu hóa hiệu suất và tích hợp chặt chẽ hơn giữa mã phía server và mã phía client.
Tuy nhiên, sự phát triển về mặt kiến trúc này đã tạo ra một lỗ hổng bảo mật mới vô cùng nghiêm trọng. Vào ngày 29 tháng 11 năm 2025, nhà nghiên cứu bảo mật Lachlan Davidson đã báo cáo một lỗ hổng trong logic giải mã phía máy chủ của React tới chương trình Bug Bounty của Meta. Được công bố rộng rãi vào ngày 3 tháng 12 năm 2025 với mã CVE-2025-55182, lỗ hổng này cho phép thực thi mã từ xa mà không cần xác thực thông qua một yêu cầu HTTP được thiết kế đặc biệt. Được phân loại là CWE-502 (Giải mã dữ liệu không đáng tin cậy), lỗ hổng này không yêu cầu xác thực, tương tác của người dùng hay cấu hình ứng dụng đặc biệt nào - một triển khai create-next-app mặc định được xây dựng cho sản xuất có thể bị khai thác ngay lập tức.

Tác động là tức thì và nghiêm trọng. Chỉ trong vòng 48 giờ sau khi thông tin được công bố, đã ghi nhận nhiều chiến dịch khai thác lỗ hổng diễn ra trên thực tế. Theo The Shadowserver Foundation, hơn 77.000 địa chỉ IP công khai đã được xác định là có khả năng bị ảnh hưởng. Dữ liệu từ Cloudflare ghi nhận hơn 582 triệu nỗ lực khai thác trong tuần sau khi thông tin được công bố, với cường độ tấn công trung bình hơn 3.500 địa chỉ IP nguồn duy nhất mỗi giờ và đạt đỉnh điểm với 16.585 địa chỉ IP tấn công đồng thời. Wiz Research báo cáo rằng 39% môi trường đám mây chứa các phiên bản dễ bị tấn công. CISA đã thêm lỗ hổng này vào danh mục Lỗ hổng đã bị khai thác (KEV) vào ngày 5 tháng 12 năm 2025.
Các tác nhân đe dọa đã hành động với tốc độ và sự đa dạng đáng chú ý. Trend Micro đã ghi nhận nhiều chiến dịch — bao gồm các chiến dịch botnet “emerald” và “nuts” — triển khai các beacon Cobalt Strike, các mô-đun cấy ghép Sliver, tác nhân giám sát Nezha, các đường hầm Fast Reverse Proxy (FRP), cùng một tải trọng mới mang tên “Secret-Hunter” tận dụng các công cụ thu thập thông tin đăng nhập mã nguồn mở như TruffleHog và Gitleaks. Threat Intelligence của Google đã xác định các cụm đe dọa có liên quan đến Trung Quốc (UNC6600, UNC6586, UNC6588, UNC6603) triển khai các công cụ chuyên dụng - bao gồm công cụ tạo đường hầm MINOCAT, trình tải xuống SNOWLIGHT, cửa hậu COMPOOD và cửa hậu HISONIC - cùng với các tác nhân có liên quan đến Iran và các nhóm có động cơ tài chính thực hiện các chiến dịch khai thác tiền điện tử. AWS đã ghi nhận các nhóm có liên quan đến Trung Quốc thử nghiệm mã khai thác từ sớm nhất là ngày 4 tháng 12, trước khi mã chứng minh khái niệm đầy đủ được công bố rộng rãi.
Giới thiệu về React Server
React là một thư viện JavaScript dùng để xây dựng giao diện người dùng, được duy trì bởi Meta và một cộng đồng mã nguồn mở rộng lớn. React Server (RSC), được giới thiệu cùng với React 19, đại diện cho một sự thay đổi cơ bản trong cách các ứng dụng React xử lý việc hiển thị. Không giống như các thành phần máy khách truyền thống được thực thi hoàn toàn trong trình duyệt, các thành phần máy chủ được thực thi trên máy chủ, tạo ra một biểu diễn tuần tự của giao diện người dùng được truyền trực tiếp đến máy khách. Thiết kế này giúp giảm lượng JavaScript được gửi đến trình duyệt, cải thiện các chỉ số thời gian tương tác và cho phép truy cập trực tiếp vào các tài nguyên phía máy chủ như cơ sở dữ liệu và hệ thống tệp.

RSC sử dụng một giao thức tuần tự hóa tùy chỉnh có tên là “Flight” để mã hóa và truyền dữ liệu giữa máy khách và máy chủ. Khi máy khách gọi một Server (trước đây gọi là Server ), trình duyệt sẽ đóng gói các đối số của hàm vào một yêu cầu HTTP có cấu trúc bằng cách sử dụng định dạng Flight. Máy chủ giải mã tải trọng này, thực thi hàm được yêu cầu và truyền kết quả trở lại máy khách. Sự kết nối chặt chẽ giữa máy khách và máy chủ (mặc dù về mặt kiến trúc thì rất tinh tế) có nghĩa là bất kỳ lỗ hổng nào trong logic giải mã đều có thể gây ra hậu quả tức thời và thảm khốc, như CVE-2025-55182 đã chứng minh.
Lỗ hổng này không chỉ ảnh hưởng đến React mà còn tác động đến toàn bộ hệ sinh thái các framework được xây dựng dựa trên nó. Next.js (đã nhận được một thông báo riêng, CVE-2025-66478, sau đó bị từ chối vì trùng lặp), React Router, Waku, plugin RSC của Parcel, plugin RSC của Vite và RedwoodSDK đều bị ảnh hưởng. Ngay cả các ứng dụng không định nghĩa rõ ràng Server cũng có thể bị ảnh hưởng nếu hỗ trợ RSC được bật trong framework.
Kiến thức kỹ thuật
Trước khi phân tích lỗ hổng này, cần lưu ý ba khái niệm cơ bản làm nền tảng cho chuỗi khai thác: hành vi `await` của JavaScript với các đối tượng `thenable`, việc duyệt chuỗi prototype, và mô hình dữ liệu dựa trên các khối (chunk) của giao thức React Flight.
Các đối tượng `await` và `Thenable` trong JavaScript
Toán tử `await` tạm dừng việc thực thi một hàm không đồng bộ cho đến khi biểu thức được chờ đợi được giải quyết. Khi `await` gặp một đối tượng Promise gốc, nó sẽ chờ cho đến khi đối tượng đó được giải quyết và trả về giá trị đã được thực hiện. Tuy nhiên, `await` không bắt buộc phải là một đối tượng Promise gốc — bất kỳ đối tượng nào có phương thức `.then()`, được gọi là “thenable”, đều được coi là một cấu trúc tương tự Promise.
Khi `await` gặp một đối tượng `thenable`, nó sẽ gọi phương thức `.then()` của đối tượng đó, đồng thời truyền các hàm gọi lại `resolve` và `reject` do hệ thống cung cấp. Giá trị được truyền vào `resolve` sẽ trở thành kết quả của biểu thức `await`. Điều quan trọng là, nếu giá trị được giải quyết chính nó là một thenable, phương thức .then() của đối tượng lồng nhau đó sẽ được gọi đệ quy cho đến khi đạt được một giá trị nguyên thủy hoặc một Promise đã được giải quyết. Hành vi giải quyết đệ quy này là yếu tố cốt lõi trong việc khai thác lỗ hổng CVE-2025-55182.
Thuật toán duyệt chuỗi mẫu
Mỗi đối tượng JavaScript đều duy trì một liên kết nội bộ đến nguyên mẫu của nó, có thể truy cập thông qua thuộc tính `__proto__`. Khi truy cập một thuộc tính trên một đối tượng, máy biên dịch JavaScript trước tiên sẽ kiểm tra các thuộc tính của chính đối tượng đó. Nếu không tìm thấy thuộc tính đó, máy biên dịch sẽ duyệt qua chuỗi nguyên mẫu — di chuyển ngược lên qua từng liên kết `__proto__` — cho đến khi tìm thấy thuộc tính hoặc chuỗi kết thúc tại `undefined`.
Kẻ tấn công có thể lợi dụng cơ chế kế thừa này để truy cập các thuộc tính nằm ngoài phạm vi dự định của một đối tượng. Bằng cách đưa __proto__ vào đường dẫn truy cập thuộc tính, kẻ tấn công có thể tiếp cận các phương thức và hàm tạo nội bộ mà ứng dụng không bao giờ có ý định tiết lộ. Trong JavaScript, biểu thức `obj.__proto__.constructor.constructor` sẽ trả về hàm tạo toàn cục `Function`, hàm này có thể tạo và thực thi các hàm tùy ý từ một chuỗi đầu vào.
Giao thức React Flight và Mô hình dữ liệu theo khối
When a client invokes a Server Function, the browser sends an HTTP POST request with a multipart/form-data body. Each form field contains a numbered “chunk” of serialized data. The Flight protocol uses special string prefixes to encode data types: $<id> references the resolved value of another chunk, $@<id> references the raw chunk object itself, $W<id> represents a Set, $K<id> represents FormData, and $B<id> triggers the blob handler.
Hãy xem xét một Server được định nghĩa như sau:

Yêu cầu HTTP tương ứng chứa nhiều trường biểu mẫu, mỗi trường bao gồm một khóa và một giá trị: trường 0 chứa mảng tham số với các tham chiếu như "$W1" và "$K2", trong khi các trường 1 và 2_* chứa dữ liệu mà các tham chiếu đó trỏ đến. Máy chủ xử lý từng trường ngay khi nhận được, đồng thời lưu trữ các kết quả trung gian vào các đối tượng được gọi là “chunks”.

Một chunk là một đối tượng thenable có bốn thuộc tính chính: status (trạng thái giải quyết), value (dữ liệu được lưu trữ), reason (thông tin lỗi) và _response (một tham chiếu ngược đến đối tượng phản hồi cha). Khi máy chủ gặp lệnh await chunk, phương thức .then() của chunk sẽ được gọi. Nếu trạng thái của chunk là INITIALIZED, hàm callback giải quyết sẽ nhận được chunk.value. Nếu trạng thái là PENDING, BLOCKED hoặc CYCLIC, các hàm callback sẽ được xếp hàng để thực thi sau.

Chunk 0 thường đại diện cho mảng đối số của Server được gọi. Sau khi nhận được tất cả các trường biểu mẫu và giải quyết xong tất cả các tham chiếu nội bộ, chunk_0.value sẽ chứa mảng đối số đã được lắp ráp hoàn chỉnh, sau đó được truyền đến hàm đích.
Xử lý yêu cầu từ đầu đến cuối (Next.js → Giải mã dữ liệu từ React Flight)
Phần sau đây mô tả cách Next.js xử lý một yêu cầu Server đến trong điều kiện bình thường, từ lớp HTTP cho đến bộ máy giải mã React Flight.

Hàm handleAction() - Next.js
Khi một Server được gọi, yêu cầu sẽ được chuyển vào hàm `handleAction`. Hàm này sẽ xác thực siêu dữ liệu, kiểm tra các tiêu đề và mã thông báo CSRF, đồng thời xác nhận rằng yêu cầu là một hành động truy xuất hợp lệ. Sau đó, một luồng có tên busboyStream được tạo ra để phân tích nội dung biểu mẫu nhiều phần. Hàm decodeReplyFromBusboy liên kết các bộ phát sự kiện với luồng này, kích hoạt các hàm xử lý giải mã ServerReact Serverkhi dữ liệu thô được nhận. Giá trị trả về của decodeReplyFromBusboy là chunk_0; toán tử await giải quyết nó và truyền giá trị đã lắp ráp của nó đến Server được gọi.

Hàm getChunk trả về khối dữ liệu tương ứng với một ID đã cho. Nếu khối dữ liệu đó chưa tồn tại, hàm sẽ tạo ra một đối tượng ResolvedModelChunk (nếu dữ liệu đã có sẵn trong response._formData) hoặc một đối tượng PendingChunk (nếu chưa có dữ liệu nào được gửi đến cho ID đó).

Khi hàm `decodeReplyFromBusboy` trả về `chunk_0`, khối này vẫn ở trạng thái PENDING. Toán tử `await` gọi phương thức `chunk_0.then()` và tạm thời lưu trữ các hàm gọi lại `resolve` và `reject` vào các biến `chunk_0.value` và `chunk_0.reason`. Các hàm gọi lại này sẽ được kích hoạt lại bởi hàm `wakeChunk` ngay sau khi quá trình giải quyết tham chiếu hoàn tất.

Quá trình giải mã - React Server
Khi busboyStream nhận được một trường dữ liệu thô hoàn chỉnh, nó sẽ kích hoạt bộ phát sự kiện 'field', gọi hàm resolveField và bắt đầu quá trình giải mã — chuyển đổi dữ liệu thô từ biểu mẫu thành các đối tượng JavaScript đã được xây dựng hoàn chỉnh. Các hàm sau đây điều khiển quá trình này.
resolveField(response, key, value)

Khóa và giá trị được thêm vào `response._formData`. Sau đó, hàm này sẽ truy xuất khối (chunk) tương ứng với ID trùng khớp với khóa. Nếu khối đó đã tồn tại, hàm `resolveModelChunk` sẽ được gọi để tái tạo lại nó. Việc giải quyết trì hoãn này là cần thiết vì giá trị có thể chứa các tham chiếu đến các trường mà dữ liệu thô của chúng chưa được nhận; trong trường hợp đó, React Server một `PendingChunk` kèm theo các hàm gọi lại (callback) `resolve` và `reject` tùy chỉnh để xử lý các tham chiếu đó sau này.
resolveModelChunk(chunk, value, id)

resolveModelChunk tạo ra một đối tượng ResolvedModelChunk ở trạng thái RESOLVED_MODEL và chèn dữ liệu thô vào đó. Sau đó, hàm này tái tạo khối dữ liệu thông qua phương thức initializeModelChunk và gọi wakeChunk để kích hoạt các hàm gọi lại (callback) resolve và reject đang nằm trong hàng đợi, từ đó hoàn tất quá trình giải quyết đối tượng hoặc tham chiếu.
khởi tạo khối mô hình(khối)

Hàm `initializeModelChunk` chuyển trạng thái của chunk sang `CYCLIC` — cho biết quá trình giải quyết tham chiếu đang diễn ra — và bắt đầu quá trình giải mã. Hàm này tạo ra một đối tượng JavaScript thô từ `chunk.value` bằng cách sử dụng `JSON.parse`, sau đó truyền đối tượng này vào hàm `reviveModel`.
reviveModel(phản hồi, đối tượng cha, khóa cha, giá trị, tham chiếu)

Hàm reviveModel xử lý đệ quy từng thành phần bên trong đối tượng đã được phân tích cú pháp. Khi gặp một giá trị chuỗi, hàm này sẽ gọi hàm parseModelString để xử lý nó.
parseModelString(response, obj, key, value, reference)

Hàm `parseModelString` xử lý dựa trên tiền tố chuỗi để xử lý các loại mã hóa khác nhau. Đối với các tham chiếu bắt đầu bằng ký tự $, hàm `getOutlinedModel` sẽ được gọi để giải quyết tham chiếu giữa các khối.
getOutlinedModel(response, reference, parentObject, key, map)

getOutlinedModel chia chuỗi tham chiếu theo dấu phân cách “:” để tạo thành đường dẫn truy cập thuộc tính, sau đó duyệt qua đường dẫn đó trên đối tượng chunk đích để trả về giá trị được tham chiếu. Như đã trình bày chi tiết trong phần Phân tích lỗ hổng bảo mật dưới đây, việc thiếu cơ chế xác thực đối với các tên thuộc tính này chính là điểm cụ thể mà lỗ hổng bảo mật tồn tại.
Phân tích lỗ hổng bảo mật bảo mật
Nguyên nhân gốc rễ
CVE-2025-55182 originates from insufficient input validation in the getOutlinedModel() function within React’s server-side Flight reply handler (ReactFlightReplyServer.js). When a chunk reference includes a property path - such as $<id>:<prop1>:<prop2> - the function resolves it by traversing the specified properties on the target chunk object, computing the result as chunk[prop1][prop2].

Lỗ hổng nghiêm trọng nằm ở chỗ các tên thuộc tính này không bao giờ được kiểm tra tính hợp lệ. Máy chủ không xác minh xem các thuộc tính được yêu cầu là thuộc tính riêng của đối tượng hay thuộc tính nguyên mẫu được kế thừa. Do đó, kẻ tấn công có thể bao gồm __proto__ trong đường dẫn thuộc tính để đi qua chuỗi nguyên mẫu và tiếp cận các phương thức nội bộ mà lẽ ra không bao giờ được truy cập từ đầu vào do người dùng kiểm soát. Ví dụ: tham chiếu $1:__proto__:then được giải quyết thành Chunk.prototype.then - một hàm mà kẻ tấn công sau đó có thể gọi với các đối số được kiểm soát.

Mã dễ bị tấn công
Chuỗi khai thác tận dụng hai luồng mã riêng biệt trong logic giải mã Flight của React.
Đầu tiên là Chunk.prototype.then, phương thức này quy định cách các chunk hoạt động như các đối tượng thenable. Khi toán tử await được áp dụng cho một chunk ở trạng thái INITIALIZED, hàm resolve(chunk.value) sẽ được gọi. Nếu chunk.value bản thân là một đối tượng thenable (một đối tượng có phương thức .then() ), toán tử await sẽ gọi đệ quy phương thức chunk.value.then(). Cơ chế giải quyết đệ quy này chính là cách mà kẻ tấn công có thể chuyển hướng quá trình thực thi sang một hàm tùy ý.
Thứ hai là trình xử lý tiền tố $B (blob) trong hàm parseModelString():

Trong trường hợp $B, hàm gọi đến response._formData.get(response._prefix + id). Cả _formData.get và _prefix đều là các thuộc tính của đối tượng _response được lưu trữ bên trong khối (chunk). Bằng cách điều khiển các thuộc tính này thông qua việc duyệt chuỗi nguyên mẫu, kẻ tấn công có thể chuyển hướng lệnh gọi này để kích hoạt hàm tạo Function toàn cục với mã tùy ý làm đối số.
Khai thác
Through prototype chain traversal, an attacker reaches the global Function constructor via the path <any_object>.constructor.constructor. Because Chunk.prototype.then is a function, the path $1:constructor:constructor resolves to the global Function constructor, which accepts a string and returns a callable function containing that code.

Để minh họa tác động tiềm tàng trong thực tế, các thành viên chương trình của chúng tôi đã xây dựng một gói mã độc thử nghiệm (proof-of-concept) phù hợp với các phân tích đã được ghi chép độc lập từ nhiều nhóm nghiên cứu bảo mật. Lỗ hổng này hoạt động theo hai giai đoạn:
Giai đoạn 1 - Xây dựng đoạn văn giả:
The object delivered in field 0 acts as a fake chunk. Its then property is set to Chunk.prototype.then via the reference path $1:__proto__:then, allowing the Flight deserialization engine to invoke prototype-level behavior on this attacker-constructed object. The _response._formData.get property is pointed at the global Function constructor via $1:constructor:constructor, and _response._prefix is set to the malicious JavaScript code. The value field contains the string {"then": "$B0"}, instructing the blob handler to invoke itself on the same chunk when resolved. The status field is set to resolved_model so that initializeModelChunk is triggered when .then() is called, causing value to be parsed and the blob handler to fire.
Vì trường 1 vẫn chưa được nhận tại thời điểm này, máy Server React Server tạo các hàm gọi lại `resolve` và `reject` để xử lý tham chiếu đang chờ xử lý.
Giai đoạn 2 - Xử lý sự cố:
Khi trường 1 — chứa "$@0", một tham chiếu thô đến khối 0 — được truyền đến, khối đang chờ xử lý sẽ được giải quyết và trỏ trực tiếp đến khối giả. Điều này kích hoạt hàm `wakeChunk`, hàm này xử lý các hàm gọi lại đang xếp hàng và khởi động quá trình duyệt chuỗi nguyên mẫu trong quá trình giải quyết tham chiếu. Khi khối giả được giải quyết hoàn toàn, wakeChunk lại được gọi. Vì callback giải quyết cho khối giả là hàm giải quyết ngầm của Node.js, nó sẽ gọi phương thức .then() của khối và giải quyết giá trị của nó - cuối cùng là xây dựng và thực thi mã độc được chèn vào thông qua hàm tạo Function.
Kỹ thuật khai thác này chỉ cần một yêu cầu HTTP duy nhất:

Replacing {{COMMAND}} with any JavaScript code executes it on the server. The reason: -1 field prevents a toString() error during processing. The Next-Action header may contain any arbitrary value - even x - because the vulnerable deserialization occurs before the server validates the requested Server Function. This is what makes the vulnerability pre-authentication: the payload is processed during the deserialization phase, before any application-level authentication or authorization logic is reached.
Nếu khai thác thành công, kẻ tấn công sẽ có được toàn quyền điều khiển môi trường thực thi Node.js trên máy chủ, bao gồm quyền truy cập vào `child_process` để thực thi lệnh shell, các biến môi trường chứa thông tin đăng nhập cơ sở dữ liệu và API , hệ thống tệp cục bộ, cũng như các điểm cuối siêu dữ liệu đám mây cho phép di chuyển ngang.
Bằng chứng về tính khả thi
Các thành viên trong nhóm của chúng tôi đã tái hiện lỗ hổng này trong môi trường phòng thí nghiệm được kiểm soát bằng cách sử dụng một ứng dụng Next.js tiêu chuẩn được tạo ra bằng create-next-app và được biên dịch cho môi trường sản xuất – mà không có bất kỳ thay đổi nào đối với cấu hình mặc định. Việc tái hiện này đã xác nhận rằng mã khai thác chỉ cần một yêu cầu như đã mô tả ở trên có thể thực thi mã từ xa một cách đáng tin cậy.


Cuộc thử nghiệm có kiểm soát đã cho thấy rằng một kẻ tấn công có quyền truy cập mạng vào máy chủ Next.js dễ bị tấn công có thể thực thi mã Node.js tùy ý — bao gồm tạo một reverse shell thông qua hàm `child_process.exec()`, đọc các biến môi trường và truy cập hệ thống tệp cục bộ — mà không cần cung cấp bất kỳ thông tin đăng nhập nào hoặc kích hoạt bất kỳ kiểm tra xác thực nào ở cấp độ ứng dụng. Giá trị tùy ý được chấp nhận cho tiêu đề Next-Action càng khẳng định thêm bản chất trước xác thực của lỗ hổng này: máy chủ xử lý và giải mã tải trọng trước khi thực hiện bất kỳ tra cứu hành động hoặc kiểm tra ủy quyền nào.
Sự làm dịu
Nhóm phát triển React đã phát hành các bản vá vào ngày 3 tháng 12 năm 2025 – cùng ngày lỗ hổng bảo mật này được công bố rộng rãi. Các phiên bản đã được khắc phục hiện có sẵn dưới dạng React 19.0.1, 19.1.2 và 19.2.1. Bản vá này bổ sung tính năng xác thực thuộc tính nghiêm ngặt trong getOutlinedModel() và reviveModel(), ngăn chặn rõ ràng việc giải quyết các thuộc tính nguyên mẫu được kế thừa - bao gồm __proto__, constructor và prototype - từ các đường dẫn tham chiếu do người dùng kiểm soát trong các gói dữ liệu Flight.
Các tổ chức cần thực hiện ngay các biện pháp sau đây:
- Hãy nâng cấp các gói React lên phiên bản đã được vá lỗi (19.0.1, 19.1.2 hoặc 19.2.1) bằng cách chạy lệnh `npm install react-server-dom-webpack@latest`, `react-server-dom-parcel@latest` hoặc `react-server-dom-turbopack@latest` tùy theo trường hợp.
- Nâng cấp các phụ thuộc của khung công tác - Next.js, React Router, Waku và các khung công tác khác bị ảnh hưởng đã phát hành các bản vá tương ứng. Vui lòng tham khảo thông báo từ nhóm React để biết lộ trình nâng cấp cụ thể cho từng phiên bản.
- Đừng chỉ dựa vào các biện pháp khắc phục của nhà cung cấp dịch vụ lưu trữ — mặc dù các nhà cung cấp như Vercel đã triển khai các quy tắc WAF tạm thời sau khi lỗ hổng được công bố, nhưng đây chỉ là những biện pháp tạm thời và không thể thay thế cho việc vá các gói phần mềm cơ bản.
- Kiểm tra nhật ký máy chủ để tìm các yêu cầu POST có tiêu đề Next-Action kèm theo nội dung multipart/form-data chứa các mẫu $@ hoặc __proto__, đồng thời theo dõi các trường hợp gọi hàm child_process hoặc execSync bất thường trong nhật ký ứng dụng.
Giảm thiểu rủi ro với OPSWAT
OPSWAT , một công nghệ độc quyền trong nền tảng MetaDefender™, cung cấp khả năng theo dõi và kiểm soát cần thiết để phòng ngừa các lỗ hổng bảo mật như CVE-2025-55182. Vì lỗ hổng này tồn tại trong các gói npm mã nguồn mở (react-server-dom-webpack, react-server-dom-parcel, react-server-dom-turbopack), các tổ chức phải trước tiên lập danh sách đầy đủ các vị trí mà các thành phần này được triển khai trên toàn bộ hạ tầng của mình trước khi có thể thực hiện các biện pháp khắc phục hiệu quả.

OPSWAT tạo ra một danh sách toàn diện về tất cả các thành phần phần mềm, thư viện, container và các phụ thuộc đang được sử dụng. Khi quét các ứng dụng hoặc hình ảnh container chứa các gói React có lỗ hổng, hệ thống sẽ tự động đánh dấu CVE-2025-55182 là “Nghiêm trọng” và cung cấp hướng dẫn về các phiên bản đã được vá lỗi, giúp các đội ngũ bảo mật ưu tiên xử lý và khắc phục trước khi lỗ hổng bị khai thác.
OPSWAT hiện có sẵn trong cả MetaDefender — để quét các ứng dụng riêng lẻ và hình ảnh container — và MetaDefender Software Chain™ — để cung cấp khả năng theo dõi ở cấp độ quy trình trên toàn bộ vòng đời phát triển của bạn. Khi kết hợp với nhau, hai giải pháp này giúp các đội ngũ an ninh:
- Nhanh chóng xác định các thành phần dễ bị tấn công - Ngay lập tức xác định các ứng dụng và container nào đang sử dụng các gói react-server-dom-* ở các phiên bản dễ bị tấn công, đảm bảo không bỏ sót bất kỳ bản triển khai nào.
- Đảm bảo việc vá lỗi chủ động - Liên tục theo dõi các thành phần phụ thuộc mã nguồn mở để phát hiện các gói phần mềm đã lỗi thời hoặc không an toàn ngay khi các thông báo mới được công bố, từ đó giảm thiểu thời gian hệ thống bị lộ lỗ hổng.
- Đảm bảo tuân thủ và tính minh bạch của chuỗi cung ứng - Đáp ứng các yêu cầu pháp lý bằng cách duy trì hồ sơ có thể kiểm toán được về tất cả các thành phần phần mềm và các lỗ hổng đã biết của chúng.
Tốc độ và quy mô của các cuộc tấn công khai thác lỗ hổng CVE-2025-55182 – với hơn 582 triệu lần thử chỉ trong tuần đầu tiên – đã cho thấy rõ lý do tại sao việc vá lỗi theo kiểu phản ứng không còn đủ nữa. Việc nắm rõ mình đang sở hữu những gì, chúng chạy ở đâu và khi nào chúng trở nên dễ bị tấn công chính là nền tảng của một chiến lược phòng thủ chủ động. Khả năng theo dõi này bắt đầu từ SBOM.
Tham khảo
- Nhóm React - Lỗ hổng bảo mật nghiêm trọng trong Server React
- Wiz Research - React2Shell (CVE-2025-55182): Lỗ hổng nghiêm trọng trong React
- Trend Micro - CVE-2025-55182: Phân tích lỗ hổng React2Shell, mã chứng minh (PoC) Chaos và các vụ khai thác trong thực tế
- Akamai - CVE-2025-55182: Lỗ hổng thực thi mã từ xa (RCE) do lỗi giải mã trong Server của React và Next.js
- Google Cloud Nhiều nhóm tấn công lợi dụng lỗ hổng React2Shell (CVE-2025-55182)
- AWS - Các nhóm tấn công mạng có liên hệ với Trung Quốc đang nhanh chóng khai thác lỗ hổng React2Shell
- NVD - CVE-2025-55182
- Hiểu về Server React - Tony Alicea
- MDN Web Docs - Toán tử await
- Mã nguồn React - ReactFlightReplyServer.js (phiên bản 19.0.0)
- Mã nguồn Next.js - action-handler.ts (phiên bản 16.0.0)
