Gambaran Umum

Dalam ekosistem pengembangan perangkat lunak modern, hampir setiap proyek bergantung pada paket pihak ketiga (third-party packages) yang dikelola melalui manajer paket seperti npm. Sayangnya, tidak semua paket tersebut bebas dari celah keamanan. npm audit adalah perintah bawaan npm yang dirancang khusus untuk mendeteksi, menganalisis, dan melaporkan kerentanan keamanan (vulnerabilities) yang ada dalam dependensi proyek Anda. Perintah ini pertama kali diperkenalkan di npm versi 6 dan telah menjadi alat esensial dalam workflow keamanan setiap proyek Node.js.

Mengapa perintah ini sangat penting? Setiap hari, ribuan paket npm diunduh dan digunakan oleh jutaan developer di seluruh dunia. Paket-paket tersebut dikelola oleh manusia, dan manusia bisa membuat kesalahan—baik berupa bug logika, kesalahan konfigurasi, maupun celah keamanan yang bisa dieksploitasi oleh pihak tidak bertanggung jawab. Serangan supply chain, di mana paket populer diretas dan disisipi kode berbahaya, juga semakin marak terjadi. Dengan menjalankan npm audit, Anda mendapatkan visibilitas langsung terhadap risiko-risiko yang mungkin terselubung di dalam node_modules Anda, sehingga Anda bisa mengambil tindakan sebelum kerentanan tersebut menjadi bencana di produksi.

Berikut adalah step-by-step dasar untuk memulai pemeriksaan kerentanan menggunakan npm audit:

Langkah 1: Pastikan npm Anda sudah versi 6 atau lebih baru

npm --version

Jika versi Anda masih di bawah 6, perbarui npm terlebih dahulu:

npm install -g npm@latest

Langkah 2: Navigasi ke direktori proyek Anda

cd /path/to/your/project

Langkah 3: Jalankan perintah audit

npm audit

Langkah 4: Baca laporan yang dihasilkan

npm akan menghubungi registry-nya, membandingkan versi paket yang Anda instal dengan database kerentanan yang dikurasi oleh tim npm dan komunitas security, lalu menampilkan laporan lengkap berupa jumlah kerentanan berdasarkan tingkat keparahan (low, moderate, high, critical), nama paket yang bermasalah, versi yang rentan, versi yang sudah diperbaiki (patched), serta tautan ke advisories terkait.

Langkah 5: Perbaiki kerentanan secara otomatis (jika memungkinkan)

npm audit fix

Perintah ini akan mencoba memperbarui paket-paket yang rentan ke versi yang sudah diperbaiki, dengan tetap menghormati batasan semver yang tercantum di package.json Anda.


Prinsip Kerjanya

Untuk memahami bagaimana npm audit bekerja secara mendalam, kita perlu melihat konsep inti yang mendasarinya. Pada tingkat fundamental, npm audit beroperasi dengan membangun pohon dependensi (dependency tree) lengkap dari proyek Anda—tidak hanya dependensi langsung yang Anda tulis di package.json, tetapi juga seluruh dependensi transitif, yaitu paket-paket yang dibutuhkan oleh dependensi Anda, dan seterusnya hingga ke daun pohon. Pohon ini kemudian dikirimkan ke npm registry audit endpoint dalam format JSON terstruktur. Registry akan merespons dengan daftar advisories (laporan kerentanan) yang cocok dengan versi paket yang Anda gunakan.

Komponen utama dalam mekanisme ini terdiri dari beberapa bagian yang saling terintegrasi. Pertama, ada package-lock.json atau npm-shrinkwrap.json yang berfungsi sebagai sumber kebenaran (source of truth) untuk versi pasti setiap paket yang terinstal. Tanpa file lock ini, npm audit tidak bisa menentukan versi eksakt yang sedang digunakan, sehingga pemeriksaan menjadi tidak akurat. Kedua, ada audit endpoint yang di-host di registry.npmjs.org. Endpoint ini menerima payload berupa dependency tree dan mengembalikan advisories berdasarkan database CVE (Common Vulnerabilities and Exposures) dan laporan dari komunitas. Ketiga, ada resolution engine yang bekerja di balik npm audit fix. Engine ini menghitung versi termutakhir yang kompatibel dengan constraint semver di package.json Anda dan mencoba melakukan upgrade secara non-breaking.

Proses resolusi ini tidak selalu trivial. Bayangkan Anda memiliki paket A versi 1.0.0 yang bergantung pada paket B versi ^2.0.0, dan paket B versi 2.3.0 ternyata rentan. Jika versi yang diperbaiki adalah B versi 2.4.0, maka engine bisa meng-upgrade B ke 2.4.0 tanpa masalah karena masih dalam range ^2.0.0. Namun, jika kerentanan hanya diperbaiki di B versi 3.0.0, maka upgrade akan menjadi breaking change, dan npm audit fix tidak akan melakukannya secara otomatis—Anda perlu intervensi manual.


Skenario Penggunaan

Skenario 1: Pemeriksaan rutin pada proyek baru

Saat Anda meng-clone repository baru atau baru saja menjalankan npm install, praktik terbaik adalah langsung memeriksa apakah ada kerentanan di baseline proyek tersebut.

npm install
npm audit

Output yang mungkin Anda lihat:

found 3 vulnerabilities (1 low, 1 moderate, 1 high)
  run `npm audit` for details

Ketika Anda menjalankan ulang npm audit untuk melihat detailnya:

# npm audit report

