Referensi cepat security scanning DevOps: Trivy untuk image dan SBOM, Semgrep untuk SAST, dependency audit, secret scanning, dan integrasi CI/CD pipeline.
Security scanning punya beberapa lapisan, masing-masing menangkap kelas masalah berbeda. Tidak ada satu tool yang menang semuanya.
| Lapisan | Tool | Yang dicari |
|---|---|---|
| SAST | Semgrep, CodeQL | Kerentanan dan pola berbahaya di source code |
| SCA | Trivy, npm audit | CVE di dependency pihak ketiga |
| Secret scanning | Gitleaks, trufflehog | API key dan password yang tercommit |
| Image scanning | Trivy | CVE di base image dan package OS |
| IaC scanning | Trivy, Checkov | Misconfiguration Terraform, K8s, Dockerfile |
| DAST | ZAP | Kerentanan di aplikasi yang berjalan |
Urutan adopsi yang masuk akal: dependency audit dan image scanning dulu (paling banyak temuan dengan effort paling kecil), lalu secret scanning, baru SAST. DAST biasanya paling akhir karena butuh aplikasi yang bisa dijalankan.
Trivy adalah scanner all-in-one buatan Aqua Security: image container, filesystem, repository Git, sampai misconfiguration IaC. Satu binary, tanpa server.
# Install via apt (Ubuntu/Debian)
sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key \
| gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" \
| sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install trivy
# Scan image
trivy image nginx:1.27
# Hanya tampilkan severity HIGH dan CRITICAL
trivy image --severity HIGH,CRITICAL nginx:1.27
# Fail build kalau ada temuan, threshold exit code
trivy image --exit-code 1 --severity HIGH,CRITICAL nginx:1.27# Scan repository Git (temukan CVE dependency plus secret)
trivy repo https://github.com/user/project
# Scan filesystem proyek lokal
trivy fs --severity HIGH,CRITICAL .
# Scan misconfiguration IaC: Dockerfile, Kubernetes, Terraform
trivy config ./infra
# Scan rootfs server atau CI runner
trivy rootfs --scanners vuln,secret /path/to/dirHasil Trivy memisahkan temuan per layer image. Kolom Fixed Version menunjukkan versi package yang sudah menambal CVE itu, jadi aksi utamamu jelas: naikkan versi. Kalau belum ada versi perbaikan, cek apakah fitur yang rawan benar-benar dipakai aplikasimu; banyak CVE hanya berlaku untuk kondisi tertentu.
| Kolom | Arti | Aksi |
|---|---|---|
| Severity | CRITICAL, HIGH, MEDIUM, LOW | Prioritas remediasi |
| Fixed Version | Versi yang sudah menambal | Upgrade package |
| Primary URL | Link ke advisory CVE | Baca detail dan syarat eksploitasi |
| Layer | Layer image sumber temuan | Kalau dari base, ganti base image |
Tiga jalan keluar untuk tiap temuan: upgrade ke fixed version, ganti base image ke tag yang lebih baru atau varian slim/alpine, atau terima risikonya dengan dokumentasi (misal CVE di package yang tidak kamu pakai fiturnya). Jangan cuma menutup temuan tanpa catatan.
| Aspek | Trivy | Grype | Snyk |
|---|---|---|---|
| Lisensi | Open source | Open source | Komersial, ada tier gratis |
| Coverage | Image, fs, repo, IaC, secret | Image dan filesystem | Image, code, dependency, IaC |
| UI | CLI plus template output | CLI | Dashboard web plus PR comments |
| SBOM | SBOM consumption plus generation | SBOM consumption | Generation |
Trivy menang di coverage per binary tunggal. Snyk menang di pengalaman tim: PR comments otomatis dan saran upgrade, tapi ada batas kuota di tier gratis.
SBOM (Software Bill of Materials) adalah daftar inventaris semua komponen di dalam artefak software kamu: package OS, library, versinya, dan lisensinya. Analoginya daftar bahan di kemasan makanan. Saat CVE baru keluar (kasus Log4Shell adalah contoh klasik), kamu tidak perlu mengaudit ulang semua aplikasi satu per satu; tinggal query SBOM: siapa pakai log4j versi di bawah 2.15.
Dua format standar:
# Generate SBOM CycloneDX dari image
trivy image --format cyclonedx --output sbom.json nginx:1.27
# Generate SBOM SPDX
trivy image --format spdx --output sbom.spdx.json nginx:1.27
# Scan CVE langsung dari file SBOM
trivy sbom sbom.jsonSimpan SBOM artefak di artifact store (GitHub Releases, OCI registry) setiap rilis. Trivy juga bisa menerima SBOM sebagai input scan, jadi kamu bisa scan ulang inventaris lama saat advisory baru muncul tanpa pull image.
Semgrep adalah SAST berbasis aturan pattern matching pada AST (abstract syntax tree), bukan teks mentah. Aturannya menyerupai kode yang dicari, jadi mudah ditulis dan dibaca. Ini pembedanya dari grep: pattern foo($X) cocok dengan pemanggilan foo siapa pun argumennya, dan tidak salah cocok dengan string "foo(1)" di komentar.
# Install
pip install semgrep
# atau
brew install semgrep
# Scan dengan registry aturan resmi
semgrep --config=auto .
# Pakai rule set spesifik
semgrep --config=p/python .
semgrep --config=p/owasp-top-ten .
semgrep --config=p/dockerfile .rules:
- id: node-md5-password-hash
pattern-regex: |
createHash\(["']md5["']\)
message: >
MD5 tidak layak untuk hashing password. Pakai bcrypt atau argon2.
languages: [javascript]
severity: WARNING
- id: flask-debug-mode
patterns:
- pattern: app.run(..., debug=True, ...)
message: >
Jangan jalankan Flask dengan debug=True di produksi; debugger bisa dieksekusi remote.
languages: [python]
severity: ERRORMulai dari registry (--config=auto), lalu tambah aturan custom untuk pola spesifik organisasimu: cara salah pakai library internal, konfigurasi internal yang dilarang, dan sebagainya.
| Aspek | Semgrep | CodeQL | SonarQube |
|---|---|---|---|
| Model | Pattern matching di AST | Analisis aliran data lintas file | Analisis statis plus quality gate |
| Aturan | Mudah ditulis sendiri | Query berbasis bahasa QL | Bawaan, konfigurasi |
| Bahasa | 30 plus bahasa | Terbatas (JS, TS, Java, Python, Go, C++) | Banyak |
| Tempat jalan | Lokal atau CI | GitHub Advanced Security (berbayar) | Self-hosted atau cloud |
Semgrep paling pas untuk tim yang ingin aturan cepat dan transparan. CodeQL lebih dalam (bisa lacak data dari input sampai sink) tapi berat dan terikat GitHub. SonarQube kuat di kualitas kode umum, bukan khusus security.
# Audit dependency npm
npm audit
# Perbaiki otomatis yang bisa (upgrade semver-compatible)
npm audit fix
# Paksa major upgrade (bisa breaking, review dulu)
npm audit fix --force
# Hasil JSON untuk diparse CI
npm audit --json
# pnpm dan yarn punya padanan
pnpm audit
yarn auditnpm audit fix menyelesaikan banyak kasus tanpa drama, tapi --force bisa merusak API. Selalu jalankan test setelahnya.
# Cek dependency Python terhadap advisory
pip-audit -r requirements.txt
# Sekaligus cek proyek di environment aktif
pip-audit
# Hasil JSON
pip-audit --format=jsonpip-audit mengambil data dari PyPI Advisory Database. Untuk lockfile penuh (poetry, pip-tools), audit file hasil lock, bukan requirements.in, supaya semua pinned version ikut diperiksa.
govulncheck ./...govulncheck unggul dibanding scanner generik: ia menganalisis call graph dan hanya melaporkan CVE pada fungsi yang benar-benar dipanggil kode kamu, bukan semua CVE di module graph.
Audit selalu file lock (package-lock.json, poetry.lock, go.sum), bukan manifest (package.json, pyproject.toml). Lock memuat versi persis yang terpasang; manifest hanya constraint. Scan manifest membuat temuan tidak akurat.
# Scan seluruh riwayat git
gitleaks detect --source . -v
# Scan hanya perubahan staged (untuk pre-commit)
gitleaks protect --staged -v
# Scan direktori non-git
gitleaks detect --source ./config --no-git -vKalau secret ketahuan sudah tercommit, jangan cuma hapus dari commit terbaru. Git menyimpan riwayat, secret tetap bisa diambil. Langkah yang benar: rotate secret tersebut segera, baru bersihkan riwayat dengan tool seperti git-filter-repo kalau repo belum dibagikan luas.
Pencegahan lebih murah dari rotate: pakai pre-commit hook dan simpan secret di environment variable atau secret manager. GitHub juga punya push protection yang menolak push berisi pola secret sebelum masuk.
Pola pipeline keamanan yang saya pakai di semua proyek: scan cepat di setiap PR, scan penuh saat build image. Sintaks lengkap workflow GitHub Actions ada di cheat sheet /cheat-sheets/github-actions; di sini fokus ke pekerjaan scan-nya.
name: security
on:
pull_request:
push:
branches: [main]
jobs:
secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm audit --audit-level=high
continue-on-error: false
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install semgrep
- run: semgrep scan --config=auto --error
image:
runs-on: ubuntu-latest
needs: [secrets, deps]
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t app:${{ github.sha }} .
- name: Trivy scan image
uses: aquasecurity/trivy-action@0.28.0
with:
image-ref: app:${{ github.sha }}
severity: HIGH,CRITICAL
exit-code: "1"
format: table
- name: Generate SBOM
uses: aquasecurity/trivy-action@0.28.0
with:
image-ref: app:${{ github.sha }}
format: cyclonedx
output: sbom.cdx.json
- uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.cdx.jsonUrutan job sengaja dibuat bertingkat: secret dan dependency gagal akan memblokir build image, jadi artefak rentan tidak pernah dihasilkan. SBOM ikut di-upload sebagai artifact untuk setiap commit yang lolos.
Fail pipeline hanya untuk CRITICAL dan HIGH dengan fixed version tersedia. Kalau kamu fail untuk semua temuan LOW dan MEDIUM, tim akan terbiasa dengan pipeline merah terus-menerus, dan saat CRITICAL asli muncul, orang sudah kebal. Fenomena alert fatigue ini persis sama dengan masalah noise di monitoring.
Pemisahan lain yang sehat: PR dari orang luar bisa dibuat continue-on-error untuk job scan (kebijakan per repo), sementara push ke main tetap keras.
# .git/hooks/pre-commit atau via framework pre-commit
gitleaks protect --staged -v || {
echo "Secret terdeteksi. Hapus secret, lalu rotate kalau sudah pernah tercommit."
exit 1
}Hook lokal mencegah secret masuk sebelum push, jauh lebih murah daripada membatalkan push di CI.
Sebagian besar temuan di image aplikasi berasal dari base layer, bukan kode kamu. Pilihan base image menentukan luas permukaan serangan:
| Base image | Ukuran | Package OS | Cocok untuk |
|---|---|---|---|
| ubuntu:24.04 | ~78 MB | Banyak, apt | Butuh tooling lengkap |
| debian:12-slim | ~75 MB | Lebih sedikit | General purpose |
| alpine:3.20 | ~7 MB | Sangat sedikit, musl | Ukuran minimal |
| distroless (Debian) | ~20-50 MB | Tanpa shell dan package manager | Produksi |
| scratch | 0 MB | Kosong | Binary static (Go, Rust) |
Alpine kecil tapi pakai musl libc; sebagian binary yang dikompilasi untuk glibc (misal versi prebuilt sebagian library) tidak jalan tanpa adaptasi. Distroless menghilangkan shell sehingga serangan remote code execution lebih sulit dieksploitasi, tapi kamu tidak bisa docker exec masuk untuk debugging; siapkan debug variant saat butuh.
# Buruk: tag latest, user root, layer tidak dipin
FROM node
COPY . .
RUN npm install
CMD npm start
# Baik: tag spesifik, multi-stage, non-root
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]Jangan rebuild image dengan tag yang sudah dipakai (app:latest anti pattern klasik). Setiap build dapat tag unik (SHA commit), dan scan mengikat hasil ke tag itu. Image yang sama bisa muncul temuan baru setelah advisory dirilis, jadi jadwalkan rescan berkala (misal mingguan via cron CI) untuk image yang masih dipakai di produksi.
Kerangka memutuskan urutan perbaikan saat daftar temuan panjang:
Dua hal yang mempercepat semua nomor di atas: pin versi dependency agar upgrade terkendali, dan otomasi upgrade via Dependabot atau Renovate sehingga mayoritas HIGH tertangani lewat PR otomatis yang tinggal di-review.
Login atau daftar akun gratis untuk membaca cheat sheet ini.