Security • Sains • Technology • Informasi

Mengenal Serangan Supply Chain pada Paket npm dan PyPI

Iklan
ITU Workshop on Zero Trust and Software Supply Chain Security

Foto: Bulexat — CC BY-SA 4.0

Ringkasan Cepat

  • Serangan supply chain menyusup lewat dependensi tepercaya, bukan selalu lewat celah aplikasi.
  • Lockfile dan hash integritas membantu mencegah perubahan versi diam-diam, tetapi tetap perlu audit dan verifikasi.
  • Kenali tanda paket berbahaya, batasi izin instalasi, dan amankan akun maintainer serta pipeline CI/CD.

Serangan supply chain pada npm dan PyPI terjadi ketika pihak tak bertanggung jawab menyisipkan kode berbahaya ke paket atau dependensi yang kita pasang. Karena pengembang umumnya memercayai registry dan versi yang sudah lama dipakai, serangan ini bisa masuk tanpa terlihat langsung. Artikel ini membahas tanda paket berbahaya, peran lockfile, dan cara verifikasi integritas dari sisi pertahanan.

Apa Itu Serangan Supply Chain di npm dan PyPI

Serangan supply chain adalah upaya menyusupkan kode berbahaya melalui bagian dari rantai pasok perangkat lunak, bukan melalui celah aplikasi yang kita tulis sendiri. Pada ekosistem npm dan PyPI, rantai itu mencakup paket, maintainer, registry, lockfile, build pipeline, hingga mesin pengembang dan server CI/CD. Ketika satu dependensi dikompromikan, ribuan proyek bisa ikut menerima kode jahat pada instalasi berikutnya.

Pola yang umum bukan selalu peretasan canggih. Pelaku bisa memakai nama paket yang mirip (typosquatting), memanfaatkan dependency confusion, mengambil alih akun maintainer, atau menyisipkan versi jahat setelah paket dipercaya. npm dan PyPI juga memungkinkan paket menjalankan skrip saat instalasi, sehingga proses npm install atau pip install perlu diperlakukan sebagai aktivitas berisiko.

Prinsip pertahanannya sederhana: kurangi kejutan, verifikasi apa yang masuk, dan batasi izin saat instalasi. Sama seperti Panduan Mengamankan Akun Domain dan DNS: 2FA & Kunci Transfer, akun registry dan maintainer juga perlu 2FA, token terbatas, dan audit akses.

Tanda Paket npm atau PyPI yang Perlu Diwaspadai

Tidak ada satu tanda yang otomatis membuktikan sebuah paket jahat. Namun, beberapa kombinasi sinyal berikut cukup untuk menghentikan instalasi dan melakukan pemeriksaan manual.

  • Nama dan metadata mencurigakan: ejaan mirip paket populer, repositori kosong, maintainer baru, atau deskripsi tidak sesuai fungsi paket.
  • Riwayat tidak wajar: versi melompat drastis, rilis mendadak setelah lama tidak aktif, atau perubahan maintainer tanpa pengumuman.
  • Skrip instalasi agresif: preinstall, postinstall, atau setup.py yang menjalankan shell, mengunduh file, atau memodifikasi sistem.
  • Kode sulit dibaca: penggunaan eval, exec, base64, atau minifikasi tanpa sumber yang jelas.
  • Akses ke rahasia: upaya membaca .npmrc, .pypirc, .env, kunci SSH, token cloud, atau metadata instance.
  • Dependensi tidak relevan: paket kecil yang tiba-tiba menarik banyak dependensi atau melakukan koneksi jaringan tak perlu.

Gunakan tabel berikut sebagai checklist cepat saat meninjau dependensi baru atau perubahan lockfile.

TandaPola yang TerlihatTindakan Aman
Nama miripPola salah ketik dari paket populerPeriksa ejaan, sumber resmi, dan metadata maintainer.
Skrip instalasi agresifMenjalankan shell atau mengunduh file saat instalasiTinjau skrip; gunakan --ignore-scripts bila memungkinkan.
Kode tidak terbacabase64, eval, exec, minify tanpa sumberBandingkan dengan repositori sumber; hindari jika tidak jelas.
Akses rahasiaMembaca file kredensial atau environment variableInstal di sandbox tanpa secret; batasi izin token.
Lockfile berubahVersi atau hash baru yang tidak dikenalReview diff lockfile; verifikasi hash di CI.

