Bagian terbesar aplikasi web modern bukan kode yang ditulis timnya sendiri, melainkan kumpulan package pihak ketiga yang dipasang melalui pengelola paket. Kondisi itu menambah kecepatan pengembangan sekaligus menambah permukaan risiko, karena kelemahan pada satu library ikut menjadi masalah aplikasi yang menggunakannya. Pada OWASP Top 10:2025, risiko ini menempati kategori A03 Software Supply Chain Failures, kategori baru yang meluas dari A06:2021 Vulnerable and Outdated Components dan menjadi perhatian utama pada survei komunitas karena dipilih separuh responden. Topik ini membahas cara menilai daftar dependensi, mengenali komponen rentan melalui laporan ala SBOM, dan mengunci versi melalui pinning.
Komponen pihak ketiga sebagai bagian aplikasi#
Pengelola paket memasang dependensi yang dideklarasikan, dan setiap dependensi menarik dependensinya sendiri sehingga satu baris deklarasi dapat berujung pada puluhan paket yang terpasang. Rantai itulah yang disebut supply chain perangkat lunak, yaitu seluruh pihak dan artefak yang dilalui kode sampai berjalan di production. Kelemahan dapat muncul di setiap mata rantai, misalnya library yang tidak diperbarui, versi yang berubah tanpa diketahui, atau paket yang diambil dari sumber yang keliru. Dari seluruh bentuk itu, komponen yang rentan adalah yang paling sering ditemukan dan paling mudah diperiksa.
Penilaian dimulai dari pertanyaan sederhana, yaitu paket apa saja yang benar-benar berjalan dan berapa versinya. Jawabannya tidak selalu sama dengan isi berkas deklarasi karena versi yang mengapung membuat paket yang terpasang berganti dari waktu ke waktu. Setelah daftar yang akurat ada, daftar itu dicocokkan dengan informasi kerentanan yang terdokumentasi untuk menemukan paket yang perlu diperbarui.
Komponen rentan dan SBOM#
Software Bill of Materials (SBOM) adalah daftar bahan perangkat lunak, yaitu inventaris paket beserta versinya yang menyusun sebuah aplikasi. SBOM menjadi dasar penilaian karena laporan kerentanan (advisory) menyebut nama paket dan rentang versi yang terdampak, sehingga pencocokannya dapat dilakukan secara mekanis. Skrip berikut membaca daftar dependensi berformat paket==versi, menilai status pinning, lalu mencocokkannya dengan umpan kerentanan kecil yang isinya fiktif. Simpan dua berkas berikut dalam satu folder, lalu jalankan dengan perintah python3 audit-dependensi.py.
# daftar dependensi aplikasi catatan
klien-http-mini==1.2.0
parsir-xml==2.3.1
toko-session==0.9.4
util-waktu
gaya-tampilan==3.1.2"""Laporan dependensi ala SBOM dengan umpan kerentanan lokal.
Membaca daftar dependensi berformat `paket==versi` (satu paket satu
baris), menilai apakah versinya dikunci (pinning), lalu mencocokkan
pasangan paket-versi dengan umpan kerentanan kecil di bawah. Seluruh
nama paket dan nomor kerentanan bersifat fiktif untuk latihan.
"""
import sys
# Umpan kerentanan lokal: data fiktif, dibuat khusus untuk latihan ini.
UMBAN_KERENTANAN = {
"parsir-xml": {
"rentang": "<2.5.0",
"id": "CONTOH-2024-001",
"ringkas": "entitas eksternal pada pengurai XML memungkinkan pembacaan berkas lokal",
"perbaikan": "2.5.0",
},
"toko-session": {
"rentang": "<1.0.0",
"id": "CONTOH-2024-002",
"ringkas": "pengenal session dapat ditebak dari waktu pembuatan",
"perbaikan": "1.0.0",
},
}
def baca_dependensi(berkas):
daftar = []
with open(berkas, encoding="utf-8") as sumber:
for baris in sumber:
baris = baris.strip()
if not baris or baris.startswith("#"):
continue
if "==" in baris:
nama, versi = baris.split("==", 1)
daftar.append((nama.strip(), versi.strip(), True))
else:
daftar.append((baris, None, False))
return daftar
def angka_versi(teks):
return tuple(int(bagian) for bagian in teks.split("."))
def versi_rentan(versi, rentang):
# rentang pada latihan ini hanya mendukung bentuk "<x.y.z"
if not rentang.startswith("<"):
return False
batas = rentang[1:].strip()
return angka_versi(versi) < angka_versi(batas)
def status_paket(nama, versi):
if nama not in UMBAN_KERENTANAN:
return "tidak terdaftar dalam umpan"
entri = UMBAN_KERENTANAN[nama]
if versi_rentan(versi, entri["rentang"]):
return f"RENTAN ({entri['id']})"
return "aman, versi sudah di luar rentang rentan"
def utama():
berkas = sys.argv[1] if len(sys.argv) > 1 else "dependensi.txt"
daftar = baca_dependensi(berkas)
print(f"== Laporan dependensi ala SBOM: {berkas} ==")
print(f"{'paket':<17} {'versi':<7} {'pinning':<8} status")
rentan = []
for nama, versi, terkunci in daftar:
if terkunci:
teks_pinning = "ya"
status = status_paket(nama, versi)
else:
teks_pinning = "tidak"
status = "tidak dapat dinilai, versi mengapung antar build"
if status.startswith("RENTAN"):
rentan.append((nama, versi))
print(f"{nama:<17} {versi or '-':<7} {teks_pinning:<8} {status}")
print(f"== {len(rentan)} paket rentan dari {len(daftar)} dependensi ==")
if rentan:
print("Rincian dan saran perbaikan:")
for nama, versi in rentan:
entri = UMBAN_KERENTANAN[nama]
print(f"- {nama} {versi}: {entri['ringkas']}")
print(f" perbaikan: kunci versi ke {entri['perbaikan']} atau lebih baru")
utama()== Laporan dependensi ala SBOM: dependensi.txt ==
paket versi pinning status
klien-http-mini 1.2.0 ya tidak terdaftar dalam umpan
parsir-xml 2.3.1 ya RENTAN (CONTOH-2024-001)
toko-session 0.9.4 ya RENTAN (CONTOH-2024-002)
util-waktu - tidak tidak dapat dinilai, versi mengapung antar build
gaya-tampilan 3.1.2 ya tidak terdaftar dalam umpan
== 2 paket rentan dari 5 dependensi ==
Rincian dan saran perbaikan:
- parsir-xml 2.3.1: entitas eksternal pada pengurai XML memungkinkan pembacaan berkas lokal
perbaikan: kunci versi ke 2.5.0 atau lebih baru
- toko-session 0.9.4: pengenal session dapat ditebak dari waktu pembuatan
perbaikan: kunci versi ke 1.0.0 atau lebih baruTabel keluaran memuat kolom paket, versi, status pinning, dan hasil pencocokan dengan umpan. Baris parsir-xml dan toko-session dinyatakan RENTAN karena versinya berada di bawah batas yang tercantum pada umpan, lengkap dengan penjelasan singkat dan saran versi perbaikan. Baris util-waktu menunjukkan masalah yang berbeda: tanpa versi yang tercantum, statusnya tidak dapat dinilai sama sekali, sehingga laporan keamanannya juga tidak dapat dipercaya.
Pinning versi dan pembaruan#
Pinning adalah mengunci versi dependensi pada nilai yang persis, biasanya dengan format paket==versi atau berkas lock milik pengelola paket. Manfaatnya ganda. Build menjadi deterministik karena eksekusi yang berbeda memasang kode yang sama, dan laporan keamanan menjadi dapat dipercaya karena SBOM mencerminkan versi yang benar-benar terpasang. Versi yang mengapung, seperti baris util-waktu pada contoh sebelumnya, membuat dua build dapat memuat kode berbeda tanpa ada perubahan apa pun pada repositori.
Pinning bukan berarti berhenti memperbarui. Pembaruan yang tertarget tetap dilakukan setiap ada advisory, yaitu pin lama diganti dengan pin baru, lalu seluruh pengujian dijalankan untuk memastikan tidak ada perilaku yang berubah. Berkas berikut adalah daftar dependensi yang sama setelah dua paket rentan diperbarui dan satu paket yang mengapung dikunci. Jalankan auditor atas daftar barunya.
# daftar dependensi aplikasi catatan setelah pembaruan
klien-http-mini==1.2.0
parsir-xml==2.5.0
toko-session==1.0.0
util-waktu==1.4.2
gaya-tampilan==3.1.2# menjalankan auditor atas daftar dependensi hasil pembaruan
python3 audit-dependensi.py dependensi-perbaikan.txt== Laporan dependensi ala SBOM: dependensi-perbaikan.txt ==
paket versi pinning status
klien-http-mini 1.2.0 ya tidak terdaftar dalam umpan
parsir-xml 2.5.0 ya aman, versi sudah di luar rentang rentan
toko-session 1.0.0 ya aman, versi sudah di luar rentang rentan
util-waktu 1.4.2 ya tidak terdaftar dalam umpan
gaya-tampilan 3.1.2 ya tidak terdaftar dalam umpan
== 0 paket rentan dari 5 dependensi ==Seluruh baris kini terkunci pada versi tertentu dan tidak ada satu pun yang berada di dalam rentang rentan. Untuk pemeliharaan berkelanjutan, pembaruan dependensi dapat diotomatisasi sehingga setiap pembaruan datang sebagai pull request (permintaan penggabungan perubahan) beserta hasil pengujian. Otomatisasi tersebut dibahas pada modul Rekayasa Pertahanan.
Kesalahan umum#
Kesalahan berikut sering muncul saat risiko dependensi ditangani.
- Menganggap isi berkas deklarasi sama dengan paket yang benar-benar terpasang. Versi mengapung dan dependensi transitif membuat keduanya berbeda, sehingga inventaris perlu dibaca dari berkas lock atau hasil instalasi.
- Memperbarui seluruh dependensi sekaligus tanpa pengujian. Bila pengujian gagal, penyebabnya sulit ditemukan di antara puluhan perubahan versi.
- Menghapus pin agar pesan konflik versi hilang. Konflik yang ditutup dengan cara ini justru memindahkan masalah ke build berikutnya yang isinya tidak terkendali.
- Menyalin SBOM ke dokumentasi tanpa tanggal. Daftar bahan yang tidak menyebut kapan daftar itu dibuat tidak dapat dipercaya saat insiden dianalisis.
Ringkasan#
- Aplikasi web tersusun dari package pihak ketiga, dan risikonya masuk kategori A03 Software Supply Chain Failures pada OWASP Top 10:2025.
- SBOM berisi paket dan versi yang benar-benar terpasang, sehingga pencocokan dengan advisory dapat dilakukan secara mekanis seperti pada auditor di atas.
- Pinning mengunci versi agar build deterministik dan laporan keamanan dapat dipercaya, sedangkan pembaruan tetap dilakukan secara tertarget per advisory.
Referensi#
- A03:2025 Software Supply Chain Failures — OWASP Top 10 — Kategori baru OWASP Top 10:2025 yang mencakup komponen rentan hingga kegagalan rantai pasok perangkat lunak.
- OWASP Top Ten Project — OWASP — Halaman proyek OWASP Top 10 beserta riwayat edisinya, termasuk A06:2021 yang menjadi cikal bakal A03:2025.