Checklist Keamanan Dasar Aplikasi Web
Di dunia sistem klinik dan rumah sakit tempat saya banyak berkecimpung, data yang mengalir lewat aplikasi web bukan sekadar angka biasa — ada rekam medis, identitas pasien, sampai resep obat. Tapi sebenarnya prinsip yang sama berlaku untuk aplikasi web apa pun: e-commerce, sistem internal kantor, atau blog sekalipun. Masalahnya, di tengah tekanan deadline, hal-hal dasar soal keamanan justru yang paling sering terlewat. Bukan karena timnya tidak tahu, tapi karena "nanti saja, yang penting fitur jalan dulu" adalah kalimat yang sangat mudah diucapkan. Berikut checklist yang biasa saya pakai sebagai pengingat, dibagi ke empat area yang menurut pengalaman saya paling sering bolong.
Input Validation
Prinsipnya sederhana: jangan pernah percaya data yang datang dari luar, termasuk dari form yang "sudah divalidasi di frontend". Validasi di sisi client itu bagus untuk pengalaman pengguna, tapi bukan pertahanan keamanan — siapa pun bisa mem-bypass-nya lewat request langsung ke API. Validasi yang sesungguhnya harus terjadi di server.
Di Laravel misalnya, saya selalu membiasakan diri memanfaatkan Form Request class ketimbang validasi inline di controller, supaya aturan validasi konsisten dan mudah diaudit:
public function rules(): array
{
return [
'email' => ['required', 'email', 'max:255'],
'nomor_rm' => ['required', 'string', 'regex:/^[0-9]+$/'],
];
}
Yang sering terlewat: validasi tipe file upload (jangan cuma cek ekstensi, cek juga MIME type sebenarnya), batas panjang string, dan whitelist nilai untuk field seperti status atau role — jangan biarkan field itu diterima sebagai string bebas.
Output Encoding
Ini pasangan dari input validation: begitu data masuk dan tersimpan, kita juga harus berhati-hati saat menampilkannya kembali. Kalau input validation mencegah data jahat masuk, output encoding mencegah data itu — yang mungkin lolos atau memang sengaja disimpan apa adanya — dieksekusi sebagai kode saat ditampilkan ke browser. Ini inti dari mencegah cross-site scripting (XSS).
Kabar baiknya, framework modern seperti Laravel Blade sudah melakukan escaping otomatis untuk {{ }}. Yang justru berbahaya adalah ketika developer sengaja pakai {!! !!} untuk menampilkan HTML mentah dari input pengguna — ini sering saya temui dilakukan demi "biar rich text-nya tampil bagus", tanpa sanitasi tambahan. Kalau memang butuh menerima HTML dari pengguna (misalnya editor WYSIWYG), gunakan library sanitasi khusus, bukan menampilkannya apa adanya.
Autentikasi
Autentikasi menjawab pertanyaan "kamu ini siapa?". Beberapa hal dasar yang sebaiknya dianggap wajib, bukan opsional: password di-hash dengan algoritma yang memang dirancang untuk password (bcrypt atau argon2, bukan MD5 atau SHA biasa), rate limiting pada endpoint login untuk mencegah brute force, dan session/token yang di-invalidate saat logout atau ganti password.
Satu hal yang sebagai ilustrasi sering saya lihat terlewat: reset password yang linknya tidak punya masa berlaku, atau token yang bisa dipakai berkali-kali. Idealnya token reset password sekali pakai dan punya expiry singkat, ditambah notifikasi email setiap kali ada perubahan kredensial.
Otorisasi
Kalau autentikasi soal "kamu siapa", otorisasi soal "kamu boleh apa". Ini area yang menurut saya paling sering jadi celah tersembunyi, karena bug-nya tidak langsung kelihatan — aplikasi tetap "jalan normal", hanya saja user A bisa mengakses data milik user B lewat manipulasi ID di URL (dikenal sebagai Insecure Direct Object Reference/IDOR).
Solusinya bukan cuma mengecek "apakah user sudah login", tapi juga "apakah user ini memang berhak atas resource spesifik ini". Di Laravel, ini persis fungsi Policy dan Gate — jangan andalkan filter di query list saja lalu lupa mengecek ulang saat akses detail lewat endpoint terpisah:
public function view(User $user, Patient $patient): bool
{
return $user->facility_id === $patient->facility_id;
}
Empat area ini memang terkesan dasar, dan justru karena itulah paling gampang diremehkan. Checklist sederhana yang saya pakai: setiap kali menambah endpoint baru, saya coba tanyakan ke diri sendiri — data apa yang masuk ke sini, apakah divalidasi; data apa yang keluar dari sini, apakah di-encode dengan benar; siapa yang boleh mengakses; dan apakah otorisasinya dicek di level resource, bukan cuma di level fitur. Kebiasaan kecil ini jauh lebih murah ditanamkan sejak awal ketimbang diperbaiki setelah insiden.