TL;DR — Bốn dòng trong
~/.npmrcchặn phần lớn cuộc tấn công supply chain npm trước khi chúng kịp chạy. Setup 30 giây. Đây là lớp phòng thủ tối thiểu cho bất kỳ ai để Claude Code hoặc Cursor tự chạynpm installtrên máy mình. Nhảy tới config →
📊 Bốn dòng này mang lại gì:
- Chặn vector
postinstallRAT (remote access trojan) dùng trong axios@1.14.1, Shai-Hulud, ua-parser-js- Pin version chính xác để một patch bị chiếm quyền không lặng lẽ lọt vào lockfile
- Fail
npm installlớn tiếng khi gặp CVE đã biết, không giấu trong output- Áp dụng cho mọi project trên máy bạn, không cần commit gì cả
🔒 Bốn dòng này đang chạy trên laptop của tôi ngay lúc này. Tôi thêm chúng ngay sáng hôm tin axios nổ ra, rồi quên luôn. Từ đó tới giờ, mọi lệnh
npm installmà Claude Code chạy trên máy tôi, qua năm project side khác nhau, đều bỏ qua lifecycle script mặc định. Không vỡ build. Không tốn công.
Đây là config. Copy vào ~/.npmrc ngay bây giờ:
ignore-scripts=truesave-exact=trueaudit-level=moderatefund=falseNăm 2025, kẻ tấn công đã publish 454,648 package npm độc hại, gần nửa triệu chỉ trong một năm (Sonatype Open Source Malware Index, 2026). Bốn dòng ở trên chặn cơ chế payload phổ biến nhất (lifecycle script) cho mọi project trên laptop của bạn, kể cả lệnh npm install mà Claude Code chạy lúc 2 giờ sáng hôm qua.
Bài này là sàn phòng thủ. Nếu bạn dùng AI coding tool (Claude Code, Cursor) và để nó tự gọi npm install, hãy đọc tiếp bài upgrade với hook. Nhưng trước tiên, làm bốn dòng này đã. 30 giây thôi.
Tại sao setup npm mặc định của bạn không an toàn năm 2026?
npm bật lifecycle script theo mặc định. Nghĩa là bất kỳ package nào, direct hay transitive, đều có thể chạy code tùy ý trên máy bạn trong khi npm install diễn ra, trước cả khi bạn gõ require(). Hơn 99% mã độc open source hiện nay nhắm vào npm, biến nó thành hệ sinh thái open source bị tấn công nhiều nhất (Sonatype, 2026).
Timeline nén của cùng một mô hình tấn công:
| Năm | Vụ việc | Vector payload |
|---|---|---|
| 2018 | event-stream (steal Bitcoin wallet, 2M/tuần) | postinstall |
| 09/2025 | Shai-Hulud worm, 18 package, 2.6B lượt tải/tuần | postinstall |
| 03/2026 | axios@1.14.1 RAT, 100M/tuần | postinstall |
Ba vụ lớn trong tám năm. Cùng một cơ chế mọi lần. Phản ứng chính thức của npm mỗi lần là unpublish package và đăng blog post. Không có thay đổi cấu trúc nào về cách postinstall hoạt động.
Key insight: Ngày 8 tháng 9 năm 2025, 18 package npm phổ biến với tổng 2.6 tỷ lượt tải mỗi tuần bị xâm phạm trong vụ Shai-Hulud (CISA, 2025). Tất cả đều dùng
postinstallscript làm vector thực thi. Nếu bạn đã bậtignore-scripts=truetrong~/.npmrc, payload sẽ bị vô hiệu hóa trên mọi máy dev bị ảnh hưởng, trước cả khi CVE được ghi nhận.
Phần khó chịu: 84% developer đang dùng hoặc có kế hoạch dùng AI coding tool, và 41% code viết năm 2025 là do AI tạo hoặc hỗ trợ (Stack Overflow 2025 Developer Survey). AI agent install package với tốc độ máy, cộng thêm approval fatigue làm phần còn lại. Bước review của con người từng chặn được những dependency lạ đã bị xóa khỏi workflow của hầu hết mọi người.
Bốn dòng .npmrc nào chặn được 80% tấn công?
Bốn dòng user-scope trong ~/.npmrc. Chúng áp dụng cho mọi project trên máy bạn, không cần commit gì, không đụng repo, không phải xin phép teammate. OWASP NPM Security Cheat Sheet liệt kê ba trong bốn dòng này như khuyến nghị hardening cơ bản (OWASP, 2026). Mỗi dòng nhắm vào một loại tấn công khác nhau.
ignore-scripts=truesave-exact=trueaudit-level=moderatefund=falseignore-scripts=true
Vô hiệu hóa preinstall, install, và postinstall lifecycle script cho mọi lệnh npm install. OWASP NPM Security Cheat Sheet gọi đây là biện pháp giảm thiểu hiệu quả nhất để chống package độc hại hoặc bị xâm nhập (OWASP, 2026). RAT trong axios@1.14.1, worm Shai-Hulud, cả Bitcoin stealer trong event-stream, đều cần cơ chế này để thực thi. Tắt nó đi trên phạm vi toàn máy, phương tiện triển khai mặc định biến mất.
save-exact=true
Pin version chính xác trong package.json mỗi khi bạn thêm package. Không có flag này, npm install axios sẽ ghi "axios": "^1.14.0", một caret range mà lần clean install tiếp theo sẽ resolve thành 1.14.1. Có save-exact=true, cùng lệnh đó ghi "axios": "1.14.0". Một patch bị chiếm quyền không thể tự promote mình vào lockfile một cách im lặng.
audit-level=moderate
Tăng exit code của npm install khi có CVE đã biết ở mức moderate trở lên. Mặc định chỉ warn. Flag này biến audit thành block, nghĩa là CI hoặc Claude Code session fail to tiếng thay vì trôi qua. Nếu project cũ của bạn cho quá nhiều false positive ở mức moderate, đổi sang high.
fund=false
Xóa dòng “N packages are looking for funding” khỏi mọi lần install. Mang tính thẩm mỹ, nhưng quan trọng. Khi output install 80% là thông báo funding, những warning thực sự quan trọng (audit, deprecation, peer dependency conflict) sẽ bị chôn vùi. Signal hygiene cũng là một lớp bảo mật.
Kiểm tra config sau khi lưu:
npm config get ignore-scripts save-exact audit-level fundOutput mong đợi: true, true, moderate, false. Nếu dòng nào ra khác, check lại vị trí file ~/.npmrc. Trên macOS và Linux: ~/.npmrc. Trên Windows: %USERPROFILE%\.npmrc.
Key insight:
ignore-scripts=truevàsave-exact=truelà hai default.npmrccó tác động cao nhất cho dev cá nhân theo hướng dẫn OWASP 2026 (OWASP NPM Security Cheat Sheet). Đặt chúng ở phạm vi user (trong~/.npmrcthay vì file ở cấp project) nghĩa là chúng bảo vệ mọi project trên máy, kể cả sandbox và workspace AI-agent mà dev thường quên mình đã tạo.
Tại sao cách này hiệu quả với phần lớn tấn công npm?
Mô hình payload chủ đạo trong các vụ tấn công npm năm 2025 và 2026 (axios, Shai-Hulud, event-stream, ua-parser-js) là một lifecycle script chạy trong lúc install. Tắt script đi là bẻ gãy phương tiện triển khai mặc định. Bảng mapping rõ ràng giữa bốn dòng và các loại tấn công chúng chặn:
| Vector tấn công | Ví dụ thực tế | Dòng chặn nó |
|---|---|---|
| postinstall RAT | axios@1.14.1 (2026) | ignore-scripts=true |
| Minor/patch hijack im lặng | Maintainer account takeover | save-exact=true |
| CVE đã biết bị ẩn trong warning | Bất kỳ advisory nào | audit-level=moderate |
| Warning fatigue che cảnh báo | Mỗi lần install, cả ngày | fund=false |
Con số “80%” trong tiêu đề là tỷ lệ ước chừng những vụ impact cao mà combo này sẽ chặn được trên máy dev. Đây không phải defense-in-depth. Đây là sàn.
Key insight: Ngày 31 tháng 3 năm 2026, axios@1.14.1 publish hai version độc hại chứa kết nối command-and-control tới hạ tầng Sapphire Sleet, triển khai RAT giai đoạn hai (Microsoft Security, 2026). Payload thực thi qua
postinstallscript của một dependency độc hại.ignore-scripts=truetrong~/.npmrcsẽ ngăn thực thi trên mọi máy chạynpm installtrong cửa sổ 3 tiếng bị compromise.
Config này KHÔNG bảo vệ được gì?
Thành thật về giới hạn. Config này chặn vector phổ biến nhất, không phải mọi vector. Dev nào cài bốn dòng rồi coi như xong là đang lặp lại đúng cái bẫy overconfidence mà mọi bài “3 lớp phòng thủ” đã dẫm phải (Tôi Set Up 3 Lớp Phòng Thủ, Nó Vẫn Xóa File). Những thứ vẫn bị phơi:
- Code độc trong main module. Bất cứ thứ gì chạy khi
require()hoặcimportkhông bịignore-scriptschặn. Nếu code bạn thực sự import package đó, payload vẫn chạy ở runtime. - Toolchain exploit.
--ignore-scriptschặn npm lifecycle hook, nhưng git vẫn chạy trong lúc install, và binary bên ngoài vẫn thực thi nếu quy trình install gọi chúng (Thinking Through Code, 2026). - Typosquatting và slopsquatting. AI trợ lý đôi khi hallucinate tên package mà kẻ tấn công đã đăng ký sẵn. OWASP đánh giá đây là loại tấn công npm tăng nhanh nhất năm 2026.
- Credential đã bị đánh cắp. Nếu token npm, GitHub PAT, hoặc cloud credential của bạn rò rỉ trước khi có config này, việc rotate là trách nhiệm của bạn.
- Package đã có trong
node_modules. Bốn dòng chỉ bảo vệ install tương lai. Nên rebuild sạch:rm -rf node_modules package-lock.json && npm install.
Nếu danh sách này làm bạn hơi lo, tốt. Lớp tiếp theo là enforcement ở cấp process. Đó là bài kế.
Key insight: Khoảng 20% mã độc npm tác động cao gần đây thực thi ngoài lifecycle script, qua
require()ở runtime hoặc main module đã bị xâm nhập, và--ignore-scriptskhông chặn được cái gì ở đó (Thinking Through Code, 2026). Coi.npmrclà cần-nhưng-chưa-đủ: lớp hook ở cấp process mới là nơi chặn được zero-day và vector không phải lifecycle.
ignore-scripts=true làm gì bị bể?
Một nhóm nhỏ package thực sự cần lifecycle script để compile binary native hoặc tải platform asset. Những cái tên hay gặp: bcrypt, node-sass, sharp, esbuild, puppeteer, canvas (Liran Tal, nodejs-security.com, 2025). Bạn sẽ phát hiện ngay lập tức vì chúng fail to tiếng, không lặng lẽ, đúng cái visibility mà bạn muốn.
Fix theo từng package:
# Install bình thường, rồi rebuild riêng package cần scriptnpm install sharpnpm rebuild sharpVới project có nhiều dependency native-compile, dùng allow-list thay vì bật lại script toàn bộ. @lavamoat/allow-scripts cho bạn liệt kê rõ ràng package được tin cậy:
npm install --save-dev @lavamoat/allow-scriptsnpx allow-scripts autonpx allow-scriptsDanh sách package thường cần npm rebuild sau khi install:
| Package | Lý do cần script |
|---|---|
bcrypt | Compile C++ native |
sharp | Tải binary + native binding |
node-sass | Build LibSass native |
esbuild | Tải binary theo platform |
puppeteer | Tải Chromium |
canvas | Native binding Cairo/Pango |
Chín mươi phần trăm project không đụng tới package nào trong nhóm này. Project đụng tới thì fail lần chạy CI đầu sau khi đổi config, và bạn fix một lần.
Key insight:
@lavamoat/allow-scriptslà công cụ allow-list được khuyến nghị khiignore-scripts=trueđang bật và một số dependency cần lifecycle thực thi (Liran Tal, 2025). Nó cho phép bạn liệt kê rõ ràng package tin cậy thay vì bật lại script cho cả cây dependency, vốn là cái mà phần lớn dev tình cờ làm.
Upgrade lên phòng thủ dựa trên hook
~/.npmrc là sàn user-scope. Lớp tiếp theo là enforcement ở cấp process: chặn mọi npm install mà Claude Code cố chạy, audit trước khi lệnh thực thi, và block cuộc gọi nếu thiếu --ignore-scripts hoặc trỏ vào dependency mới chưa review. Với 41% code năm 2025 là do AI tạo hoặc hỗ trợ (Stack Overflow, 2025), agent chứ không phải con người mới là thứ chính kích hoạt npm install. Đó là PreToolUse hook (một lifecycle hook trong Claude Code chạy trước mỗi tool call) trong .claude/settings.json.
Bài về hook bao phủ setup ba lớp: PreToolUse audit, PostToolUse lockfile diff, và quy tắc enforcement trong CLAUDE.md. Setup 5 phút. Nếu bạn đã chạy Claude Code ở chế độ auto-accept, đây là lưới an toàn bạn cần.
Key insight: Enforcement ở cấp process qua
PreToolUsehook của Claude Code chặn lệnhnpm installthiếu--ignore-scriptstrước khi lệnh thực thi, đóng lỗ hổng runtime mà.npmrcmột mình không thể bao phủ (ShipWithAI, 2026). Kết hợp default.npmrcở user-scope với chặn ở cấp hook là pattern hai lớp mà series bài này hướng tới.
Nhận tip Claude Code security hàng tuần — Một email mỗi tuần. Hook, pattern CLAUDE.md, và phân tích tấn công thật. Subscribe AI Developer Weekly →
Thử ngay: Mở terminal và chạy
echo -e "ignore-scripts=true\nsave-exact=true\naudit-level=moderate\nfund=false" >> ~/.npmrc, rồi verify bằngnpm config get ignore-scripts save-exact audit-level fund. Tổng thời gian: dưới 30 giây. Lầnnpm installtiếp theo, ở bất kỳ project nào, đều dùng default mới.
Sẵn sàng cho phòng thủ cấp process? Đọc tiếp → Chặn Tấn Công Supply Chain npm Bằng Claude Code Hooks.
Muốn nhận ba bài hardening npm tiếp theo qua email? Một email mỗi tuần, chuyên về security. Đăng ký AI Developer Weekly →
FAQ
ignore-scripts=true có làm bể build không?
Thường là không, với dependency thuần JavaScript, chiếm hơn 90% project React hoặc Node điển hình. Có, với package native-compile như bcrypt, sharp, esbuild. Cách fix là npm rebuild <pkg> theo từng package, hoặc @lavamoat/allow-scripts cho allow-list ở cấp team. Phần lớn solo dev không bao giờ đụng build bị bể.
Có nên commit .npmrc vào repo không?
Config cá nhân vào ~/.npmrc (không commit, là user default). Project-level .npmrc ở repo root có thể commit miễn là không chứa secret, để teammate dùng chung default. Registry auth token chỉ đặt ở ~/.npmrc, không bao giờ trong repo.
Còn esbuild, sharp, và các package native khác thì sao?
Chúng cần postinstall để compile hoặc tải binary. Ba lựa chọn: (1) npm rebuild <pkg> sau mỗi install, (2) allow-list qua @lavamoat/allow-scripts, (3) pin package với save-exact=true và review trước mỗi lần upgrade. Phương án 1 là default cho solo project. Phương án 2 scale cho team.
Cách này có dùng được với pnpm và yarn không?
.npmrc dùng chung. pnpm đọc ignore-scripts=true trực tiếp. Yarn classic cũng đọc .npmrc. Yarn Berry dùng .yarnrc.yml thay thế, setting tương đương là enableScripts: false. Bun cũng honor .npmrc qua pm config của nó.
npm audit có còn hữu ích nếu đặt audit-level=moderate?
Có, và thậm chí hữu ích hơn. Flag này đổi audit từ warn-mode sang block-mode với CVE từ severity moderate trở lên. CVE đã biết sẽ fail install to tiếng. Audit vẫn chỉ bắt được CVE đã được công bố. Với zero-day, bạn cần lớp hook từ bài hook.
Đọc Tiếp
- Chặn Tấn Công Supply Chain npm Bằng Claude Code Hooks — Upgrade cấp process. PreToolUse hook chặn
npm installthiếu--ignore-scripts, lockfile diff bắt transitive dep mới, CLAUDE.md enforce pin version. - Bảo Vệ Code Nhạy Cảm Khi Dùng Claude Code — Bốn chiến lược giữ secret khỏi context Claude Code trên repo thật, bao gồm
.claudeignorevà cô lập git worktree. - Tôi Set Up 3 Lớp Phòng Thủ Claude Code, Nó Vẫn Xóa File — Kiểu thất bại của defense-in-depth mà bài này muốn tránh. Test trường hợp thường gặp, không chỉ trường hợp tệ nhất.