Satu image kini membawa dua bukti tentang dirinya: tabel cacat dari pemindaian dan attestation asal-usul dari provenance. Tetapi kedua bukti itu menjelaskan produk akhir saja — padahal image tidak lahir dari kekosongan. Image lahir dari rantai yang panjang: source code di repository, dependensi dari package registry, base image dari image registry, build di runner CI, penyimpanan di registry, dan akhirnya deploy ke server. Setiap mata rantai itu dioperasikan orang dan sistem yang berbeda, dan setiap mata rantai adalah pintu masuk bagi penyerang yang tidak mau susah payah menembus isolasi container. Chapter ini memanjangkan pengawasan kita dari satu image menjadi seluruh rantai pasoknya: memetakan risiko tiap mata rantai, memasang mitigasi yang sudah kita kenali satu per satu sepanjang course, lalu merangkainya menjadi checklist dan peta kematangan.
Rantai Pasok Sebuah Image #
Diagram di atas membaca alur lahirnya budi/katalog-web:2.0 dari hulu ke hilir: kode Budi digabung dengan dependensi npm dan base image node:22-alpine, dirakit oleh CI menjadi image, tersimpan di registry, lalu ditarik server produksi. Enam mata rantai, enam pihak yang harus kita percaya — dan satu-satunya cara mempercayai dengan mata terbuka adalah memberi tiap mata rantai kontrol yang bisa diverifikasi. Serangan supply chain menyusup justru lewat kepercayaan itu: penyerang tidak menyerang image yang sudah jadi, melainkan mengganti satu bahan sebelum image dirakit.
Risiko di Setiap Mata Rantai #
| Mata rantai | Skenario serangan nyata | Mitigasi inti |
|---|---|---|
| Source code | repository dibajak, commit berbahaya menyusup | proteksi branch, review wajib |
| Dependensi | typosquatting — paket requets meniru requests | lock file, disiplin nama paket |
| Base image | tag node:22-alpine dipindahkan ke isi berbeda | pin berdasarkan digest |
| Runner CI | action pihak ketiga diracuni, kredensial dicuri | runner ephemeral, action dipin SHA |
| Registry | akun push dibajak, image ditimpa | tanda tangan + verifikasi digest |
| Insider | orang dalam menyuntik kode atau kredensial | review, audit log, least privilege |
Enam skenario itu bukan khayalan: typosquatting dengan nama yang salah satu hurufnya digeser adalah cara klasik menyelundupkan paket berbahaya ke project, dan image populer yang ditimpa isinya pernah terjadi di registry publik. Mari kita pasang mitigasinya satu per satu.
Mitigasi per Mata Rantai #
Kunci Dependensi dengan Lock File #
Dependensi harus diinstal dari versi yang tercatat persis, bukan versi yang kebetulan tersedia saat build berjalan. Berkas package-lock.json (atau Cargo.lock, poetry.lock) menyimpan versi terpasang lengkap dengan hash-nya, dan perintah npm ci menegakkannya dengan keras: bila lock file tidak sinkron dengan package.json, instalasi menolak jalan — kegagalan yang kita manfaatkan sebagai gerbang pada Chapter Reproducible Build. Lock file ikut di-commit ke repository, sehingga build ulang kapan pun menghasilkan pohon dependensi yang sama.
Pin Base Image berdasarkan Digest #
FROM node:22-alpine adalah kepercayaan pada tag yang bisa dipindahkan penerbitnya — risiko yang kita buktikan tuntas pada Chapter Image Digest. Versi terkuncinya menuliskan digest secara eksplisit:
FROM node:22-alpine@sha256:22c1edb32d80d7d5460fa55063156af7fa5daa79bf932170a06e30c9d8fbb09fBuild kini terikat pada byte-byte base image tertentu: penerbit boleh memindahkan tag sebanyak apa pun, image kita tidak bergeser. Konsekuensinya harus dijalani juga — pembaruan base image tidak lagi datang otomatis, sehingga bot penjaga dependensi seperti Dependabot atau Renovate disiapkan untuk membuka PR yang menaikkan digest secara terjadwal dan ter-review.
Verifikasi Penerbit Image #
CI Ephemeral dengan Permission Minimal #
Runner yang membangun image adalah mata rantai paling kaya kredensial: token registry, kunci penandatanganan, akses repository. Dua kebiasaan menutup sebagian besar permukaannya. Pertama, runner ephemeral — VM sekali pakai yang dihancurkan setiap selesai job, tidak menyimpan state dan tidak menyimpan rahasia job sebelumnya. Kedua, permission minimal: token diberi scope sesempit mungkin, secret di-inject per job lewat mekanisme secret yang kita kenal dari Chapter Secret Management, dan action GitHub dipin berdasarkan commit SHA penuh alih-alih tag yang bisa dipindahkan — logika digest, diterapkan pada workflow. Seluruh pola CI ini dibangun tuntas di Section CI/CD dan Automation.
Gerbang Scan dan Verifikasi Provenance #
Hilir rantai menuntut bukti sebelum image boleh lewat. Gerbang scan menolak rilis yang melampaui ambang kebijakan — tabel CRITICAL dan HIGH dari Chapter Image Scanning — dan verifikasi provenance memastikan attestation yang dibaca memang milik image yang akan dideploy. Kuncinya satu dan tidak bisa dinegosiasi: semua verifikasi dilakukan terhadap digest, bukan tag. Tag boleh berpindah di antara manifest kapan pun; digest yang sama hari ini dan esok adalah satu-satunya pegangan yang membuat hasil verifikasi tetap bermakna.
Diff SBOM antar Rilis #
Satu kebiasaan audit yang murah tetapi tajam: bandingkan SBOM rilis baru dengan rilis sebelumnya. Perubahan yang wajar — kode berubah, dependensi ikut berubah — terlihat seimbang. Yang mencurigakan adalah satu sisi berat sebelah: paket baru muncul di SBOM padahal tidak ada perubahan kode sama sekali — misalnya base image berganti isi, atau dependensi transitive membawa tamu tak diundang. Bendera merah seperti ini paling mudah tertangkap bila diff SBOM menjadi bagian rutin dari review rilis, dan kedua attestation yang kita bangun pada Chapter Image Provenance menyediakan bahan diff-nya secara gratis.
SLSA sebagai Peta Kematangan #
Tangga level SLSA yang kita kenal di chapter sebelumnya — dari build terdokumentasi, hosted build, sampai hardened build — di sini menemukan perannya yang sebenarnya: bukan sertifikat yang dibeli sekali, melainkan peta jalan yang dinaiki lewat kebijakan tertulis. Naik level berarti menulis dan menegakkan aturan: “semua image produksi wajib provenance mode=max”, lalu “semua build harus berjalan di runner ephemeral”, lalu “setiap deploy memverifikasi tanda tangan terhadap digest”. Setiap aturan yang ditulis dan ditegakkan menggeser seluruh rantai satu tingkat lebih sulit disusupi.
Checklist Rantai Pasok #
| Mata rantai | Kontrol yang wajib melekat |
|---|---|
| Source | proteksi branch dan review wajib untuk setiap merge |
| Dependensi | lock file di-commit; CI menjalankan npm ci |
| Base image | FROM dipin berdasarkan digest; kenaikan via PR |
| Build | provenance mode=max dan SBOM menyala |
| Rilis | gerbang scan dengan ambang tertulis |
| Deploy | pull dan verifikasi berdasarkan digest |
Rantai pasok kini terkunci dari hulu ke hilir: source dijaga review, dependensi terkunci, base image terpatok digest, build membawa bukti, rilis melewati gerbang, dan deploy memegang identitas yang tak bisa dipalsukan. Namun setelah semua pintu itu tertutup, satu lubang klasik masih sering dibiarkan terbuka — dan lubang itu bukan di dalam container, melainkan di sistem yang menjalankan semuanya: socket /var/run/docker.sock. Siapa pun yang memegang socket itu memegang root di host, dan container yang mount socket-nya menyerahkan kunci itu begitu saja. Chapter Docker Socket Security menutup section ini dengan membongkar lubang yang paling sering diabaikan beserta enam mitigasinya.
Referensi #
- Build best practices — pematokan base image dan praktik build yang aman.
- Docker security — kerangka isolasi dan keamanan di sekitar rantai build-run.
- SLSA — definisi resmi level kematangan supply chain dan jalur penaikkannya.