Ringkasan inti
Untuk menghadapi serangan rantai pasok yang menargetkan ekosistem paket Python, dibutuhkan strategi pertahanan berlapis yang tidak bergantung pada satu kontrol saja. Artikel ini merekomendasikan pemblokiran kerentanan statis dengan memanfaatkan aturan S (Bandit) di Ruff, penguncian dependensi berbasis hash kriptografis menggunakan uv, serta penggunaan pip-audit dan pembuatan SBOM (CycloneDX) di lingkungan CI. Saat mendistribusikan paket, artikel ini menyarankan penerapan Trusted Publishing berbasis OIDC alih-alih token API jangka panjang, serta menyajikan pipeline praktis yang secara sengaja menunda adopsi paket baru (Delayed Ingestion) agar tersedia waktu bagi komunitas untuk memverifikasi paket berbahaya.
Analisis mendalam
- Vektor serangan rantai pasok dan dependensi transitif (Transitive Dependency): Saat ini PyPI memiliki lebih dari 740 ribu paket, dan insiden keamanan berskala besar terus terjadi, seperti pembajakan domain ctx, injeksi skrip CI pada Ultralytics (YOLO), dan pencurian token GhostAction. Bahkan ketika hanya memasang satu paket saja, misalnya Flask, banyak dependensi transitif ikut terpasang, misalnya MarkupSafe. Akibatnya, bahkan paket yang tidak dinyatakan secara eksplisit oleh pengembang pun menjadi bagian dari attack surface yang besar.
- Pemblokiran dini kerentanan dalam kode internal: Sebelum membahas paket eksternal, cacat pada kode internal harus dicegah terlebih dahulu. Secret yang di-hardcode, algoritme hash yang lemah (MD5, SHA1), request jaringan tanpa timeout yang dapat memicu DoS, serta serialisasi tidak aman seperti
picklemudah terlewat saat code review. Untuk mencegahnya, integrasi aturan keamanan Bandit di Ruff ke pipeline CI/CD dan IDE menjadi hal yang esensial agar deteksi dan pemblokiran berjalan otomatis. - Penguncian dependensi dan delayed ingestion: Saat memasang dependensi, tidak cukup hanya menyebutkan versi; hash kriptografis paket juga perlu dikunci untuk mencegah manipulasi di lingkungan runtime. Selain itu, untuk menurunkan risiko sebelum paket berbahaya yang baru dirilis diblokir, strategi yang efektif adalah memakai flag
--exclude-newerdariuv, atau menempatkan "antrian ingestion 7 hari" pada mirror internal agar hanya paket yang telah melewati verifikasi awal komunitas yang masuk ke jaringan internal. - Distribusi paket yang aman: Maintainer open source dan penerbit paket sebaiknya menghentikan penggunaan token API statis yang selalu berisiko dicuri, lalu beralih ke Trusted Publishing berbasis OIDC (OpenID Connect) yang memanfaatkan Sigstore. Dengan cara ini, attestation yang secara kriptografis membuktikan keterhubungan dengan source repository dapat dibuat secara otomatis.
Kode dan data utama
1. Memeriksa dependensi transitif (Transitive Dependencies)
# Periksa pohon dependensi tak terlihat yang ikut terbawa saat memasang satu paket saja (Flask)
uv pip install flask
uv pip tree
# Output:
flask v3.1.0
├── blinker v1.9.0
├── click v8.1.8
├── itsdangerous v2.2.0
├── jinja2 v3.1.5
│ └── markupsafe v3.0.2
└── werkzeug v3.1.3
└── markupsafe v3.0.2
2. Menerapkan ruleset keamanan (Bandit) dengan Ruff
# Contoh konfigurasi `pyproject.toml`
[tool.ruff]
line-length = 120
# Aktifkan S (aturan keamanan Bandit) bersama E (Error) dan F (Pyflakes)
lint.select = ["E", "F", "S"]
# Contoh pola kerentanan yang umum dan otomatis terdeteksi oleh ruleset Ruff 'S'
# FLAGGED: S301 - `pickle.loads()` berisiko mengeksekusi kode arbitrer (`json.loads()` direkomendasikan)
import pickle
data = pickle.loads(untrusted_input)
# FLAGGED: S608 - Kerentanan SQL injection melalui string formatting
cursor.execute(f"SELECT * FROM users WHERE name = '{user_input}'")
# FLAGGED: S113 - Request eksternal tanpa timeout (terpapar penantian tanpa batas dan serangan DoS)
import requests
response = requests.get("[https://api.example.com/data](https://api.example.com/data)")
3. Mengontrol paket baru melalui delayed ingestion
# Kompilasi dependensi hanya dengan paket yang dirilis sebelum tanggal tertentu (mis. 7 hari lalu) untuk menghindari malware/error awal
uv pip compile --exclude-newer 2026-03-02 requirements.in -o requirements.txt
4. Pipeline kontrol ingestion di dalam organisasi
| Tahap proses | Komponen sistem | Tujuan dan penjelasan keamanan |
|---|---|---|
| Masuk | PyPI ➜ Ingestion Queue | Paket baru yang terdaftar di PyPI tidak langsung didistribusikan ke sistem internal, melainkan lebih dulu dimasukkan ke antrean |
| Tunggu | Wait (mis. 7 hari) | Mengamankan waktu yang cukup bagi komunitas dan peneliti keamanan untuk menganalisis apakah paket berbahaya atau memiliki kerentanan |
| Verifikasi | Security Scan ➜ Approved | Setelah masa tunggu selesai, paket hanya disetujui jika lolos pemindaian kerentanan yang diketahui (CVE) dan malware |
| Distribusi | Internal Mirror ➜ Developers | Hanya paket yang telah diverifikasi yang di-cache pada mirror internal agar dapat digunakan dengan aman oleh tim pengembang |
Belum ada komentar.