Audit Keamanan Laravel Sendiri

Sebelum sebuah aplikasi Laravel saya publikasikan lebih jauh, saya memutuskan untuk audit keamanan menyeluruh terhadap aplikasi portofolio saya sendiri yang pakai Filament sebagai panel admin. Cakupannya cukup lengkap: potensi kebocoran secret, proteksi CSRF, mass assignment, raw SQL query, XSS, mekanisme otorisasi panel admin, sampai kerentanan pada dependency (CVE). Niat awalnya cuma checklist rutin sebelum tidur nyenyak, tapi ternyata ada dua temuan yang bikin saya berhenti sejenak.

Root cause: fungsi otorisasi yang selalu bilang "iya"

Temuan pertama ini yang paling bikin deg-degan. Di Filament, ada satu fungsi yang tugasnya menentukan siapa boleh masuk ke panel admin. Waktu saya baca ulang implementasinya, isinya cuma satu baris: mengembalikan true tanpa syarat apa pun.

Artinya, siapa pun yang berhasil login ke aplikasi — bukan cuma admin, tapi user biasa sekalipun — otomatis mendapat akses penuh ke panel admin. Tidak ada pengecekan role, tidak ada pengecekan flag apa pun. Kemungkinan besar ini sisa dari fase development awal, semacam "biar gampang testing dulu", yang lupa dikencangkan lagi sebelum aplikasi jalan lebih serius.

Yang melegakan: ini ketahuan lewat audit yang saya jalankan sendiri, bukan lewat insiden atau laporan orang lain.

Solusi: kolom boolean yang sengaja tidak bisa diisi sembarangan

Perbaikannya saya buat sesederhana dan seaman mungkin. Saya tambahkan kolom boolean is_admin di tabel user, lalu fungsi otorisasi panel admin saya ubah supaya benar-benar mengecek nilai kolom itu, bukan lagi mengembalikan true begitu saja.

public function canAccessPanel(Panel $panel): bool
{
    return $this->is_admin === true;
}

Detail yang menurut saya justru paling penting: kolom is_admin ini sengaja tidak saya masukkan ke daftar field yang boleh diisi lewat mass assignment ($fillable). Kalau sampai masuk daftar itu, secara teori user bisa saja menyelipkan nilai is_admin: true lewat payload form registrasi atau API dan menaikkan level dirinya sendiri jadi admin. Dengan mengeluarkannya dari $fillable, kolom itu cuma bisa diubah lewat jalur yang saya kontrol sendiri, misalnya lewat seeder atau proses admin yang eksplisit.

Temuan kedua: puluhan CVE yang "legal" menurut composer

Bagian audit dependency juga tidak kalah mengagetkan. Saya jalankan audit terhadap dependency composer, dan hasilnya menunjukkan puluhan CVE — kerentanan yang sudah diketahui publik — tersebar di berbagai library yang dipakai aplikasi ini.

Yang menarik, semua versi yang terpasang itu sebenarnya masih dalam rentang yang diizinkan oleh composer.json. Constraint versinya tidak salah, cuma belum pernah dijalankan update untuk menarik versi terbaru yang sudah menambal celah-celah tersebut. Fix-nya jauh lebih sederhana dibanding temuan pertama: update semua dependency ke versi terbaru yang kompatibel, lalu jalankan audit lagi untuk memastikan daftarnya bersih.

Pelajaran

Dari dua temuan ini saya menarik satu benang merah: fungsi otorisasi yang kelihatannya remeh — apalagi yang cuma satu baris return true — adalah salah satu tempat paling berbahaya untuk tertinggal dalam kondisi "sementara" atau "buat testing dulu". Kodenya jalan mulus, tidak ada error, tidak ada warning, sampai suatu hari ada orang yang login dan tiba-tiba punya akses admin penuh.

Sebelum aplikasi apa pun, apalagi yang punya panel admin, dipublikasikan: cek ulang secara eksplisit siapa saja yang benar-benar bisa masuk ke sana. Jangan cuma berasumsi dari kode yang "kelihatannya baik-baik saja". Dan jangan lupakan audit dependency — jalankan secara rutin, bukan cuma sekali di awal project, karena CVE baru terus bermunculan pada library yang sudah lama terpasang.