Jika sebuah paket memicu beberapa sinyal di atas, jangan langsung mempercayai popularitasnya. Paket populer pun bisa dikompromikan melalui akun maintainer atau dependensi transitifnya.

Lockfile: Fungsi, Batas, dan Cara Membacanya

Lockfile mencatat versi tepat dan biasanya hash integritas dari setiap dependensi. Di npm ada package-lock.json, di pnpm ada pnpm-lock.yaml, di Yarn ada yarn.lock, sedangkan di Python ada poetry.lock, Pipfile.lock, atau requirements.txt dengan hash. Fungsinya mencegah resolusi versi yang berubah-ubah, sehingga build di mesin lokal, CI, dan produksi memakai bahan yang sama.

Namun, lockfile bukan jaminan keamanan. Jika paket jahat sudah masuk sebelum lockfile dibuat, lockfile akan setia mengunci paket jahat itu. Lockfile juga bisa diubah lewat pull request, jadi diff-nya wajib diperiksa. Perhatikan perubahan versi, sumber registry, URL unduhan, dan hash yang tiba-tiba berbeda.

Di pipeline, gunakan perintah yang mematuhi lockfile secara ketat. Contohnya npm ci, pnpm install --frozen-lockfile, yarn install --immutable, atau pip install --require-hashes. Jalankan proses ini di runner yang terisolasi dan tidak memiliki kredensial produksi. Untuk proyek yang berjalan di server, prinsip hardening di Panduan Mengamankan VPS Ubuntu untuk Proyek Pribadi & UMKM bisa diterapkan pada mesin build: pembaruan rutin, akses minimum, dan pemantauan proses keluar.

Yang perlu diperiksa pada diff lockfile

  • Apakah ada dependensi baru yang tidak dijelaskan di deskripsi pull request?
  • Apakah hash integritas berubah tanpa perubahan versi?
  • Apakah sumber paket berpindah dari registry resmi ke URL atau git langsung?
  • Apakah dependensi transitif bertambah banyak secara tidak wajar?

Verifikasi Integritas dan Pertahanan Berlapis

Verifikasi integritas berarti memastikan paket yang diunduh sesuai dengan yang diharapkan, bukan versi lain yang disisipkan di tengah jalan. Hash di lockfile adalah lapisan pertama. Lapisan berikutnya adalah provenance atau attestation yang menghubungkan paket dengan repositori dan proses build tertentu, bila tersedia. Untuk Python, hash pada requirements dan trusted publishing membantu mengurangi risiko akun maintainer. Untuk npm, provenance dan audit tanda tangan dapat menjadi sinyal tambahan.

Pertahanan tidak berhenti di verifikasi. Terapkan kebiasaan berikut secara konsisten:

  1. Aktifkan 2FA dan token granular. Cabut token lama, batasi scope, dan audit anggota organisasi secara berkala.
  2. Kunci dependensi dan verifikasi hash. Gunakan lockfile, hash, serta perintah instalasi ketat di CI.
  3. Isolasi instalasi. Jalankan npm install, pip install, atau build di container tanpa akses ke kredensial produksi.
  4. Pantau perubahan. Review diff lockfile, gunakan audit dependensi, dan periksa paket baru sebelum masuk produksi.
  5. Batasi dampak. Gunakan least privilege untuk CI, pisahkan lingkungan, dan pantau koneksi jaringan yang tidak biasa.
  6. Catat bahan bangunan. Simpan SBOM atau daftar dependensi agar respons insiden lebih cepat.

Jika mencurigai paket berbahaya, hentikan pipeline, jangan jalankan paket di mesin bernilai tinggi, dan anggap kredensial yang pernah tersedia di lingkungan tersebut sudah terpapar. Ganti token, periksa log akses, lalu laporkan paket ke registry terkait. Edukasi tim tentang risiko dependensi sama pentingnya dengan menambal celah CVE, karena supply chain sering masuk lewat pintu yang tampak resmi.

Pertanyaan yang Sering Diajukan (FAQ)

