Skip to main content
BlogWeb Dev

Manajemen Dependensi npm dan Audit Keamanan: Yang Benar-benar Saya Lakukan

Cara mengaudit dependensi npm untuk kerentanan, mengelola update debt, dan melindungi proyek Anda dari serangan supply chain.

Matthews Wong

Software Engineer

Juni 20259 menit baca
Web Dev

Pada 8 September 2025, penyerang mengkompromikan 18 paket npm yang banyak digunakan — termasuk chalk, debug, ansi-styles, dan strip-ansi — yang secara kolektif diunduh lebih dari 2,6 miliar kali per minggu. 80% dependensi aplikasi tetap tidak diperbarui selama lebih dari setahun, bahkan ketika 95% komponen yang rentan memiliki versi yang diperbaiki tersedia. Statistik ini mendefinisikan taruhannya: supply chain Anda seaman maintainer paling tidak aman dari paket apa pun di pohon dependensi Anda.

npm audit: Apa yang Diberitahukannya dan Apa yang Dilewatkannya

Menjalankan `npm audit` memeriksa paket yang diinstal terhadap database advisory npm — kerentanan yang diketahui dengan CVE yang diterbitkan. Ini mengembalikan daftar kerentanan dengan rating keparahan, versi paket yang terpengaruh, dan perbaikan yang direkomendasikan. Keterbatasan: `npm audit` hanya menangkap kerentanan yang diketahui dengan advisory yang diterbitkan. Tidak dapat mendeteksi eksploitasi zero-day, paket berbahaya, serangan typosquatting, atau versi berbahaya yang baru diterbitkan dari paket yang sah.

Membaca Output Audit

Output npm audit mencakup tingkat keparahan: critical (dapat dieksploitasi, dampak tinggi), high (dapat dieksploitasi, dampak signifikan), moderate (memerlukan kondisi yang tidak biasa), dan low (dampak minimal). Untuk aplikasi produksi, perbaiki critical dan high segera. Moderate dapat dijadwalkan di sprint berikutnya. Low dapat di-batch.

Perbedaan Antara Dependensi Langsung dan Transitive

Package.json Anda mencantumkan dependensi langsung — paket yang Anda instal secara eksplisit. Dependensi transitive adalah paket yang diperlukan oleh dependensi langsung Anda. Aplikasi Next.js tipikal memiliki 30-50 dependensi langsung dan 500-1.000 dependensi transitive. Sebagian besar kerentanan yang ditandai oleh `npm audit` ada dalam dependensi transitive.

npm Dependency Landscape (2025 reality):
────────────────────────────────────────────────────────────
Typical Next.js app:
  package.json:  ~40 direct dependencies
  node_modules:  ~800 total packages (transitives included)
                  ↑ you didn't install 760 of these directly

Vulnerability sources:
  Direct deps:    You chose these → easy to update
  Transitive:     Pulled by your deps → harder to control

Sept 2025 supply chain attack:
  Packages compromised: chalk, debug, ansi-styles, strip-ansi
  Weekly downloads:     2.6 BILLION combined
  Attack vector:        Phishing against package maintainer
  Detection:            Not by npm audit (no CVE yet)

npm audit severity levels:
  critical  → Fix immediately (RCE, SQLi, auth bypass)
  high      → Fix this sprint
  moderate  → Schedule within 30 days
  low       → Batch with monthly updates
  info      → Review, may be false positive

npm audit --audit-level=high  ← CI threshold I use
  Fails CI only on high/critical → meaningful signal
  Low/moderate reviewed weekly as separate task

Dari pengalaman saya mengelola dependensi proyek Next.js: jalankan `npm audit --audit-level=high` di CI daripada hanya `npm audit`. Level audit default adalah low, yang menandai kerentanan yang biasanya informatif dan dapat menyebabkan 'audit fatigue' — pengembang mulai mengabaikan output karena selalu ada item yang ditandai. Mengatur --audit-level=high membuat CI gagal hanya untuk kerentanan high dan critical, memberi alert makna.

