Hari 8: Semgrep SAST Scan Temukan Kode Tidak Aman
4 min read

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.

devsecops
semgrep
sast
golang
code-security
60-days-challenge
Share

Dari Dependensi ke Kode Sendiri

Kemarin kita udah selesai ngeremidasi semua CVE di dependensi — pipeline hijau lagi, Trivy scan bersih. Tapi CVE di dependensi cuma separuh cerita. Bagaimana dengan kode yang kita tulis sendiri?

Hari ini kita masuk ke materi baru: SAST (Static Application Security Testing). Bedanya sama SCA: SCA scan library orang lain, SAST scan kode kita sendiri. Tool yang dipakai: Semgrep — scanner SAST yang bisa detect insecure pattern di kode secara otomatis.

Install Semgrep

brew install semgrep

Semgrep v1.165.0 berhasil diinstall tanpa masalah (berbeda dengan Trivy yang sempat timeout waktu install).

Sengaja Tambah Kode yang Tidak Aman

Sama kayak Day 05 yang sengaja tambah dependensi rentan, hari ini kita sengaja bikin kode yang insecure buat latihan:

package crypto

import (
    "crypto/md5"
    "encoding/hex"
)

// HashPassword uses MD5 — intentionally insecure for SAST demo
func HashPassword(password string) string {
    h := md5.Sum([]byte(password))
    return hex.EncodeToString(h[:])
}

Kenapa MD5? Karena MD5 itu cryptographically broken — gak cocok buat password hashing, rentan collision, dan udah ditinggalin komunitas security sejak lama. Tapi masih sering muncul di kode lama.

Scan dengan Semgrep: 2 Finding

Pertama, scan pakai built-in rules Go:

semgrep --config "p/golang" .

Hasilnya: 2 findings ditemukan.

Rule File Line Severity Masalah
use-of-md5 pkg/crypto/hash.go 11 WARNING MD5 adalah weak hash algorithm
use-tls cmd/api/main.go 80 WARNING HTTP server tanpa TLS

Yang menarik: Semgrep gak cuma nemuin MD5 yang kita sengaja taruh, tapi juga HTTP server tanpa TLS di main.go — sesuatu yang bahkan gak kepikiran buat dicek!

Custom Rule: .semgrep.yml

Built-in rules bagus, tapi setiap project punya kebutuhan khusus. Makanya kita buat custom rules di root repo:

rules:
  - id: no-md5-usage
    patterns:
      - pattern: md5.Sum(...)
    message: "MD5 is cryptographically broken. Use SHA-256 or bcrypt."
    languages: [go]
    severity: ERROR

  - id: no-http-listen-without-tls
    patterns:
      - pattern: http.ListenAndServe(...)
    message: "HTTP server without TLS. Use http.ListenAndServeTLS()."
    languages: [go]
    severity: WARNING

Perhatikan: rule MD5 kita set severity ERROR (lebih ketat dari WARNING di built-in), karena di project SecureBank, password hashing pakai MD5 itu harusnya gak boleh lolos sama sekali.

Sekarang scan pakai custom rules:

semgrep --config ../.semgrep.yml .

Hasilnya: sama — 2 findings. Custom rules kita bekerja sesuai harapan.

Pelajaran tentang Custom Rule Pattern

Awalnya aku coba pattern crypto/md5 (import path) buat ngedeteksi MD5. Tapi Semgrep gak match. Kenapa? Karena Semgrep itu pattern-based — dia nge-match pemanggilan fungsi (md5.Sum(...)), bukan import path (crypto/md5).

Ini beda sama SCA yang scan go.mod dan detect library berdasarkan import path. SAST itu detect cara kode ditulis, bukan library apa yang dipakai.

Simpan Report untuk Audit Trail

Buat keperluan dokumentasi dan nanti di-upload ke DefectDojo:

semgrep --config "p/golang" . --json --output security/semgrep-report.json

Report ini berisi detail lengkap: rule ID, file path, line number, severity, message, dan CWE mapping.

Lesson Learned

1. SAST dan SCA itu dua lapis pertahanan yang berbeda. SCA scan dependensi (library orang lain), SAST scan kode sendiri (cara kita nulis kode). Keduanya harus jalan barengan — cuma punya salah satu aja gak cukup.

2. Semgrep bisa nemuin masalah yang gak kepikiran. HTTP server tanpa TLS itu gak pernah kepikiran sebagai vulnerability, tapi Semgrep langsung flag. Ini contoh bagus kenapa automated scanning itu penting — kadang kita terlalu fokus ke satu masalah sampe lupa masalah yang lain.

3. Custom rule pattern harus match pemanggilan fungsi, bukan import path. crypto/md5 gak match, tapi md5.Sum(...) match. Ini beda fundamental antara SAST dan SCA — SAST nge-analyze aliran kode (code flow), bukan dependency tree.

4. Severity di custom rule bisa diatur lebih ketat. Kita set MD5 sebagai ERROR (bukan WARNING) karena di project SecureBank, password hashing pakai MD5 itu gak boleh lolos ke production sama sekali. Ini contoh shift-left — nge-blok masalah sedini mungkin.

5. Built-in rules (p/golang) udah cukup buat mulai. Gak perlu nulis semua custom rule dari nol. Mulai dari built-in rules, lalu tambahin custom rules buat kebutuhan spesifik project.

Kesimpulan

Hari ini pipeline keamanan kita tambah satu lapis lagi. Kalau kemarin cuma SCA (dependensi), sekarang ada SAST (kode sendiri). Semgrep nemuin 2 masalah — MD5 yang sengaja kita taruh, dan HTTP tanpa TLS yang bahkan gak kepikiran.

Custom rules bikin Semgrep lebih powerful buat project spesifik. Kita bisa set severity yang lebih ketat (ERROR ketimbang WARNING) dan nge-blok pattern yang memang gak boleh ada di SecureBank.

Dua finding ini gak akan di-fix hari ini — sengaja dibiarkan buat latihan. Di Day 10 (SAST Remediation), kita akan ganti MD5 ke SHA-256 dan pertimbangkan TLS buat production.

Besok di Day 9 kita masukkin Semgrep ke CI pipeline — biar setiap push otomatis di-scan dan PR diblok kalau ada masalah severity tinggi.

Repo: github.com/stayrelevantid/chalange-devsecops

Enjoyed this article? Share it!

Share

Diskusi & Komentar

Artikel Terkait