Apakah lockfile menjamin dependensi bebas malware?
Tidak. Lockfile mengunci versi dan hash, tetapi jika paket jahat sudah masuk sebelum lockfile dibuat, lockfile akan mengunci paket tersebut. Lockfile lebih berfungsi mencegah perubahan versi diam-diam dan memudahkan audit.
Bagaimana cara memverifikasi integritas paket npm dan PyPI?
Gunakan lockfile dengan hash integritas, lalu instal memakai perintah ketat seperti npm ci, pnpm --frozen-lockfile, atau pip --require-hashes. Bila tersedia, manfaatkan provenance, attestation, dan verifikasi tanda tangan dari sumber resmi.
Apakah semua postinstall script berbahaya?
Tidak. Banyak paket sah memakai postinstall untuk kompilasi native atau menyiapkan berkas. Namun script itu berjalan dengan izin pengguna saat instalasi, jadi tetap perlu ditinjau, terutama jika mengunduh file, menjalankan shell, atau membaca kredensial.
Apa langkah pertama jika menemukan paket mencurigakan?
Hentikan instalasi atau pipeline, jangan jalankan paket di mesin produksi, catat nama dan versinya, lalu ganti kredensial yang mungkin terpapar. Setelah itu audit sistem yang sempat menjalankan paket dan laporkan ke registry atau maintainer.
Apakah dependensi dev bisa menjadi vektor serangan?
Bisa. Dependensi dev sering dijalankan di mesin pengembang dan CI, sehingga tetap memiliki akses ke file, token, dan jaringan. Perlakukan dependensi dev dengan kontrol akses dan isolasi yang memadai.
Bagaimana melindungi akun maintainer npm dan PyPI?
Aktifkan 2FA, gunakan token granular dengan masa berlaku pendek, tinjau anggota organisasi, dan cabut token yang tidak dipakai. Jangan simpan token registry di lingkungan yang tidak perlu.
English Version — Understanding Supply Chain Attacks on npm and PyPI Packages

Quick Summary

  • Supply chain attacks infiltrate through trusted dependencies, not always through application vulnerabilities.
  • Lockfiles and integrity hashes help prevent silent version changes, but audits and verification are still necessary.
  • Recognize signs of malicious packages, limit installation permissions, and secure maintainer accounts and CI/CD pipelines.

Supply chain attacks on npm and PyPI occur when an unauthorized party inserts malicious code into a package or dependency that we install. Because developers generally trust the registry and versions that have been used for a long time, these attacks can enter without being immediately visible. This article discusses signs of malicious packages, the role of lockfiles, and how to verify integrity from a defensive standpoint.

What Is a Supply Chain Attack in npm and PyPI

A supply chain attack is an attempt to infiltrate malicious code through part of the software supply chain, rather than through a vulnerability in the application we wrote ourselves. In the npm and PyPI ecosystems, that chain includes packages, maintainers, registries, lockfiles, build pipelines, and developer machines and CI/CD servers. When one dependency is compromised, thousands of projects can also receive malicious code on their next installation.

The common pattern is not always sophisticated hacking. Attackers can use similar package names (typosquatting), exploit dependency confusion, take over maintainer accounts, or insert a malicious version after a package has gained trust. npm and PyPI also allow packages to run scripts during installation, so the npm install or pip install process should be treated as a risky activity.

The defense principle is simple: reduce surprises, verify what comes in, and limit permissions during installation. Just like Guide to Securing Domain and DNS Accounts: 2FA & Transfer Lock, registry and maintainer accounts also need 2FA, limited tokens, and access audits.

Signs of npm or PyPI Packages to Watch For

No single sign automatically proves that a package is malicious. However, the following combinations of signals are enough to stop installation and perform a manual inspection.

  • Suspicious name and metadata: spelling similar to a popular package, empty repository, new maintainer, or a description that does not match the package's function.
  • Unusual history: drastic version jumps, a sudden release after a long period of inactivity, or a maintainer change without an announcement.
  • Aggressive installation scripts: preinstall, postinstall, or setup.py that runs a shell, downloads files, or modifies the system.
  • Hard-to-read code: use of eval, exec, base64, or minification without a clear source.
  • Access to secrets: attempts to read .npmrc, .pypirc, .env, SSH keys, cloud tokens, or instance metadata.
  • Irrelevant dependencies: a small package that suddenly pulls in many dependencies or makes unnecessary network connections.

Use the following table as a quick checklist when reviewing new dependencies or lockfile changes.

SignVisible PatternSafe Action
Similar nameMisspelled pattern of a popular packageCheck spelling, official source, and maintainer metadata.
Aggressive installation scriptsRuns a shell or downloads files during installationReview the script; use --ignore-scripts when possible.
Unreadable codebase64, eval, exec, minify without sourceCompare with the source repository; avoid it if unclear.
Secret accessReads credential files or environment variablesInstall in a sandbox without secrets; limit token permissions.
Lockfile changedUnknown new version or hashReview the lockfile diff; verify the hash in CI.