Menjaga Dependensi Diperbarui

Pertahanan terbaik terhadap kerentanan yang diketahui adalah tetap terkini — sebagian besar CVE memiliki versi yang diperbaiki tersedia. `npm outdated` mencantumkan paket dengan pembaruan yang tersedia. Gunakan `npx npm-check-updates` (ncu) untuk memperbarui package.json ke versi terbaru. Proses pembaruan yang aman: jalankan `ncu -u --target minor` untuk memperbarui versi minor (semver menjamin tidak ada perubahan yang merusak), tes, lalu tangani pembaruan versi major satu per satu.

Dependabot dan PR Otomatis

GitHub Dependabot secara otomatis membuat pull request untuk pembaruan dependensi. Aktifkan dengan menambahkan file .github/dependabot.yml. Konfigurasikan untuk memperbarui ekosistem npm mingguan, mengelompokkan pembaruan patch dan minor bersama, dan memperbarui GitHub Actions secara terpisah. PR Dependabot mencakup jenis perubahan (patch/minor/major), tautan changelog, dan skor kompatibilitas.

# Weekly dependency audit workflow
npm audit --audit-level=high        # check for critical/high CVEs
npm outdated                         # list packages with updates available
npx npm-check-updates -u --target minor  # update minor versions in package.json
npm install                          # install updated packages
npm test && npm run e2e              # verify nothing broke

# Fix transitive dependency vulnerability (can't update the parent yet):
# In package.json, use overrides:
{
  "overrides": {
    "vulnerable-transitive-package": "^2.1.0"  // force safe version
  }
}

# .github/dependabot.yml — automated PR for updates
version: 2
updates:
  - package-ecosystem: npm
    directory: "/"
    schedule:
      interval: weekly
      day: monday
    groups:
      patch-and-minor:
        patterns: ["*"]
        update-types: ["minor", "patch"]
    ignore:
      - dependency-name: "@types/*"
        update-types: ["version-update:semver-major"]
  - package-ecosystem: github-actions
    directory: "/"
    schedule:
      interval: monthly

# CI — npm audit check in GitHub Actions
- name: Security audit
  run: npm audit --audit-level=high
  # Fails build if high or critical vulnerabilities found

# Use npm ci (not npm install) in CI — respects lockfile exactly
- name: Install dependencies
  run: npm ci
  # Fails if package-lock.json is out of sync with package.json

Keamanan Supply Chain Beyond npm audit

Untuk proyek dengan jaminan lebih tinggi, jauh di luar `npm audit`. Socket.dev memindai paket untuk perilaku mencurigakan (akses jaringan, eksekusi proses, kode yang diobfuskasi) yang tidak memicu CVE. Snyk menawarkan pemindaian dependensi dengan lebih banyak konteks daripada npm audit. OWASP npm Security Cheat Sheet merekomendasikan: mengunci dependensi transitive dengan lockfile, menggunakan `npm ci` alih-alih `npm install` di CI.

File package-lock.json menyematkan versi tepat dari setiap paket dalam pohon dependensi Anda, termasuk transitive. Tanpanya, `npm install` menyelesaikan versi terbaru dari setiap paket — artinya deployment dapat menarik versi berbahaya yang baru diterbitkan dari dependensi transitive yang bersih saat pengembangan. Selalu commit lockfile Anda, dan verifikasi itu tidak berubah sebelum deploy.

Kepatuhan Lisensi

Keamanan bukan satu-satunya risiko dependensi — lisensi adalah risiko hukum. Paket dengan lisensi GPL dalam pohon dependensi Anda dapat memaksakan persyaratan copyleft GPL pada seluruh proyek Anda. Gunakan `license-checker` (CLI) atau FOSSA (komersial, dengan integrasi CI) untuk memindai dependensi Anda untuk jenis lisensi. Untuk proyek komersial, Anda biasanya menginginkan lisensi MIT, BSD, Apache-2.0, dan ISC.

