SBOM dalam Praktik: Otomatiskan Cek Lisensi Sebelum Serah Terima

SBOM dalam Praktik: Otomatiskan Cek Lisensi Sebelum Serah Terima
Satu service Node ukuran menengah menarik 800 sampai 1.500 package begitu dependency transitif ikut dihitung. Setiap package punya lisensi. Sebagian kecil dari lisensi itu membawa kewajiban yang harus dipenuhi saat delivery.
Membaca semuanya satu per satu bukan rencana yang masuk akal. Jawaban yang dipakai di lapangan: SBOM plus policy check di CI.
Bayangkan SBOM seperti daftar komposisi di kemasan makanan. Isinya daftar lengkap semua bahan yang masuk ke build Anda, dibuat otomatis. Policy check-nya menggagalkan pipeline saat ada bahan yang tidak boleh ikut dikirim ke klien.
Lisensi mana saja yang benar-benar menggigit sudah saya bahas terpisah di artikel lisensi open-source. Artikel ini soal cara tahu isi build Anda sebenarnya apa.
Manifest itu klaim, bukan fakta
Ini kegagalan yang menjebak tim yang merasa npm ls sudah cukup. Field
lisensi di manifest package itu metadata yang diisi sendiri oleh
pembuatnya. Tidak ada yang memverifikasi.
Ada package yang menulis MIT di package.json, padahal di dalam lib/
ada file source hasil salin dengan header GPL. Ada package yang tidak
menulis lisensi sama sekali. Ada juga field lisensi berisi
SEE LICENSE IN LICENSE.txt yang menunjuk ke file yang tidak pernah ikut
terbit di tarball.
SPDX, standar SBOM yang lebih tua, memisahkan dua hal ini secara eksplisit.
Setiap entri package punya field licenseDeclared, yaitu klaim proyeknya
sendiri. Ada juga field licenseConcluded, yaitu hasil analisis Anda.
Tool murah cuma mengisi field pertama. Scanner level file seperti ScanCode Toolkit membaca header source aslinya untuk mengisi field kedua.
Untuk kebanyakan pekerjaan delivery, scan lisensi yang dideklarasikan sudah menangkap masalah yang jelas. Contohnya package AGPL yang masuk sprint lalu, atau helper model berlisensi non-komersial. Scan level file baru perlu saat tim legal klien minta bukti, bukan sekadar pernyataan. Perlu juga saat satu codebase mau berpindah tangan dan jawabannya berdampak ke harga.
Dua format, dan pilihannya tidak terlalu penting
SPDX dan CycloneDX sama-sama bisa dipakai. SPDX lahir dari Linux Foundation dan sudah jadi standar ISO/IEC 5962:2021. CycloneDX lahir dari OWASP dengan fokus keamanan, lalu diadopsi sebagai ECMA-424 pada 2024.
Pilih berdasarkan siapa yang mengonsumsi hasilnya. Kalau tim compliance klien sudah punya alur kerja sendiri, ikuti format mereka. Kalau tidak ada yang punya preferensi, CycloneDX JSON lebih enak dibaca dan diolah, sedangkan SPDX punya lebih banyak tool legal di sekitarnya.
Konversi antar keduanya juga rutin, dan syft sendiri bisa menghasilkan
dua-duanya. Debat format ini memakan waktu rapat lebih banyak daripada
nilainya. Nilai sebenarnya ada di kebiasaan membuat file itu, lalu
menindaklanjutinya.
Cara membuatnya
Syft (Apache-2.0) jadi pilihan default saya. Tool ini membaca direktori source, container image, atau artifact hasil build, lalu mengeluarkan SPDX atau CycloneDX:
syft dir:. -o cyclonedx-json=sbom.json
syft registry.example.com/app:2.4.1 -o spdx-json=sbom-image.json
Tool bawaan tiap ekosistem menggali lebih dalam di bahasanya sendiri, jadi layak dijalankan berdampingan:
cargo deny check licenses— Rust, sudah punya allow/deny list dan evaluasi SPDX expression di dalamnyago-licenses report— Go, mencari file lisensi per modulepip-licenses— Python, membaca metadata distribusi yang terpasang
Versi Rust-nya patut ditiru ekosistem lain: policy dan scanning ada di satu tool, exit code non-zero saat ada pelanggaran, tanpa perlu script perekat.
Gate-nya baru bagian yang bernilai
SBOM yang cuma nongkrong di folder build tidak mengubah apa pun. Gate-nya yang bekerja. Kelompokkan lisensi ke tiga keranjang, lalu hubungkan masing-masing ke satu hasil CI.
Lolos diam-diam — MIT, BSD-2-Clause, BSD-3-Clause, ISC, Apache-2.0, Zlib. Semuanya permisif, kewajibannya cuma atribusi, dan itu ditangani langkah NOTICE di bawah.
Gagalkan build — AGPL-3.0, SSPL, BUSL-1.1, varian Creative Commons non-komersial, dan string kosong. AGPL dan SSPL karena pemakaian lewat jaringan memicu kewajiban buka source yang hampir pasti tidak Anda inginkan menempel di deliverable klien. BUSL karena selama masa change period-nya lisensi itu bukan open source. CC non-komersial karena delivery komersial justru pekerjaan yang sedang Anda kerjakan.
String kosong masuk daftar gagal karena tanpa teks lisensi berarti tidak ada izin yang diberikan. Posisinya lebih buruk daripada lisensi restriktif, bukan lebih aman.
Tandai untuk review manusia — LGPL-2.1, LGPL-3.0, MPL-2.0, EPL-2.0, dan GPL-2.0 dengan classpath exception. Semuanya aman secara bersyarat. LGPL masih bisa dipakai saat dynamic linking (library dimuat terpisah saat program jalan) dan bermasalah saat static linking (ditanam mati ke dalam program), jadi jawabannya bergantung pada cara Anda mengirimkannya. MPL itu copyleft (lisensi yang mewajibkan turunan ikut terbuka) per file yang jarang menggigit, tapi tetap ada yang harus memastikan file mana saja yang Anda ubah.
Satu detail teknis sering merusak gate yang dibuat asal-asalan. SPDX
license expression bukan string biasa. Satu package bisa menulis
MIT OR Apache-2.0, Apache-2.0 WITH LLVM-exception, atau
MIT AND BSD-3-Clause.
Perbandingan string persis akan menolak MIT OR Apache-2.0, padahal
keduanya sama-sama boleh. Pakai tool yang benar-benar mem-parsing
expression. Kalau tidak, dalam dua sprint tim Anda akan terbiasa
mengabaikan gate itu.
Container image adalah pohon dependency kedua
Scan di level aplikasi melewatkan lapisan sistem operasi. Padahal satu jenis kejutan khas justru bersembunyi di sana.
Contoh paling jelas: ffmpeg yang dipasang lewat apt di Debian atau Ubuntu.
Paket itu dibangun dengan encoder berlisensi GPL seperti libx264 dan
libx265, jadi binary hasilnya didistribusikan di bawah GPL.
Cerita LGPL yang sering diulang orang soal FFmpeg berlaku untuk build yang
dikonfigurasi tanpa komponen itu. Hampir tidak ada yang membangun sendiri.
Semua orang menjalankan apt-get install ffmpeg, dan image-nya mewarisi
binary GPL yang tidak akan pernah muncul di scan package.json.
Seberapa penting hal ini bergantung pada cara Anda mengirim produk. Binary GPL yang dipanggil sebagai proses terpisah di service yang Anda operasikan sendiri berbeda posisinya dengan binary yang sama di dalam appliance yang diserahkan ke klien. Bagaimanapun, lapisan OS harus di-scan dulu sebelum pertanyaannya bisa diajukan.
Atribusi adalah kewajiban yang paling sering dilanggar
Semua lisensi permisif di allow list tadi tetap menuntut satu hal: cantumkan ulang copyright notice dan teks lisensinya di distribusi Anda. MIT menyatakannya dalam satu kalimat. Apache-2.0 menjabarkannya di empat klausul, plus kewajiban menyertakan file NOTICE kalau proyek asalnya punya.
Ini kewajiban yang paling sering dilanggar di software komersial, sekaligus yang paling murah diperbaiki. Buat file atribusi pihak ketiga dari SBOM saat build, lalu kirimkan bersama produk. Bisa di installer, di layar about, atau di folder docs sebelah binary.
Satu langkah pipeline menutup celah yang paling mungkin dipakai sebagai pembuka saat audit compliance.
Yang tidak akan ditemukan scanner mana pun
Tiga kategori ini tetap tidak terlihat oleh tool, jadi butuh proses manusia.
SDK biner tanpa manifest. File AAR dari vendor, DLL tertutup, atau library driver yang diserahkan lewat flashdisk. Tidak ada metadata package, tidak ada file lisensi, tidak ada yang bisa di-scan. Itu urusan kontrak yang diselesaikan sebelum integrasi, bukan saat build.
Model weights dan dataset. Package pip berlisensi Apache-2.0 bisa mengunduh weights berlisensi riset non-komersial saat pertama dijalankan. SBOM melihat package-nya dan melaporkannya bersih. Lisensi kode, lisensi weights, dan lisensi dataset adalah tiga izin yang terpisah.
Kode hasil salin-tempel. Potongan dari jawaban forum, contoh dari repository orang lain, fungsi yang diambil dari satu blog post. Tidak ada entri dependency, jadi tidak ada scanner yang melaporkannya. Scanner level file menangkap sebagiannya saat header lisensi lengkap ikut tersalin. Itu satu alasan menjalankannya sebelum codebase berpindah tangan.
Simpan SBOM bersama release-nya
Buat SBOM per release dan simpan sebagai artifact release di sebelah binary-nya. Bukan di wiki, bukan di folder home seseorang.
Alasannya praktis. Delapan belas bulan setelah serah terima, auditor klien bertanya isi versi 2.3.1 apa saja. Atau muncul CVE di sebuah library dan Anda perlu tahu versi mana saja yang sudah ter-deploy memakainya.
Membuat ulang SBOM dari git tag cuma menghasilkan perkiraan. Lockfile menghasilkan resolusi berbeda seiring waktu, dan package upstream bisa ditarik dari registry. SBOM yang dibuat saat build adalah catatan isi produk yang benar-benar dikirim.
Arah regulasi juga sama. EU Cyber Resilience Act mewajibkan produsen produk dengan elemen digital menyusun SBOM yang minimal mencakup dependency level atas. Kewajiban pelaporan kerentanannya mulai berlaku 11 September 2026, dan berlaku penuh pada 11 Desember 2027. Buat siapa pun yang menjual hardware atau software ke pasar Uni Eropa, ini bukan lagi pilihan.
Kesimpulan
Buat SBOM di CI. Saring dengan policy allow, deny, dan review yang paham SPDX expression. Scan container image-nya, bukan cuma repository. Hasilkan file NOTICE dari data yang sama, lalu arsipkan SBOM bersama release.
Itu menutup sisi pohon dependency. SDK biner, model weights, dan kode salin-tempel tetap urusan manusia. Sadar bahwa tool tidak menjangkau tiga hal itu sudah separuh jalan supaya ketiganya tidak berubah jadi masalah saat delivery.
Artikel Terkait
Mau bangun hal serupa?
Jasa Pembuatan Sistem Manajemen Hotel
Software manajemen hotel custom ala ERP: booking, status kamar, invoice, staf, dan otomatisasi WhatsApp — dibangun sesuai cara hotel Anda bekerja.
Lihat cara saya bisa bantu