Skip to content

Cooldown 1 Hari Memblokir 70% Rilis npm yang Dibajak di 2026. Untuk Typosquat, 7 Hari Masih Meloloskan 45%

Terbit Terakhir diperbarui 8 menit baca

Poin penting

  • Untuk paket npm yang dibajak, median jendela dari publish sampai advisory adalah 4,9 jam, jadi cooldown 1 hari memblokir 70,4% dan cooldown 3 hari memblokir 81,3%.
  • Untuk paket npm yang jahat sejak lahir, median jendelanya 100,5 jam, dan cooldown 7 hari pun hanya memblokir 55,0%.
  • Dari 11.556 paket npm dan PyPI berbahaya, median jendelanya 72,4 jam, tetapi p75 mencapai 28,9 hari dan p90 103,0 hari.
  • Dengan cooldown 3 hari, 22,7% perbaikan keamanan baru sampai ke Anda setelah disclosure, dan dengan cooldown 7 hari angkanya naik jadi 46,1%, kecuali update keamanan dikecualikan.
  • pnpm 11 menyalakan cooldown 1 hari secara default, npm menambahkan min-release-age di 11.10.0, dan pip menambahkan --uploaded-prior-to di 26.0.

Versi bahasa Inggris dengan metodologi lengkap: A 1-Day Cooldown Would Have Blocked 70% of 2026’s Hijacked npm Releases.

Pada 8 Oktober, seseorang mem-push tensorlake@0.5.144 ke npm dengan worm pencuri kredensial di hook preinstall. Socket menandainya 11 menit kemudian. Advisory OSV muncul 1,7 jam setelah publish, dan npm menggantinya dengan placeholder keamanan 3,1 jam setelah publish. Kalau installer Anda menolak rilis yang umurnya kurang dari sehari, versi itu tidak pernah sampai ke mesin Anda.

Saya mengambil semua advisory paket berbahaya OSV untuk npm dan PyPI dari 1 Januari sampai 24 Oktober 2026, lalu bertanya untuk tiap paket: apakah cooldown 1, 3, atau 7 hari akan menahannya?

Untuk rilis hasil pembajakan paket npm asli, cooldown 1 hari memblokir 70,4%. Untuk paket yang berbahaya sejak hari pertama, cooldown 7 hari masih meloloskan 45%.

Ringkasan untuk pembaca non-teknis

  • “Cooldown” membuat installer mengabaikan rilis yang lebih baru dari N hari. Banyak malware tertangkap sebelum sempat setua itu.
  • Kalau penyerang membajak paket asli yang tepercaya, versi jahatnya cepat ditandai: median 4,9 jam. Menunggu 1 hari akan memblokir 70,4% dari semuanya di 2026, menunggu 3 hari 81,3%.
  • Paket yang palsu sejak awal, misalnya nama mirip, bertahan jauh lebih lama. Menunggu 7 hari pun meloloskan 45% dari mereka. Melawannya butuh pengecekan nama, bukan menunggu.
  • Biayanya: dengan cooldown 3 hari, 22,7% perbaikan keamanan baru sampai ke Anda setelah kerentanannya publik, kecuali update keamanan dikecualikan. Renovate dan Dependabot melakukannya otomatis. pnpm, npm, dan uv memungkinkan pengecualian manual per paket.

Kenapa sekarang

  • ChainDrop, 4 Agustus. Microsoft menjelaskan varian Mini Shai-Hulud yang menyebar sendiri dan menyerang “lebih dari 400 paket npm”, termasuk ekosistem keyv, flat-cache, dan cache-manager. Worm ini mencuri token publish, menaikkan versi patch, lalu merilis ulang (Microsoft Security Blog). Di data saya, flat-cache@6.1.24 dapat advisory OSV 0,5 jam setelah publish, cache-manager@7.2.10 1,0 jam, keyv@6.0.0 1,7 jam.
  • Tensorlake, 8 Oktober. Keluarga worm yang sama. Versi jahat dipublikasikan pukul 01:12:07 UTC dan terdeteksi pukul 01:23:10 UTC (Socket, The Hacker News).
  • MALFEX, Oktober. Kebalikannya. Delapan paket npm berbahaya, 40.767 unduhan, dengan function-flag saja 37.419 unduhan dan pertama kali terbit pada Juli 2024 (The Hacker News). Versi 1.7.3 miliknya tayang 429 hari sebelum advisory OSV muncul. Cooldown tidak menolong di sini.

