TÓM TẮT
Các cuộc tấn công chuỗi cung ứng NPM đã tăng vọt lên hơn 3.000 gói độc hại chỉ riêng trong năm 2024, và vụ xâm nhập Axios tháng 3 năm 2026 đã chứng minh rằng ngay cả các gói nằm trong top 10 cũng không an toàn. Hướng dẫn này bao gồm mọi lớp phòng thủ mà nhà phát triển API cần: thực thi lockfile, chặn script postinstall, xác minh nguồn gốc, công cụ phân tích hành vi và các lựa chọn kiến trúc giúp thu hẹp bề mặt tấn công của bạn.
Giới thiệu
Cuộc tấn công chuỗi cung ứng Axios vào ngày 31 tháng 3 năm 2026 không phải là vụ xâm nhập npm đầu tiên. Và nó cũng sẽ không phải là cuối cùng. Nhưng với 83 triệu lượt tải xuống hàng tuần và một RAT (công cụ truy cập từ xa) đa nền tảng được triển khai thông qua một tài khoản bảo trì bị chiếm quyền kiểm soát, đó là tiếng chuông cảnh tỉnh lớn nhất mà hệ sinh thái JavaScript đã nhận được.
Đây là điều làm cho vụ việc này khác biệt so với lời khuyên thông thường “cập nhật các phần phụ thuộc của bạn”: cuộc tấn công Axios đã vượt qua mọi biện pháp phòng thủ truyền thống. Mã độc không nằm trong chính Axios. Nó được tiêm vào thông qua một phần phụ thuộc ảo đã kích hoạt hook postinstall. Lockfile không giúp ích gì nếu bạn chạy npm install trong thời gian cuộc tấn công diễn ra. Việc ghim phiên bản cũng không giúp ích nếu bạn chưa ghim.
Các nhà phát triển API đặc biệt dễ bị tổn thương. Các script kiểm thử, pipeline CI/CD, máy chủ giả lập và client HTTP của bạn đều kéo từ npm. Một gói bị xâm nhập duy nhất trong chuỗi công cụ của bạn có thể làm rò rỉ khóa API, thông tin đăng nhập cơ sở dữ liệu và token đám mây từ máy phát triển của bạn.
💡 Apidog loại bỏ một vector tấn công lớn bằng cách cung cấp một client HTTP tích hợp sẵn để kiểm thử API, vì vậy bạn không cần Axios, node-fetch, hoặc got trong bộ công cụ kiểm thử của mình. Tải xuống Apidog miễn phí để giảm bề mặt phụ thuộc npm của bạn trong khi áp dụng các chiến lược phòng thủ dưới đây.
Hướng dẫn này bao gồm bảy lớp bảo vệ, từ vệ sinh lockfile cơ bản đến phân tích hành vi nâng cao.
Lớp 1: Thực thi lockfile
Tại sao lockfile quan trọng
Lockfile ghi lại phiên bản chính xác của mọi gói và các phần phụ thuộc bắc cầu tại thời điểm cài đặt. Nếu không có lockfile, npm install sẽ phân giải phiên bản mới nhất phù hợp với phạm vi semver của bạn. Nếu package.json của bạn ghi "axios": "^1.14.0" và một phiên bản 1.14.1 độc hại tồn tại trên registry, bạn sẽ nhận được phiên bản độc hại đó.
Các quy tắc
Luôn commit lockfile của bạn. Dù là package-lock.json (npm), yarn.lock (Yarn), pnpm-lock.yaml (pnpm), hay bun.lock (Bun), nó đều thuộc về hệ thống kiểm soát phiên bản.
Sử dụng chế độ cài đặt đông lạnh (frozen installs) trong CI/CD. Không bao giờ chạy npm install trong các môi trường tự động. Hãy sử dụng lệnh tương đương với lockfile đông lạnh:
# npm
npm ci
# yarn
yarn install --frozen-lockfile
# pnpm
pnpm install --frozen-lockfile
# bun
bun install --frozen-lockfile
npm ci xóa node_modules và cài đặt nghiêm ngặt từ lockfile. Nếu lockfile không khớp với package.json, nó sẽ thất bại. Điều này ngăn chặn những bất ngờ trong quá trình phân giải.
Xem xét các thay đổi lockfile trong pull request. Khi một PR sửa đổi package-lock.json, hãy kiểm tra những gì đã thay đổi. Các phần phụ thuộc mới, tăng phiên bản và thay đổi URL registry đều cần được xem xét kỹ lưỡng. Công cụ như Socket.dev có thể gắn cờ các thay đổi lockfile đáng ngờ trong các đánh giá PR.
Khoảng trống của lockfile
Lockfile bảo vệ chống lại việc phân giải phiên bản không mong muốn, nhưng không bảo vệ khỏi lần cài đặt đầu tiên. Nếu bạn khởi tạo dự án hoặc thêm phần phụ thuộc mới đúng lúc diễn ra tấn công, phiên bản độc hại sẽ bị khóa lại. Đây là lý do lockfile chỉ là Lớp 1, không phải duy nhất.
Lớp 2: Vô hiệu hóa script postinstall
Vector tấn công chính
Cuộc tấn công Axios, ua-parser-js, event-stream và nhiều vụ khác đều sử dụng script postinstall để chạy mã độc tùy ý trong quá trình cài đặt. Hook này thực thi trước khi mã ứng dụng của bạn chạy và trước khi bất kỳ công cụ bảo mật nào kịp can thiệp.
Chặn script trên toàn cầu
Thêm vào .npmrc:
ignore-scripts=true
Hoặc qua CLI:
npm config set ignore-scripts true
Điều này ngăn chặn mọi script vòng đời (preinstall, install, postinstall, prepare) chạy khi cài đặt.
Xử lý các gói cần script
Một số gói như bcrypt, sharp, hoặc sqlite3 cần script postinstall để biên dịch native. Có thể xử lý như sau:
Tùy chọn 1: Chạy script chọn lọc sau khi cài đặt
npm ci --ignore-scripts
npm rebuild bcrypt sharp
Tùy chọn 2: Danh sách cho phép (npm 10+)
Tạo file .scriptsrc.json:
{
"allowScripts": {
"bcrypt": true,
"sharp": true
}
}
Tùy chọn 3: Dùng binary biên dịch sẵn
Nhiều gói giờ đã hỗ trợ binary sẵn, không cần script biên dịch. Kiểm tra trước khi cấp phép chạy script.
Lưu ý về PackageGate
Vào tháng 1/2026, các lỗ hổng "PackageGate" cho thấy phần phụ thuộc Git có thể mang tệp cấu hình cho phép thực thi mã ngay cả khi đã tắt scripts. Nếu package.json tham chiếu URL Git, hãy ghim vào commit hash cụ thể và kiểm tra nội dung repo.
Lớp 3: Ghim các phiên bản chính xác
Ngừng dùng phạm vi semver
Mặc định, npm install --save thêm tiền tố dấu mũ:
{
"axios": "^1.14.0"
}
Dấu ^ nghĩa là “tương thích với 1.14.0”, và sẽ lấy bản 1.x.x mới nhất—có thể là độc hại.
Cách ghim phiên bản:
{
"axios": "1.14.0"
}
Cấu hình npm để lưu phiên bản chính xác:
# .npmrc
save-exact=true
save-prefix=''
Ghi đè phần phụ thuộc bắc cầu
Dùng overrides để kiểm soát phiên bản:
{
"overrides": {
"axios": "1.14.0",
"plain-crypto-js": "npm:empty-npm-package@1.0.0"
}
}
Yarn:
{
"resolutions": {
"axios": "1.14.0"
}
}
pnpm:
{
"pnpm": {
"overrides": {
"axios": "1.14.0"
}
}
}
Đánh đổi
Ghim chính xác đồng nghĩa bạn tự tay nâng cấp, không còn tự động vá lỗi nhỏ. Đối với dự án nhạy cảm bảo mật, sự đánh đổi này là hợp lý.
Lớp 4: Xác minh nguồn gốc gói
Nguồn gốc là gì?
Nguồn gốc npm dùng chữ ký Sigstore liên kết gói đã xuất bản với repo nguồn và pipeline CI/CD đã build ra nó. Bằng chứng này giúp xác thực:
- Repo nguồn nào được dùng
- Hệ thống CI/CD nào đã build
- Commit nào kích hoạt build
Cách kiểm tra nguồn gốc
npm audit signatures
Lệnh này xác thực các package đã cài đặt có xác nhận nguồn gốc hợp lệ không.
Bật nguồn gốc khi xuất bản package
Thêm vào CI/CD:
# GitHub Actions example
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
- run: npm publish --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Thêm vào .npmrc:
provenance=true
Hạn chế
Provenance là tùy chọn và chỉ chứng minh nơi gói được build, không đảm bảo mã nguồn an toàn tuyệt đối.
Lớp 5: Sử dụng công cụ phân tích hành vi
Không chỉ quét lỗ hổng
Các công cụ như npm audit hay Snyk chỉ kiểm tra các CVE đã biết. Tấn công kiểu zero-day, như Axios, sẽ không phát hiện được.
Công cụ phân tích hành vi kiểm tra hành động thực sự của gói.
Socket.dev
Socket phân tích hành vi cài đặt và runtime. Gắn cờ:
- Yêu cầu mạng khi cài đặt
- Truy cập file ngoài thư mục gói
- Thực thi shell
- Thu thập biến môi trường
- Mã bị che khuất
Để sử dụng:
# Cài đặt Socket CLI
npm install -g @socketsecurity/cli
# Quét dự án
socket scan
Snyk
Snyk mạnh về lỗ hổng đã biết, điểm rủi ro, hướng dẫn khắc phục.
# Cài đặt Snyk CLI
npm install -g snyk
# Quét dự án
snyk test
Phối hợp nhiều lớp
Kết hợp cả ba công cụ:
# Cơ bản
npm audit
# Phân tích hành vi
socket scan
# Quản lý lỗ hổng
snyk test
Chạy tất cả trong CI/CD. Phát hiện nghiêm trọng phải chặn build.
Lớp 6: Giảm thiểu bề mặt phụ thuộc
Kiểm tra cây phụ thuộc
# Đếm tổng số phần phụ thuộc
npm ls --all | wc -l
# Kiểm tra trùng lặp
npm ls --all | sort | uniq -c | sort -rn | head -20
Tự hỏi với từng phụ thuộc:
- Tính năng này Node.js native đã có chưa?
- Gói này kéo theo bao nhiêu phụ thuộc con?
- Có thể vendor mã nguồn vào dự án không?
Thay thế native cho các gói phổ biến
| Gói | Thay thế native | Có sẵn từ |
|---|---|---|
| axios, node-fetch, got |
fetch (global) |
Node.js 18 |
| uuid | crypto.randomUUID() |
Node.js 19 |
| dotenv |
--env-file flag |
Node.js 20.6 |
| chalk | util.styleText() |
Node.js 21.7 |
| glob | fs.glob() |
Node.js 22 |
| path-to-regexp | Native URL pattern API | Node.js 23 |
Đặc biệt cho kiểm thử API
Kiểm thử API thường kéo theo nhiều phụ thuộc (client HTTP, assert, test runner, mock server).
Apidog thay thế toàn bộ stack:
- Client HTTP: tích hợp sẵn, không cần npm package
- Khẳng định: builder kiểm thử trực quan
- Test runner: tự động, hỗ trợ CI/CD qua Apidog CLI
- Mock server: giả lập thông minh, không cần Express/third-party
- Tài liệu: tự động từ spec API
Chuyển kiểm thử API sang Apidog giúp loại bỏ hàng chục package npm khỏi stack kiểm thử.
Dùng thử Apidog miễn phí để hợp nhất stack kiểm thử API của bạn.
Lớp 7: Giám sát mạng và thời gian chạy
Chặn tên miền độc hại đã biết
Sau mỗi cuộc tấn công, hãy chặn domain chỉ huy & kiểm soát ở cấp mạng:
# Thêm vào /etc/hosts
echo "0.0.0.0 sfrclak.com" | sudo tee -a /etc/hosts
Trong CI/CD, hạn chế outbound network chỉ cho phép registry, git server, đích triển khai.
StepSecurity Harden-Runner cho CI/CD
StepSecurity Harden-Runner giám sát workflow GitHub Actions theo thời gian thực.
# GitHub Actions
- uses: step-security/harden-runner@v2
with:
egress-policy: audit # hoặc 'block' cho nghiêm ngặt
Giám sát thời gian chạy
Với máy phát triển, dùng EDR để gắn cờ quy trình con bất thường mà Node.js tạo ra: osascript (macOS), cscript (Windows), python3 (Linux) từ trong npm install có thể bị phát hiện.
Cấu hình .npmrc được khuyến nghị
Một file .npmrc mẫu bảo mật:
# Ghim phiên bản chính xác
save-exact=true
save-prefix=
# Vô hiệu hóa script vòng đời
ignore-scripts=true
# Bật nguồn gốc khi publish
provenance=true
# Dùng registry chính thức
registry=https://registry.npmjs.org/
# Yêu cầu 2FA khi xuất bản
auth-type=web
# Ngưỡng mức kiểm toán
audit-level=moderate
Commit file này lên repo để toàn bộ nhóm dùng chung cài đặt bảo mật.
Ví dụ pipeline bảo mật CI/CD
Workflow GitHub Actions thực thi đủ 7 lớp:
name: Secure Build
on: [push, pull_request]
jobs:
security-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: step-security/harden-runner@v2
with:
egress-policy: audit
- uses: actions/setup-node@v4
with:
node-version: 22
# Lớp 1+2: Lockfile đông lạnh, không script
- run: npm ci --ignore-scripts
# Lớp 3: Kiểm tra không có version lạ
- run: npm ls --all > deps.txt
# Lớp 4: Kiểm tra provenance
- run: npm audit signatures
# Lớp 5: Phân tích hành vi
- run: npx socket scan
# Lớp 5: Quét lỗ hổng
- run: npx snyk test
# Lớp 1: Kiểm toán cơ bản
- run: npm audit --audit-level=moderate
# Chỉ rebuild các phụ thuộc native được phép
- run: npm rebuild sharp bcrypt
Điều gì sẽ đến tiếp theo cho bảo mật npm
Xác nhận nguồn gốc bắt buộc cho các gói phổ biến
npm đang xem xét yêu cầu provenance cho các gói vượt qua ngưỡng tải xuống nhất định, nhằm ngăn xuất bản thủ công bằng token như vụ Axios.
Phê duyệt phát hành hai người
Các gói tải xuống cao có thể phải được hai maintainer phê duyệt trước khi phát hành.
Phạm vi quyền runtime
Deno đã hạn chế quyền truy cập mạng, file, env. Node.js cũng đang nghiên cứu mô hình quyền tương tự: script postinstall sẽ cần xin quyền rõ ràng.
Sự hội tụ của package manager
pnpm đã triển khai cách ly nghiêm ngặt: gói chỉ truy cập phụ thuộc đã khai báo. Khi npm áp dụng tương tự, bề mặt tấn công sẽ giảm tiếp.
Câu hỏi thường gặp
Tấn công chuỗi cung ứng trong npm là gì?
Kẻ tấn công xâm nhập account maintainer, tiêm mã độc vào các gói phổ biến hoặc xuất bản typosquat. Khi bạn cài đặt/cập nhật phụ thuộc, mã độc sẽ thực thi trên máy của bạn hoặc CI/CD pipeline, đánh cắp thông tin đăng nhập, cài backdoor hoặc lấy cắp dữ liệu.
npm audit có đủ để bảo vệ chống lại tấn công chuỗi cung ứng không?
Không. npm audit chỉ quét CVE đã biết. Các tấn công zero-day như Axios sẽ không phát hiện. Cần thêm các công cụ phân tích hành vi như Socket.dev.
Có nên ngừng sử dụng npm hoàn toàn không?
Không. npm vẫn là hệ sinh thái lớn nhất, đa số gói an toàn. Hãy giảm thiểu rủi ro bằng ghim phiên bản, thực thi lockfile, chặn script, giảm phụ thuộc và dùng lựa chọn native khi có thể.
Apidog giúp giảm rủi ro chuỗi cung ứng npm như thế nào?
Apidog cung cấp client HTTP, test runner, mock server, document generator—all-in-one—loại bỏ nhu cầu về các gói npm như Axios, node-fetch, Jest, Express... Giảm số lượng package npm, giảm vector tấn công.
Nguồn gốc gói trong npm là gì?
Nguồn gốc dùng Sigstore liên kết mật mã package đã xuất bản với repo nguồn và CI/CD. Xác minh bằng npm audit signatures. Gói xuất bản thủ công từ máy dev sẽ thiếu nguồn gốc—cảnh báo với các package download cao.
Có bao nhiêu gói npm độc hại?
Năm 2024 Snyk xác định hơn 3.000 gói npm độc hại. Q4/2025, Sonatype chặn 120.612 cuộc tấn công malware trong một quý trên npm, PyPI,... Chủ yếu là typosquat, nhưng các vụ lớn như Axios cho thấy gói nổi tiếng vẫn bị tấn công.
Lỗ hổng PackageGate là gì?
PackageGate là sáu lỗ hổng zero-day công bố tháng 1/2026 ảnh hưởng npm, pnpm, vlt, Bun. Phụ thuộc Git có thể mang config cho phép thực thi mã ngay cả khi đã tắt script. Hãy ghim phụ thuộc Git vào commit hash cụ thể.
Những điểm chính cần ghi nhớ
- Thực thi lockfile là nền tảng, nhưng không bảo vệ khỏi lần cài đặt đầu tiên khi diễn ra tấn công
- Vô hiệu hóa script postinstall trên toàn cầu bằng
ignore-scripts=truetrong .npmrc - Ghim phiên bản chính xác với
save-exact=true - Xác minh nguồn gốc gói với
npm audit signatures - Kết hợp Socket.dev (phân tích hành vi), Snyk (lỗ hổng đã biết),
npm audit(cơ bản) - Giảm số lượng phụ thuộc bằng API native Node.js và nền tảng tích hợp như Apidog
- Giám sát lưu lượng mạng CI/CD với StepSecurity Harden-Runner
Mỗi phần phụ thuộc là một quyết định tin cậy. Càng ít phụ thuộc, bề mặt tấn công càng nhỏ. Xây dựng phòng thủ theo chiều sâu, không chỉ đơn độc một lớp.
Tải xuống ứng dụng



Top comments (0)