Semua pertahanan yang kita bangun sepanjang section ini — rate limit, policy, secret yang rapi — berdiri di atas asumsi bahwa kondisinya tetap seperti saat ditulis. Kenyataannya, aplikasi hidup: dependency baru dipasang tiap pekan, fitur baru menambah route baru, dan celah di paket pihak ketiga ditemukan orang lain di luar sana. Audit keamanan adalah ritual berkala yang memverifikasi asumsi-asumsi itu, idealnya tiap kuartal. Chapter terakhir ini merangkai alurnya jadi rutinitas satu jam: scan dependency otomatis, review kode terarah, dan checklist yang konsisten.
Scan Dependency dengan composer audit #
Mayoritas kerentanan serius di aplikasi modern datang dari paket yang dipasang, bukan dari kode kita. Composer menyediakan pemeriksa bawaan yang membandingkan versi terpasang dengan basis data security advisory publik. Kita jalankan di aplikasi uji:
$ composer audit
No security vulnerability advisories found.Hasil bersih — versi terkunci di composer.lock tidak cocok dengan satu pun advisory yang diketahui. Variasi composer audit --no-dev memeriksa dependensi produksi saja, berguna bila proses build Anda memasang paket dengan --no-dev. Perlu dicatat hasilnya adalah foto kondisi hari ini: advisory baru terbit setiap saat, jadi nilainya ada pada pengulangan. Sebagai referensi kebiasaan rilis dan perbaikan keamanan Laravel, pantau catatan rilis resmi
; untuk analisis statis menyeluruh, komunitas menyediakan paket pemeriksa seperti enlightn/security-advisories yang memeriksa versi Laravel terhadap daftar CVE historis.
Mengunci Gerbang di CI #
Audit manual mudah dilupakan — jadi jangan buat manual. Masukkan composer audit sebagai gerbang wajib di pipeline CI agar pull request yang membawa paket rentan otomatis gagal:
name: Security Audit
on:
schedule:
- cron: '0 6 * * 1' # setiap Senin pagi
pull_request:
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
- run: composer install --prefer-dist --no-interaction
- run: composer audit --no-devKonfigurasi ini menjalankan audit dua arah: pada setiap pull request (mencegah paket rentan baru masuk) dan terjadwal mingguan (menangkap advisory yang terbit setelahnya). Exit code composer audit bukan nol saat ada temuan, sehingga pipeline otomatis merah.
Review Kode Terarah: Mencari yang Berbahaya #
Mesin tidak bisa menilai niat kode; review manusia masih diperlukan — tetapi menjadi efisien kalau terarah ke pola berisiko tinggi. Dua pola teratas di aplikasi Laravel: output Blade mentah dan SQL mentah. Keduanya bisa dicari dengan rg langsung di repositori. Kita cari directive {!! !!} yang mem-bypass escaping Blade:
$ rg -n '\{!!' resources/views/
resources/views/catatan/tampil.blade.php:3: {!! $catatan->isi_html !!}Satu temuan — dan langkah yang jauh lebih penting daripada temuan itu: telusuri dari mana $catatan->isi_html berasal. Bila isinya murni hasil generate aplikasi, risikonya rendah; bila isinya input user yang sudah disaring, pastikan sanitasinya memadai — persis skenario di Cross-Site Scripting
. Pencarian yang sama berlaku untuk SQL mentah:
$ rg -n "whereRaw|orderByRaw|DB::raw" app/ routes/
app/Http/Controllers/CatatanController.php:18: return Tugas::whereRaw("judul like ?", ['%'.$request->input('q').'%'])
app/Http/Controllers/CatatanController.php:19: ->orderByRaw($urutan)Baris 18 aman — nilai user masuk lewat binding parameter ?. Baris 19 layak dicermati: orderByRaw($urutan) hanya aman bila $urutan dipilih dari daftar kolom yang diizinkan (pola in_array($urut, ['judul', 'isi']) ? $urut : 'judul'), bukan diambil langsung dari input user. Setiap Raw harus punya penjelasan semacam ini — persis standar yang dibedah di SQL Injection Prevention
.
Checklist Review Keamanan #
Pola yang sama, dikumpulkan jadi checklist yang dijalankan konsisten tiap audit:
- Setiap route tulis (
POST/PUT/PATCH/DELETE) punya pemeriksaan otorisasi (Authorization Security ) - Setiap input eksternal tervalidasi sebelum menyentuh query atau response
-
rg '{!!'atas views: setiap temuan punya justifikasi dan sanitasi -
rg 'Raw|DB::select': setiap query mentah memakai binding parameter -
$fillablemodel hanya memuat kolom yang memang boleh diisi user (Mass Assignment ) -
.envtidak terlacak Git; secret produksi hanya hidup di environment-nya -
APP_DEBUG=false; cookie produksi ber-secure; header keamanan terpasang - Route login dan endpoint berat terlindungi
throttle - Upload file dibatasi tipe, ukuran, dan lokasi simpannya (Secure File Uploads )
- Upload berkala:
composer audit,composer outdated --direct, dan sesuaikan temuan
Checklist ini sengaja memetakan kembali bab-bab section ini — audit yang baik bukan ilham, melainkan pengulangan daftar yang sama tanpa bosan.
Penetration Test, Bug Bounty, dan Insiden #
Checklist internal punya batas: ia memeriksa hal yang sudah kita ketahui. Penetration test membawa sudut pandang luar — penguji berperan sebagai penyerang pada aplikasi staging. Untuk tim kecil, satu pentest tahunan atau sesi mutual review antar developer sudah jauh lebih baik daripada tidak ada. Aplikasi publik bisa melangkah lebih jauh dengan program bug bounty: sediakan kanal pelaporan yang jelas dan apresiasi bagi pelapor yang bertanggung jawab.
Bila laporan masuk — atau kebocoran terdeteksi — urutan tanggap daruratnya: isolasi (revoke token/session terdampak), rotasi secret (Secret Management ), perbaikan, lalu transparansi ke pengguna terdampak. Catat timeline kejadian untuk evaluasi; insiden yang tidak dicatat akan terulang.
Dengan ritme audit terjaga, siklus keamanan aplikasi kita tertutup penuh: mencegah di desain, memverifikasi lewat testing , dan memeriksa ulang secara berkala. Keamanan memang bukan fitur yang selesai — ia kebiasaan yang dipelihara.