Tooling sudah menyusul. npm merilis min-release-age di 11.10.0, pip merilis --uploaded-prior-to di 26.0, dan pnpm 11 menyalakan cooldown 1 hari secara default. Dokumentasi pnpm membenarkannya begini: “In most cases, malicious releases are discovered and removed from the registry within an hour.” Saya ingin menguji kalimat itu.

Metode

Semuanya dijalankan pada 25 Oktober 2026 dari laptop Windows.

  1. Advisory. Saya mengunduh ekspor massal OSV untuk npm dan PyPI, menyimpan entri MAL-* yang terbit 2026-01-01 sampai 2026-10-24, dan membuang yang ditarik. Tersisa 12.820 advisory npm dan 1.545 PyPI.
  2. Waktu publish. Untuk npm saya membaca field time di tiap packument. npm menyimpan timestamp versi yang dihapus dan waktu placeholder 0.0.1-security menggantikan paket. Untuk PyPI saya memakai upload_time dari JSON API.
  3. Jendela waktu. Untuk tiap paket: published di OSV dikurangi waktu publish versi jahat pertama. Hanya versi pertama yang dihitung, karena cooldown tetap menginstal versi lama.
  4. Terblokir. Cooldown D hari memblokir paket jika jendelanya lebih pendek dari D.
  5. Dibajak vs jahat sejak lahir. “Dibajak” berarti paket npm asli dengan rilis bersih sebelum versi jahat dan masih hidup sampai sekarang. Sisanya (typosquat, dependency confusion, spam) masuk “jahat sejak lahir”. Ini heuristik.
  6. Biaya. Saya mengambil 200 paket npm teratas (npm-high-impact) dan 200 paket PyPI teratas (daftar hugovk), memeriksa setiap rilis stabil dari 28 April sampai 25 Oktober, lalu mengukur seberapa sering cooldown menahan “latest”. Rilis juga saya cocokkan dengan versi fixed di OSV untuk menemukan perbaikan keamanan.

Timestamp OSV adalah batas atas deteksi: tensorlake ditandai Socket 91 menit sebelum OSV punya entri.

Hasil: apa yang diblokir cooldown

Histogram 11.556 paket berbahaya menurut waktu sampai advisory OSV

Dari 11.556 paket dengan timestamp yang bisa dipakai, median jendelanya 72,4 jam, hampir persis 3 hari. Lalu ekornya mengambil alih: p75 adalah 28,9 hari dan p90 103,0 hari.

Populasi (per paket)nMedian jendelaCooldown 1 hari3 hari7 hari14 hari
Paket npm dibajak1.3364,9 jam70,4%81,3%85,1%87,4%
Semua npm + PyPI11.55672,4 jam37,7%49,9%58,4%65,1%
npm jahat sejak lahir10.160100,5 jam33,5%45,8%55,0%62,3%
npm, jam takedown registry9.923130,9 jam33,1%43,8%52,4%58,9%

Grafik batang paket berbahaya yang diblokir cooldown 1, 3, 7, dan 14 hari

Kalimat di dokumentasi pnpm itu terlalu optimis. Hanya 13,1% paket yang mendapat advisory dalam satu jam sejak versi jahat pertama. Bahkan untuk pembajakan, kasus tercepat, angkanya 10,0% dalam satu jam dan 59,7% dalam enam jam.

Cooldown adalah pertahanan terhadap pembajakan. Worm dan rilis dari token curian menyerang paket populer, jadi scanner mengerubunginya, dan menunggu sehari terbayar. Typosquat menunggu salah ketik atau nama halusinasi asisten AI. Tidak ada yang mengawasi, jadi mereka hidup berminggu-minggu.