lodash  <4.17.21
Severity: high
Prototype Pollution in lodash - https://github.com/advisories/GHSA-p6mc-m468-83gw
fix available via `npm audit fix`
node_modules/lodash
  lodash  4.17.15 -> 4.17.21

2 other vulnerabilities found

Dari sini Anda langsung tahu bahwa lodash versi di bawah 4.17.21 memiliki kerentanan prototype pollution dengan severity high, dan bisa diperbaiki dengan npm audit fix.

Skenario 2: Memperbaiki kerentanan otomatis

Setelah mengetahui ada kerentanan, langkah pertama yang harus dicoba adalah perbaikan otomatis:

npm audit fix

Output:

fixed 2 of 3 vulnerabilities in 124 scanned packages
  1 vulnerability required manual review and could not be fixed

npm berhasil memperbaiki dua kerentanan secara otomatis, tetapi menyisakan satu yang membutuhkan review manual—biasanya karena fix-nya melibatkan major version bump yang bersifat breaking.

Skenario 3: Memaksa perbaikan termasuk breaking changes

Jika Anda yakin bahwa breaking changes bisa ditangani dan ingin memaksa npm untuk meng-upgrade paket meskipun melanggar constraint semver:

npm audit fix --force

Output:

npm WARN using --force I sure hope you know what you are doing.
fixed 3 of 3 vulnerabilities in 124 scanned packages

Peringatan: Gunakan flag --force dengan sangat hati-hati. Perintah ini bisa meng-upgrade paket ke major version baru yang mengubah API secara drastis dan berpotensi merusak kode Anda. Selalu uji aplikasi secara menyeluruh setelah menggunakan flag ini.

Skenario 4: Menghasilkan laporan dalam format JSON

Untuk keperluan integrasi CI/CD atau analisis programatis, Anda bisa menghasilkan laporan audit dalam format JSON:

npm audit --json

Output (disederhanakan):

{
  "metadata": {
    "vulnerabilities": {
      "low": 1,
      "moderate": 1,
      "high": 1,
      "critical": 0
    },
    "dependencies": 124
  },
  "advisories": {
    "1001": {
      "severity": "high",
      "package_name": "lodash",
      "vulnerable_versions": "<4.17.21",
      "patched_versions": ">=4.17.21",
      "title": "Prototype Pollution"
    }
  }
}

Format JSON ini sangat berguna ketika Anda ingin mem-parsing hasil audit dalam script bash, GitHub Action, atau GitLab CI pipeline untuk mengambil keputusan otomatis seperti gagalkan build jika ada kerentanan critical.

Skenario 5: Memeriksa hanya dependensi produksi

Di lingkungan produksi, dependensi dev (devDependencies) tidak ikut terinstal. Untuk memastikan audit hanya memeriksa paket yang relevan untuk produksi:

npm audit --production

Output:

found 1 vulnerability (1 high)
  run `npm audit` for details

Flag --production membuat npm mengabaikan devDependencies, sehingga Anda bisa fokus pada kerentanan yang benar-benar akan berdampak di lingkungan live.


Hal yang Sering Salah

Masalah Umum: npm audit fix tidak memperbaiki apa pun

Seringkali Anda menjalankan npm audit fix dan mendapat pesan "0 vulnerabilities fixed" padahal laporan audit masih menunjukkan ada kerentanan. Ini terjadi ketika versi yang diperbaiki berada di luar range semver yang diizinkan oleh package.json. Misalnya, package.json Anda menentukan "some-package": "^1.2.0" sementara fix hanya tersedia di versi 2.0.0. Dalam situasi ini, Anda perlu secara manual mengubah entry di package.json menjadi "some-package": "^2.0.0", lalu menjalankan npm install dan menguji apakah aplikasi masih berfungsi.

Masalah Umum: Kerentanan di dependensi transitif yang tidak bisa diperbaiki langsung

Ini adalah skenario yang lebih rumit. Misalnya, paket Anda my-app bergantung pada framework-x yang bergantung pada old-lib versi 1.0.0 yang rentan. Anda tidak bisa mengubah old-lib secara langsung karena tidak ada di package.json Anda. Solusi pertama adalah memeriksa apakah framework-x telah merilis versi baru yang meng-upgrade old-lib ke versi aman. Jika ya, upgrade framework-x. Jika belum, Anda bisa menggunakan npm overrides (tersedia di npm v8.3+) untuk memaksa resolusi versi tertentu:

{
  "overrides": {
    "old-lib": "1.1.0"
  }
}

Setelah menambahkan override, jalankan npm install dan verifikasi dengan npm audit. Pendekatan ini memang bukan solusi ideal karena bisa menyebabkan inkonsistensi, tetapi merupakan jalan keluar yang valid saat maintainer paket upstream belum merilis fix.

Masalah Umum: Lockfile hilang atau tidak sinkron

Tanpa package-lock.json, npm audit tidak bisa menentukan versi eksakt dependensi transitif dan akan menampilkan peringatan atau hasil yang tidak akurat. Pastikan lockfile selalu di-commit ke repository dan tidak masuk .gitignore. Jika lockfile rusak atau tidak sinkron, jalankan:

rm -rf node_modules package-lock.json
npm install
npm audit

Ini akan membangun kembali lockfile dari awal dan menghasilkan audit yang akurat.

Best Practice: Integrasikan audit ke CI/CD pipeline

Jangan hanya menjalankan audit secara manual dan sporadis. Integrasikan ke dalam pipeline CI Anda agar setiap pull request atau deployment secara otomatis diperik