Rutinitas Kebersihan Dependensi Mingguan Saya

Yang benar-benar saya lakukan: Senin — jalankan `npm audit` dan periksa kerentanan critical/high baru. Mingguan — tinjau dan merge PR Dependabot untuk pembaruan patch dan minor setelah CI lulus. Bulanan — jalankan `ncu --target major` untuk melihat pembaruan major yang tertunda. Triwulan — audit penuh: kepatuhan lisensi, jumlah dependensi, dan dampak ukuran dependensi utama menggunakan `bundlephobia`.

Sumber & Bacaan Lebih Lanjut

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Apa perbedaan antara dependensi langsung dan dependensi transitive dalam proyek Next.js?

Dependensi langsung adalah paket yang Anda instal secara eksplisit dan tercantum di package.json, sedangkan dependensi transitive adalah paket yang dibutuhkan oleh dependensi langsung tersebut. Aplikasi Next.js tipikal memiliki 30–50 dependensi langsung tetapi 500–1.000 dependensi transitive. Sebagian besar kerentanan yang ditandai oleh npm audit berada di paket transitive yang tidak pernah Anda instal langsung, sehingga memerlukan penanganan khusus melalui upgrade paket induk atau menggunakan field overrides di npm.

Mengapa menggunakan --audit-level=high di CI daripada menjalankan npm audit dengan pengaturan default?

Level audit default adalah low, yang menandai kerentanan yang bersifat informatif dan menyebabkan 'audit fatigue' — pengembang mulai mengabaikan output karena selalu ada item yang ditandai. Menjalankan npm audit --audit-level=high membuat CI gagal hanya untuk kerentanan high dan critical, sehingga alert memiliki makna nyata. Kerentanan low dan moderate kemudian bisa ditinjau mingguan sebagai tugas terpisah yang tidak memblokir.

Mengapa package-lock.json dianggap file keamanan dan harus selalu di-commit?

Lockfile menyematkan versi tepat dari setiap paket dalam pohon dependensi Anda, termasuk yang transitive. Tanpanya, npm install menyelesaikan versi terbaru dari setiap paket saat instalasi berlangsung, yang berarti deployment dapat menarik versi berbahaya yang baru diterbitkan dari dependensi transitive yang sebelumnya bersih. Jika lockfile Anda berubah secara tak terduga setelah menjalankan npm install, selidiki sebelum merge — bisa jadi indikasi dependency confusion atau paket yang disusupi.

Alat apa yang bisa digunakan untuk keamanan supply chain di luar npm audit?

Socket.dev memindai paket untuk perilaku mencurigakan seperti akses jaringan, eksekusi proses, dan kode yang diobfuskasi — perilaku yang tidak memicu CVE dan tidak terdeteksi oleh npm audit. Snyk menawarkan pemindaian dependensi dengan lebih banyak konteks dan saran remediasi. OWASP npm Security Cheat Sheet juga merekomendasikan penggunaan npm ci daripada npm install di CI, karena npm ci menggunakan lockfile secara tepat dan gagal jika tidak sinkron.

Bagaimana kepatuhan lisensi harus ditangani sebagai bagian dari manajemen dependensi?

Lisensi adalah risiko hukum: paket dengan lisensi GPL dalam pohon dependensi Anda dapat memaksakan persyaratan copyleft pada seluruh proyek. Alat seperti license-checker (CLI) atau FOSSA (komersial, dengan integrasi CI) memindai dependensi Anda untuk jenis lisensi. Untuk proyek komersial, lisensi permisif seperti MIT, BSD, Apache-2.0, dan ISC lebih disukai, sementara GPL, AGPL, dan LGPL perlu pengawasan ekstra. Pemindaian lisensi sebaiknya menjadi bagian dari checklist onboarding saat menambahkan dependensi baru.