Penghapusan di registry tertinggal dari advisory di bagian ekor. Di mana npm memasang placeholder, itu datang sebelum advisory OSV untuk 60,6% paket, tetapi yang lambat jauh lebih lambat, sehingga median jendela takedown 5,5 hari.

PyPI menghapus proyek berbahaya sepenuhnya, jadi hanya 60 paket PyPI yang timestamp-nya bisa dipakai. Saya tidak menarik kesimpulan PyPI dari situ.

Hasil: berapa biaya cooldown

Selama 180 hari, 239 dari 400 paket teratas memindahkan versi terbarunya minimal sekali. Untuk paket-paket itu, inilah seberapa sering cooldown menjauhkan Anda dari rilis terbaru:

CooldownTertahan (npm + PyPI, aktif)Rilis npm tak pernah terinstalRilis PyPI tak pernah terinstalPerbaikan keamanan tiba setelah disclosure (dari 141)
1 hari3,94% waktu17,8%24,4%21 (14,9%)
3 hari9,71%30,1%43,2%32 (22,7%)
7 hari18,53%44,4%57,5%65 (46,1%)
14 hari29,48%55,2%68,7%86 (61,0%)

Saat tertahan, Anda biasanya hanya tertinggal 1,1 sampai 1,7 versi untuk cooldown 1 sampai 7 hari.

Kolom keamanan adalah biaya sebenarnya. Saya menghitung perbaikan sebagai terlambat jika Anda masih di versi rentan setelah advisory-nya publik. Disclosure biasanya datang jauh setelah perbaikan: median selisihnya 12,8 hari di npm dan 7,9 hari di PyPI. Itu sebabnya cooldown 1 hari murah. Pada 7 hari, hampir separuh perbaikan baru tiba setelah advisory publik.

Grafik garis manfaat dan biaya cooldown 1 sampai 14 hari

Naik dari 3 ke 7 hari menambah 8,5 poin pemblokiran malware dan 23,4 poin perbaikan keamanan yang terlambat. Pada 14 hari, kedua kurva hampir bertemu.

Pengaturan untuk stack Anda

Setiap opsi di bawah sudah saya cek ke dokumentasi resmi pada 25 Oktober 2026.

pnpm (pnpm-workspace.yaml, dalam menit; default 1440 sejak v11):

minimumReleaseAge: 4320   # 3 days
minimumReleaseAgeExclude:
  - '@myorg/*'
  - nx@21.6.5

npm (11.10.0 ke atas, dalam hari; min-release-age-exclude butuh 11.17.0):

# .npmrc
min-release-age=3
npm install --min-release-age-exclude='@myorg/*'

uv (menerima durasi sederhana, durasi ISO 8601 seperti P3D, atau timestamp):

[tool.uv]
exclude-newer = "3 days"
exclude-newer-package = { cryptography = false }

pip (26.1 ke atas untuk durasi; index harus menampilkan waktu upload):

pip install --uploaded-prior-to P3D -r requirements.txt
# or: PIP_UPLOADED_PRIOR_TO=P3D

Renovate (security:minimumReleaseAgeNpm dan security:minimumReleaseAgePypi masing-masing menetapkan 3 hari):

{
  "extends": ["security:minimumReleaseAgeNpm", "security:minimumReleaseAgePypi"]
}

Dependabot (update versi sudah default cooldown 3 hari; ini membuatnya eksplisit):

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 3
      exclude: ["@myorg/*"]

Kapan cooldown merugikan

Bot sudah menangani masalah perbaikan keamanan. Dokumentasi Renovate menyebut “Security updates bypass any minimumReleaseAge checks”, dan dokumentasi Dependabot menyebut “The cooldown option is only available for version updates, not security updates.” Kalau PR upgrade Anda dibuka oleh bot, angka 22,7% saya sebagian besar tidak berlaku.

