
Hari 10: MD5 ke Bcrypt, Pipeline Hijau Lagi
Hari kesepuluh 60 hari DevSecOps! Fix SAST findings — ganti MD5 ke bcrypt, hapus custom rule HTTP TLS, dan pipeline CI kembali hijau setelah 4 job semua pass.
Dari Pipeline Merah ke Pipeline Hijau (Lagi)
Kemarin pipeline merah karena Semgrep nemuin 2 findings: MD5 yang gak aman dan HTTP server tanpa TLS. Hari ini tugasnya fix semua itu biar pipeline kembali hijau.
Ini repeat pattern yang udah kita lakuin di Day 7 (SCA remediation): scan → temukan masalah → fix → pipeline hijau. Tapi kali ini yang di-fix bukan dependensi, tapi kode yang kita tulis sendiri.
Fix 1: Ganti MD5 dengan bcrypt
Kode pkg/crypto/hash.go yang kemarin sengaja bikin pakai MD5, sekarang diganti bcrypt — industry standard buat password hashing:
// SEBELUM — insecure, MD5 is cryptographically broken
func HashPassword(password string) string {
h := md5.Sum([]byte(password))
return hex.EncodeToString(h[:])
}
// SESUDAH — secure, bcrypt with auto-salt and cost factor
func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes), err
}
func CheckPassword(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
Perhatikan signature berubah dari func(string) string jadi func(string) (string, error) — sekarang return error juga, yang cuma good practice di Go. Dan kita tambah fungsi CheckPassword() buat verifikasi hash.
Kenapa bcrypt dan bukan SHA-256?
- bcrypt otomatis tambah salt — gak perlu manual
- bcrypt punya cost factor yang bisa di-adjust — makin tinggi makin lambat buat brute force
- SHA-256 cocok buat checksum dan data integrity, bukan password hashing
- Di Go,
golang.org/x/crypto/bcryptudah ada sebagai dependency transitif dari gin
Fix 2: HTTP tanpa TLS
Untuk finding no-http-listen-without-tls di main.go, kita tentukan untuk accept sebagai warning. Kenapa?
- HTTP server tanpa TLS itu expected untuk development environment
- Di production, biasanya pakai reverse proxy (nginx, cloud load balancer) yang handle TLS termination
- Force TLS di application level buat development itu lebih ribet daripada manfaatnya
Jadi kita hapus custom rule no-http-listen-without-tls dari .semgrep.yml. Built-in rules dari p/golang masih akan flag ini sebagai WARNING, tapi custom rules kita cuma focus ke yang critical.
Hasil: Pipeline Hijau
✅ Build & Test (Go 1.26) — success
✅ Secret Scan (Gitleaks) — success
✅ SCA Scan (Trivy) — success (0 CVE)
✅ SAST Scan (Semgrep) — success (0 blocking findings)
4/4 job hijau. Dari pipeline merah kemarin karena SAST findings, sekarang semua clean.
Perbandingan Sebelum dan Sesudah
| Aspek | Sebelum (Day 09) | Sesudah (Day 10) |
|---|---|---|
| MD5 hashing | crypto/md5 (insecure) |
bcrypt (secure) |
| HTTP tanpa TLS | Flagged sebagai WARNING | Accepted untuk dev environment |
| Semgrep custom findings | 2 (1 ERROR, 1 WARNING) | 0 |
| Semgrep built-in findings | 2 (use-of-md5, use-tls) | 1 (use-tls, accepted) |
| Pipeline status | ❌ MERAH | ✅ HIJAU |
| Trivy CVE | 0 | 0 |
Lesson Learned
1. bcrypt itu standard untuk password hashing, bukan SHA-256. Bcrypt auto-salt, punya cost factor, dan secara khusus dirancang buat password. SHA-256 dirancang buat data integrity, bukan password. Pilih tool yang sesuai use case-nya.
2. Accept WARNING di dev environment itu valid. HTTP tanpa TLS di development itu common pattern. Yang penting di production pakai reverse proxy yang handle TLS. Gak semua finding harus di-fix — tapi semua harus di-dokumentasi kenapa diterima.
3. Function signature change itu aman kalau belum dipanggil. HashPassword cuma di-blank import, jadi mengubah return type dari string ke (string, error) gak merusak kode mana pun. Kalau udah dipakai di banyak tempat, signature change butuh refactor lebih besar.
4. Custom rules bisa di-adjust per project. Kita hapus rule no-http-listen-without-tls karena gak applicable buat development API server. Tapi rule no-md5-usage tetap dipertahankan karena MD5 emang gak boleh dipakai di project perbankan manapun.
5. Pull pattern makin jelas: scan → temukan → fix → hijau. Dari Day 5 sampai Day 10, kita udah lakuin cycle ini 3 kali: SCA (scan → temukan CVE → fix dependencies → hijau), SAST (scan → temukan insecure pattern → fix kode → hijau). Pattern-nya konsisten dan repeatable.
Kesimpulan
Hari ini pipeline kembali hijau — 4/4 job pass, 0 CVE, 0 blocking SAST findings. Dari MD5 yang deprecated ke bcrypt yang aman, dari pipeline merah ke pipeline hijau.
Yang penting dari remediasi ini: kita bukan cuma nge-fix kode, tapi juga nge-fix strategy. MD5 itu fundamentally broken buat password hashing — gak ada versi "yang aman" dari MD5. Satu-satunya jalan adalah ganti total ke algoritma yang benar. Sama kayak jwt-go di Day 07 — library deprecated gak bisa di-patch, harus diganti total.
Sekarang pipeline punya 4 lapis pertahanan yang semua hijau: build/test, secret scanning, SCA scanning, dan SAST scanning. Setiap push dan PR otomatis di-scan dari 4 sudut yang berbeda.
Besok lanjut ke Hari 11: AI-Assisted Code Audit — gunakan output Trivy dan Semgrep sebagai input buat AI analisis.
Diskusi & Komentar
Hari 9: Semgrep SAST di CI, Pipeline Gagal Karena Kode
Next ArticleHari 11: AI Audit Temukan 5 Bug yang Scanner Lewati
Artikel Terkait
Hari 5: Trivy SCA Scan Nemukan 4 CVE di Golang API
Hari kelima 60 hari DevSecOps! Scan dependensi Go pakai Trivy dan nemukan 4 CVE termasuk 1 CRITICAL — termasuk library deprecated jwt-go.
Hari 8: Semgrep SAST Scan Temukan Kode Tidak Aman
Hari kedelapan 60 hari DevSecOps! Install Semgrep, buat kode insecure (MD5), dan scan ketemu 2 finding — MD5 weak hash dan HTTP server tanpa TLS.
Hari 3: Ngecek Kebocoran Secret di Kode Pakai Gitleaks
Hari ketiga 60 hari DevSecOps! Pakai Gitleaks buat scan secret yang bocor di repo — ternyata tool ini cukup pintar bedainya secret asli dan contoh.