Nhóm nghiên cứu mối đe dọa của Socket đã phát hiện một mạng lưới gồm ít nhất 28 gói npm độc hại, bao gồm các script protestware, với tổng số khoảng 2.000 bản sao. Phát hiện này đánh dấu một sự leo thang đáng kể trong chuỗi cung ứng npm.
Các gói này ban đầu được gắn cờ trong hai trường hợp do chức năng ẩn nhắm mục tiêu người dùng nói tiếng Nga trên các miền của Nga hoặc Belarus, và đã lan rộng khắp hệ sinh thái.
Bản chất và Tác động của Protestware
Protestware được phân loại theo hệ thống cảnh báo của Socket, gây gián đoạn tương tác giao diện người dùng bằng cách vô hiệu hóa các sự kiện chuột và khởi phát phát lại quốc ca Ukraine. Điều này làm cho các trang web bị ảnh hưởng trở nên không thể sử dụng được đối với người dùng cụ thể. Sự phát triển này làm nổi bật rủi ro của việc tái sử dụng mã nguồn trong các kho lưu trữ mã nguồn mở, nơi các payload không được tiết lộ có thể lan truyền qua các phụ thuộc, khuếch đại tác động tiềm tàng lên các ứng dụng hạ nguồn.
Cơ chế Vô hiệu hóa Tương tác
Khi các tiêu chí kích hoạt được thỏa mãn, script sẽ thiết lập thuộc tính pointerEvents của document.body.style thành 'none'. Điều này ngăn chặn mọi tương tác của người dùng với các yếu tố trên trang web, bao gồm cả chuột và cảm ứng.
document.body.style.pointerEvents = 'none';Kích hoạt Phát lại Âm thanh
Sau khi vô hiệu hóa tương tác, script tiếp tục tạo và thêm một phần tử âm thanh vào tài liệu HTML một cách động. Nguồn của âm thanh được lấy từ một URL bên ngoài chứa quốc ca Ukraine. Quá trình phát lại được thiết lập để lặp lại sau một khoảng thời gian trì hoãn.
// Đoạn mã minh họa cho việc tạo và chèn phần tử âm thanh
const audio = document.createElement('audio');
audio.src = 'https://example.com/ukrainian-anthem.mp3'; // URL giả định
audio.loop = true;
document.body.appendChild(audio);
setTimeout(() => {
audio.play().catch(e => console.error("Error playing audio:", e));
}, delayInMilliseconds); // Thời gian trì hoãn trước khi phátNhững chiến thuật như vậy không chỉ nhằm phản đối các sự kiện địa chính trị mà còn tiềm ẩn rủi ro về tính toàn vẹn trong môi trường JavaScript phía máy khách, có khả năng vi phạm các tiêu chuẩn tiếp cận như WAI-ARIA.
Cơ chế Kỹ thuật của Payload Độc hại
Mã độc hại biểu hiện dưới dạng một đoạn mã nhúng sâu bên trong các gói, thường vượt quá 100.000 dòng mã, và thường được đặt ở cuối để che giấu. Mã này sử dụng một chuỗi kiểm tra điều kiện đa diện để xác định mục tiêu và thời điểm kích hoạt.
Kiểm tra Điều kiện Môi trường
Script thực hiện các kiểm tra sau để đảm bảo nó đang chạy trong môi trường và đối tượng mục tiêu cụ thể:
-
Xác minh Môi trường Thực thi Trình duyệt: Kiểm tra xem biến
windowcó tồn tại hay không, đảm bảo script đang chạy trong trình duyệt chứ không phải môi trường Node.js hoặc tương tự.typeof window !== 'undefined' -
Xác nhận Ngôn ngữ Điều hướng: Kiểm tra xem ngôn ngữ trình duyệt của người dùng có khớp với tiếng Nga hay không, sử dụng biểu thức chính quy để khớp với các mã ngôn ngữ bắt đầu bằng
ru./^ru\\b/.test(navigator.language) -
Đảm bảo Tên máy chủ Mục tiêu: Kiểm tra xem hostname hiện tại có phù hợp với các tên miền cấp cao nhất (TLD) được nhắm mục tiêu của Nga và Belarus hay không, bao gồm
.ru,.su,.by, hoặc.xn--p1ai.// Kiểm tra tên miền cấp cao nhất (TLD) // Ví dụ: hostname.endsWith('.ru') || hostname.endsWith('.su') || ...
Chỉ khi tất cả các tiêu chí này được thỏa mãn, script mới tiếp tục các bước kích hoạt payload.
Cơ chế Kích hoạt Dựa trên Thời gian
Khi các tiêu chí môi trường được thỏa mãn, script sẽ sử dụng localStorage để theo dõi các dấu thời gian khởi tạo. Điều này cho phép nó kích hoạt payload chỉ sau một ngưỡng ba ngày, nhắm mục tiêu vào những người truy cập lặp lại. Logic này giúp tránh ảnh hưởng đến những lượt truy cập một lần, có thể là các nhà nghiên cứu hoặc những người nói tiếng Nga ở các khu vực không phải mục tiêu chính như Kazakhstan hoặc Ukraine.
// Đoạn mã minh họa logic kích hoạt dựa trên localStorage và thời gian
const STORAGE_KEY = 'protestware_init_time';
const THREE_DAYS_IN_MS = 3 * 24 * 60 * 60 * 1000;
function checkAndActivate() {
const currentTime = Date.now();
let initTime = localStorage.getItem(STORAGE_KEY);
if (!initTime) {
localStorage.setItem(STORAGE_KEY, currentTime);
return false; // Chưa đủ 3 ngày
}
initTime = parseInt(initTime, 10);
if (currentTime - initTime >= THREE_DAYS_IN_MS) {
return true; // Đủ điều kiện kích hoạt
}
return false; // Chưa đủ 3 ngày
}
// ... sau khi kiểm tra các điều kiện môi trường ...
if (checkAndActivate()) {
// Kích hoạt payload (vô hiệu hóa chuột, phát nhạc)
}Nguồn gốc và Sự Lan truyền
Nguồn gốc của protestware này có thể được truy tìm từ SweetAlert2, một thư viện phổ biến với hơn 700.000 lượt tải xuống hàng tuần, cung cấp các hộp thoại có thể tùy chỉnh để thay thế các popup JavaScript gốc. Người duy trì thư viện, limonte, đã công khai chức năng này từ phiên bản 11.6.14 được xuất bản khoảng ba năm trước, trong bối cảnh cuộc xâm lược Ukraine của Nga, và trong tất cả các bản phát hành tiếp theo cho đến 11.22.2, bao gồm cả các phiên bản trước đó như 9.17.3 và 11.6.6.
Tuy nhiên, script đã vô tình lan truyền sang các gói không liên quan, rất có thể thông qua việc sao chép mã trực tiếp, bằng chứng là các cấu trúc tệp và quy ước đặt tên giống hệt nhau. Lỗ hổng chuỗi cung ứng này ảnh hưởng đến nhiều dự án khác nhau mà không có bất kỳ xác nhận nào trong README, nhấn mạnh những nguy hiểm của việc tích hợp mã không được kiểm duyệt.
Các Chỉ số Độc hại (IOCs)
Các gói npm sau đây đã được xác định là bị ảnh hưởng bởi protestware này:
-
@starlawfirm/counsel-function- Lượt tải xuống cao nhất: 284
- Phiên bản bị ảnh hưởng: 13 phiên bản khác nhau, bao gồm phiên bản 0.0.12 được xuất bản 17 giờ trước thời điểm báo cáo.
-
falcon-library-comp- Lượt tải xuống: 1.822
- Phiên bản bị ảnh hưởng: 0.0.34–0.0.42
-
currency_contry_exchange- Lượt tải xuống: 1.276
- Phiên bản bị ảnh hưởng: 1.2.7–1.7.1
-
meshcentral- Lượt tải xuống: 16.895
- Phiên bản bị ảnh hưởng: 1.1.32–1.1.44
-
alurkerja-ui- Lượt tải xuống: 1.521
- Phiên bản bị ảnh hưởng: 572 phiên bản khác nhau.
-
starlawfirm-counsel-function-test- Lưu ý: Gói này đã bị deprecated (không còn được duy trì).
Nhiều gói trong số này vẫn đang hoạt động và đã có các bản cập nhật gần đây, cho thấy rủi ro tiếp tục tồn tại. Theo báo cáo từ Socket, các tác giả của các gói này rất đa dạng, từ các nhà phát triển cá nhân đến các nhóm, với các gói được tạo từ vài tháng đến vài năm trước, làm tăng mức độ phơi nhiễm.
Ảnh hưởng Chuỗi Cung ứng Phần mềm và Biện pháp Phòng ngừa
Hiệu ứng chuỗi domino từ SweetAlert2 minh họa cách protestware có thể vô tình nhúng vào các công cụ doanh nghiệp. Điều này nhấn mạnh tầm quan trọng của việc các nhà phát triển phải kiểm tra các phụ thuộc một cách nghiêm ngặt và sử dụng các công cụ chuyên dụng như Socket để chủ động phát hiện mối đe dọa trong kho lưu trữ npm.
Những phát hiện này, tính đến ngày 17 tháng 7 năm 2025, nhấn mạnh sự phát triển không ngừng của các cuộc tấn công chuỗi cung ứng phần mềm, nơi hoạt động xã hội được pha trộn với hành vi phá hoại kỹ thuật. Các tổ chức và nhà phát triển cần cảnh giác cao độ và áp dụng các biện pháp bảo mật mạnh mẽ để bảo vệ chuỗi cung ứng phần mềm của mình khỏi các mối đe dọa đa dạng này.










