Penyamaan Enum dan Slug pada Gerbang Modul di CMS KotaPortal
Gerbang moderasi yang selalu tertutup bukan karena otorisasi rusak, tetapi karena enum modul tidak pernah dipetakan ke slug konten.
Ringkasan
Jadi masalah lencana read-only di daftar moderasi itu bukan karena permission service rusak, tapi frontend kirim enum huruf besar kayak PARIWISATA padahal backend nyari slug kayak wisata, jadi gagal diam-diam deh. Solusinya dibikin mapping MODULE_TO_SLUG biar enum diubah jadi slug yang bener. Sisi server juga dikasih guardModule yang ngecek kepemilikan dulu, kalau gagal ya langsung 403.
Saat membuka daftar moderasi ulasan di CMS KotaPortal, setiap baris menampilkan lencana read-only. Kondisi ini terjadi meskipun bidang pengguna tersebut secara resmi memiliki kepemilikan penuh atas salah satu modul yang sedang dimoderasi. Antarmuka seolah-olah mengunci akses tanpa alasan yang jelas.
Dugaan awal mengarah pada kerusakan layanan izin atau permission service. Logika yang muncul adalah sistem otorisasi gagal memvalidasi peran pengguna atau terjadi penurunan hak akses secara tiba-tiba di sisi basis data. Tim pengembang sempat memeriksa log autentikasi untuk mencari anomali penurunan hak istimewa yang tidak terduga.
Pemeriksaan lebih lanjut menunjukkan bahwa lapisan belakang berfungsi dengan normal. Masalah sebenarnya terletak pada lapisan depan. Antarmuka mengirimkan nilai enum modul dalam format huruf besar mentah, seperti PARIWISATA, ke gerbang akses yang sebenarnya mengharapkan format slug konten, seperti wisata. Perbandingan antara kedua nilai ini selalu menghasilkan nilai salah dan gagal secara diam-diam, yang akhirnya memaksa antarmuka masuk ke mode read-only sebagai mekanisme pengamanan default.
Ketidakcocokan pengenal yang terjadi antar lapisan adalah penyebab utamanya. Solusi yang diterapkan melibatkan dua langkah konkret untuk menyelaraskan komunikasi data dan menutup celah keamanan tersebut.
Pemetaan Terpusat pada Lapisan Antarmuka
Langkah pertama adalah pembuatan pemetaan terpusat menggunakan utilitas Record di modul Role-Based Access Control (RBAC). Pemetaan MODULE_TO_SLUG bertugas mengonversi enum menjadi slug yang konsisten. Utilitas Record<string, string> di TypeScript memungkinkan pembuatan tipe objek di mana kunci properti adalah Keys dan nilai properti adalah Type [4]. Hal ini memberikan keamanan tipe data pada waktu kompilasi, memastikan setiap enum yang valid memiliki pasangan slug yang sesuai. Jika terdapat enum yang tidak dipetakan, seperti INFORMASI, nilainya akan dipetakan ke string kosong untuk mencegah kebocoran data tidak sengaja.
Penjaga Tingkat Sumber Daya di Sisi Server
Langkah kedua adalah penerapan penjaga tingkat sumber daya atau resource-level guard di sisi server. Fungsi guardModule dirancang untuk memeriksa scope.IsGlobal terlebih dahulu. Selanjutnya, fungsi ini melakukan pencarian modul entitas berdasarkan ID ulasan melalui operasi JOIN sebelum mengizinkan tindakan moderasi apa pun. Operasi JOIN ini menghubungkan tabel ulasan dengan tabel modul untuk memverifikasi kepemilikan bidang secara real-time sebelum eksekusi perintah.
Tindakan seperti Remove, Restore, SetReply, atau ClearReply sepenuhnya diblokir jika validasi gagal. Jika bidang tidak dikenali, sistem akan gagal secara tertutup dengan mengembalikan kode status 403. Prinsip deny-by-default ini memastikan aplikasi tidak tetap netral ketika tidak ada aturan yang cocok, melainkan harus secara eksplisit menolak akses [2]. Kontrol akses yang rusak atau Broken Access Control menempati peringkat sebagai kerentanan keamanan web yang paling mengkhawatirkan dalam OWASP Top 10 tahun 2021 [2].
Validasi otorisasi ini tidak dapat diandalkan hanya melalui pemindaian Dynamic Application Security Testing (DAST) pasif. Pengujian harus dilakukan secara aktif menggunakan uji unit dan uji integrasi untuk memastikan logika gerbang modul berjalan sesuai harapan [1]. Pemindaian pasif tidak akan mampu menangkap logika bisnis yang kompleks seperti pencocokan enum terhadap slug yang bergantung pada keadaan sesi atau hubungan basis data yang spesifik.
Di sisi server, urutan pemeriksaan guardModule berjalan sebelum aksi moderasi mana pun dijalankan: periksa apakah peminta membawa cakupan global, jika tidak ambil modul entitas lewat JOIN berdasarkan id ulasan, lalu bandingkan dengan daftar modul yang boleh dikelola bidang tersebut. Bidang yang tidak dikenal tidak diberi tanggapan netral; permintaan ditolak 403. Empat aksi moderasi melewati jalur yang sama, sehingga tidak ada celah lewat aksi kedua.
Matriks cakupan lalu dikunci lewat uji integrasi: aktor dengan cakupan melihat daftar lintas modul sebagai bacaan, ditolak saat memoderasi baris di luar bidangnya, dan id yang tidak ada dipetakan ke 404 agar keberadaan data di modul lain tidak terbocor. Pola pengujiannya dapat direplikasi: coba aksi tulis dengan aktor ber-cakupan sempit pada modul yang bukan miliknya, lalu pastikan respons 403 dan tidak ada perubahan data.
Proses standarisasi enum slug gerbang modul menjadi fondasi keamanan yang mencegah kegagalan akses diam-diam. Implementasi enum slug gerbang modul yang terstandarisasi memastikan setiap lapisan sistem berbicara dalam bahasa pengenal yang sama, menghilangkan celah yang dapat dieksploitasi atau menyebabkan kebingungan bagi administrator.
Sumber
[1] ZAP Baseline Scan documentation