Cooldown di level installer tidak tahu mana perbaikan keamanan. Di npm, jika min-release-age memblokir versi yang sudah ditambal, npm audit fix membiarkan Anda di versi rentan, memberi peringatan, dan keluar dengan kode non-nol. Mode gagal yang benar, tetapi Anda butuh playbook:

  • CVE mendesak di satu paket: tambahkan ke daftar exclude (minimumReleaseAgeExclude, min-release-age-exclude, exclude-newer-package = { pkg = false }), instal, lalu hapus entrinya. pnpm 11.22 bisa memangkas entri basi dengan minimumReleaseAgeExcludePrune.
  • Paket milik sendiri: kecualikan scope organisasi Anda secara permanen.
  • Pin dengan versi persis, bukan nama, bila bisa. pnpm menerima nx@21.6.5 agar pengecualian tidak diam-diam mencakup rilis berikutnya.

Catatan batasan

  • published di OSV adalah saat entri masuk OSV, bukan saat seseorang pertama kali menyadari. Deteksi nyata sering lebih awal, jadi angka saya konservatif.
  • Label “dibajak” adalah heuristik.
  • Timestamp PyPI hanya bertahan untuk paket yang tidak dihapus, jadi 60 paket adalah sampel yang bias.
  • Model biaya mengasumsikan Anda selalu ingin versi stabil terbaru, dan 141 perbaikan adalah sampel kecil.
  • Cooldown tidak berguna melawan paket yang jahat sejak hari pertama dan sengaja Anda instal. function-flag milik MALFEX bertengger di npm selama 429 hari.

Pengaturan saya setelah semua ini: 3 hari untuk npm dan PyPI, pengecualian untuk scope sendiri, dan update keamanan lewat Renovate agar lolos antrean. Jika diputar ulang terhadap 2026, itu memblokir 81,3% pembajakan dengan harga 9,71% waktu tertahan.

Cooldown apa yang Anda pakai, dan pernahkah Anda butuh pintu darurat untuk CVE sungguhan?

Terkait: backdoor supply chain LiteLLM dan playbook ekstensi browser palsu, kini hadir sebagai agent skills.

Pertanyaan yang sering diajukan

Bagaimana cara mengatur cooldown dependensi di npm, pnpm, uv, dan pip?
Di pnpm, atur minimumReleaseAge di pnpm-workspace.yaml (dalam menit, 4320 untuk 3 hari). Di npm 11.10.0 ke atas, set min-release-age=3 di .npmrc. Di uv, set exclude-newer = '3 days' di bawah [tool.uv]. Di pip 26.1 ke atas, pakai --uploaded-prior-to P3D atau PIP_UPLOADED_PRIOR_TO=P3D.
Berapa banyak malware yang diblokir cooldown?
Untuk paket npm yang dibajak, cooldown 1 hari memblokir 70,4% dan cooldown 3 hari 81,3%. Untuk paket npm yang jahat sejak lahir seperti typosquat, cooldown 7 hari hanya memblokir 55,0%, jadi 45% tetap lolos.
Apa biaya dari cooldown?
Dengan cooldown 3 hari, 22,7% perbaikan keamanan sampai ke Anda setelah kerentanannya publik, dan 46,1% pada 7 hari. Renovate dan Dependabot mengecualikan update keamanan, sedangkan pnpm, npm, dan uv memungkinkan Anda mengecualikan paket secara manual.
Bagaimana cara menginstal perbaikan keamanan mendesak saat cooldown aktif?
Tambahkan paket ke daftar exclude (minimumReleaseAgeExclude, min-release-age-exclude, atau exclude-newer-package = { pkg = false }), instal, lalu hapus entrinya. Pin dengan versi persis, misalnya nx@21.6.5, supaya pengecualian tidak mencakup rilis berikutnya.
Bagikan Bagikan ke X Bagikan ke LinkedIn

About the author

Portrait of Kiell Tampubolon

Security Engineer & Technical Writer

Security engineer and technical writer based in Batam, Indonesia. I review and harden MCP servers and AI agents, build security automation, and write up what holds and what fails. I also train on DNS security as a PANDI .id Academy trainer.

All writing | RSS | Markdown