If a package triggers several of the signals above, do not immediately trust its popularity. Even popular packages can be compromised through a maintainer account or their transitive dependencies.

Lockfile: Function, Limits, and How to Read It

A lockfile records the exact version and usually the integrity hash of each dependency. In npm there is package-lock.json, in pnpm there is pnpm-lock.yaml, in Yarn there is yarn.lock, while in Python there are poetry.lock, Pipfile.lock, or requirements.txt with hashes. Its function is to prevent variable version resolution, so builds on local machines, CI, and production use the same ingredients.

However, a lockfile is not a security guarantee. If a malicious package entered before the lockfile was created, the lockfile will faithfully lock in that malicious package. A lockfile can also be changed through a pull request, so its diff must be checked. Pay attention to version changes, registry sources, download URLs, and hashes that suddenly differ.

In the pipeline, use commands that strictly adhere to the lockfile. For example, npm ci, pnpm install --frozen-lockfile, yarn install --immutable, or pip install --require-hashes. Run these processes on isolated runners that do not have production credentials. For projects running on a server, the hardening principles in Guide to Securing an Ubuntu VPS for Personal Projects & SMEs can be applied to build machines: regular updates, minimum access, and monitoring outbound processes.

What to Check in a Lockfile Diff

  • Are there new dependencies that are not explained in the pull request description?
  • Has the integrity hash changed without a version change?
  • Has the package source moved from the official registry to a URL or direct git?
  • Have transitive dependencies increased unreasonably?

Integrity Verification and Layered Defense

Integrity verification means ensuring that the downloaded package matches what is expected, not another version inserted along the way. The hash in the lockfile is the first layer. The next layer is provenance or attestation that links the package to a specific repository and build process, when available. For Python, hashes in requirements and trusted publishing help reduce maintainer account risk. For npm, provenance and signature auditing can be additional signals.

Defense does not stop at verification. Apply the following habits consistently:

  1. Enable 2FA and granular tokens. Revoke old tokens, limit scopes, and audit organization members regularly.
  2. Lock dependencies and verify hashes. Use lockfiles, hashes, and strict installation commands in CI.
  3. Isolate installations. Run npm install, pip install, or builds in containers without access to production credentials.
  4. Monitor changes. Review lockfile diffs, use dependency audits, and inspect new packages before they reach production.
  5. Limit impact. Use least privilege for CI, separate environments, and monitor unusual network connections.
  6. Record build materials. Keep an SBOM or dependency list so incident response is faster.

If you suspect a malicious package, stop the pipeline, do not run the package on high-value machines, and assume that credentials that were ever available in that environment have been exposed. Replace tokens, check access logs, and report the package to the relevant registry. Educating the team about dependency risks is as important as patching CVE vulnerabilities, because the supply chain often enters through doors that appear official.

FAQ (English)

Does a lockfile guarantee that dependencies are free of malware?
No. A lockfile locks versions and hashes, but if a malicious package entered before the lockfile was created, the lockfile will lock in that package. A lockfile is more useful for preventing silent version changes and making audits easier.
How can I verify the integrity of npm and PyPI packages?
Use a lockfile with integrity hashes, then install using strict commands such as npm ci, pnpm --frozen-lockfile, or pip --require-hashes. When available, use provenance, attestation, and signature verification from official sources.
Are all postinstall scripts malicious?
No. Many legitimate packages use postinstall for native compilation or setting up files. However, that script runs with the user's permissions during installation, so it still needs review, especially if it downloads files, runs a shell, or reads credentials.
What is the first step if I find a suspicious package?
Stop the installation or pipeline, do not run the package on production machines, note its name and version, and replace any credentials that may have been exposed. After that, audit systems that ran the package and report it to the registry or maintainer.
Can dev dependencies be an attack vector?
Yes. Dev dependencies are often run on developer machines and CI, so they still have access to files, tokens, and the network. Treat dev dependencies with adequate access controls and isolation.
How do I protect npm and PyPI maintainer accounts?
Enable 2FA, use granular tokens with short expiration, review organization members, and revoke unused tokens. Do not store registry tokens in unnecessary environments.
Iklan

Komentar