Menguji Broken Object-Level Authorization pada API
Keputusan kepemilikan di batas data
Review BOLA dimulai ketika record dipilih. Buat fixture dua tenant dengan role setara, lalu daftar identifier pada path, query string, body request, cursor, field relasi, dan payload job asinkron. Misalnya, request ekspor dapat menolak /reports/beta dengan benar tetapi menerima { "reportId": "beta" } pada body bulk bila filter repository hilang. Uji panggilan baca, ubah, hapus, unduh, dan status job secara terpisah.
Output yang diharapkan bukan hanya 403 atau 404. Kumpulkan jumlah baris, pembuatan file, panggilan processor, event yang dipancarkan, dan perilaku cache. 404 dapat diterima bila kebijakan disclosure memilihnya; hasil itu gagal bila perbedaan ukuran respons, file yang dibuat, atau endpoint status membocorkan data tenant B. Worker queue harus membawa konteks tenant dan subjek yang tepercaya, kemudian memeriksanya ulang sebelum memproses, bukan mempercayai request lama yang diserialkan.
Penutupan temuan BOLA berarti mengubah lookup agar predicate tenant dan identitas objek tidak dapat dipisahkan, atau memanggil kebijakan bersama sebelum lookup. Owner uji mencatat request ID asing, penolakan yang diharapkan, state yang terlihat, referensi patch, dan retest dengan sesi baru. Pengecualian seperti akuntan delegasi membutuhkan hubungan delegasi terdokumentasi dan tanggal berakhir; pengecualian tidak boleh menjadi role lintas-tenant yang luas.
Gunakan satu objek fixture untuk setiap tenant dan jangan menebak identifier produksi. Uji UUID asing harus mencakup response cache dan URL unduhan karena lookup utama yang benar dapat diikuti fetch sekunder yang lemah. Bila endpoint menerima array, campurkan ID milik sendiri dan asing lalu tetapkan apakah item valid boleh berjalan atau seluruh request gagal. Bukti harus membuktikan perilaku yang dipilih. Setelah perubahan kode, periksa SQL yang dihasilkan atau predicate repository untuk memastikan filter tenant tetap terpasang pada setiap cabang.
Penutupan akses objek
Buat fixture ketika tenant merah dan tenant biru memiliki invoice, file, report job, serta objek anak yang identik. Kirim identifier asing pada path, body, query, relasi bertingkat, cursor, dan array bulk. Periksa total list serta cursor pagination seteliti payload item; jumlah atau timing dapat membocorkan keberadaan record. Route unduhan harus mengotorisasi ulang saat membuat signed URL, bukan mewarisi keputusan list sebelumnya.
Untuk request ID asing yang gagal, amati jumlah baris database, lookup object storage, enqueue queue, cache key, dan event audit. Hasil dapat 403 atau 404 menurut kebijakan disclosure, tetapi tidak boleh memuat konten asing atau efek downstream. Payload worker harus membawa konteks otorisasi stabil dan memeriksa ulang keanggotaan saat job berjalan karena delegasi dapat berubah antara enqueue dan eksekusi.
Perbaiki akses objek dengan mengikat predicate tenant ke lookup atau memanggil policy memakai subjek tepercaya sebelum load. Retest dengan sesi baru dan jalur klien yang cached. Akses delegasi dapat diterima hanya bila relasi memiliki owner, scope, dan expiry; keanggotaan “support” luas bukan pengganti kebijakan objek.
Referensi tidak langsung dan cache
Graf objek menciptakan referensi tidak langsung. Pengguna dapat berhak atas order, tetapi tidak otomatis atas setiap lampiran, metode pembayaran, atau job anak yang dapat dijangkau dari order tersebut. Uji penggantian parent dan child secara terpisah. Encoding cursor harus diperlakukan sebagai input opaque, bukan bukti bahwa pemanggil pernah melihat koleksi. Cache key wajib memuat dimensi tenant atau subjek yang relevan terhadap otorisasi; jika tidak, fetch yang diizinkan dapat menanam respons untuk tenant lain. Untuk unduhan bertanda tangan, gunakan expiry pendek dan otorisasi ulang ketika tautan diterbitkan; jangan membuka bucket key hanya karena halaman sebelumnya menampilkan nama file.
Kasus ekspor lintas tenant
Siapkan invoice tenant merah dan tenant biru dengan nilai yang berbeda. Jalankan POST /exports memakai invoice merah sebagai kontrol, lalu kirim invoice biru pada path, body JSON, dan daftar bulk. Setiap variasi asing harus berhenti sebelum query ekspor, pembuatan file, enqueue worker, atau panggilan storage. Periksa count hasil, audit trail, cache, serta endpoint status job. Bila desain memilih 404, ukuran respons dan waktu proses tidak boleh membedakan objek yang benar-benar tidak ada dari objek tenant lain. Bukti penutupan memuat predicate repository atau keputusan policy, capture tiga request, dan retest setelah sesi baru diterbitkan.
Pemeriksaan repository dan worker
Review kode pada lokasi objek dimuat, bukan hanya middleware controller. Query repository perlu menggabungkan predicate tenant dan objek, misalnya memilih invoice dengan invoice_id serta konteks tenant tepercaya. Lapisan policy dapat memutuskan lebih dahulu, tetapi lazy load dan lookup file berikutnya harus mempertahankan konteks sama. Instrumentasikan environment test untuk mencatat pembacaan storage dan enqueue queue; 404 yang masih menyentuh objek ekspor asing tidak bersih.
Negatif yang berdekatan juga penting. Setelah invoice asing ditolak, coba ID lampiran asing di bawah invoice milik sendiri, cursor asing setelah halaman valid, dan polling job yang dibuat tenant lain. Respons tidak boleh membuka URL file maupun progres job. Lalu verifikasi objek sendiri tetap tersedia setelah cache diinvalidasi. Langkah ini membedakan enforcement tenancy yang disengaja dari cache miss kebetulan.
Delegasi adalah relasi objek eksplisit. Uji awal, expiry, dan pencabutannya. Akuntan delegasi boleh membaca ledger yang disebut untuk tenant yang disebut, tetapi tidak mewarisi akses metode pembayaran atau administrasi akun. Bukti mencatat ID relasi, keputusan policy, waktu expiry, dan request setelah pencabutan.
Ledger uji objek asing
| Substitusi objek | Owner | Bukti | Hasil yang diharapkan | Hasil teramati / status | Pengecualian | Penutupan |
|---|---|---|---|---|---|---|
Tenant Merah meminta invoice Tenant Biru inv-blue-02 lewat body POST /exports | Owner otorisasi data | Capture BOLA-118; trace SQL memuat tenant_id=red; counter storage dan queue | 404 tanpa row asing, file, job, atau entri cache | 404; row 0; pembacaan storage 0; job 0 — ditutup | Tidak ada | Retest sesi baru dan bulk campuran lulus; patch SEC-381 diterima 2026-06-10 |