Unggah berkas yang aman: izin, batas, Signed URL, pemindaian
Unggah berkas yang aman di aplikasi web membutuhkan izin ketat, batas ukuran, Signed URL yang singkat, dan pola pemindaian sederhana untuk menghindari insiden.

Mengapa unggahan berkas berisiko (dalam bahasa sederhana)
Unggahan berkas terlihat tidak berbahaya: foto profil, PDF, spreadsheet. Tapi mereka sering menjadi insiden keamanan pertama karena memungkinkan orang asing mengirim kotak misteri ke sistem Anda. Jika Anda menerimanya, menyimpannya, dan menampilkannya kembali ke orang lain, Anda membuat jalur serangan baru ke aplikasi.
Risikonya bukan hanya “seseorang mengunggah virus.” Unggahan berbahaya bisa membocorkan file pribadi, membengkakkan tagihan penyimpanan, atau menipu pengguna agar memberikan akses. Berkas bernama “invoice.pdf” mungkin bukan PDF sama sekali. Bahkan PDF dan gambar yang asli bisa bermasalah jika aplikasi Anda mempercayai metadata, membuat preview otomatis, atau menyajikannya dengan aturan yang salah.
Kegagalan nyata biasanya seperti ini:
- Seseorang menebak URL berkas dan mengunduh dokumen pengguna lain.
- Berkas HTML yang diunggah disajikan seperti halaman web dan menampilkan prompt pencurian login.
- Penyerang mengunggah berkas-berkas besar berulang kali sampai aplikasi melambat atau crash.
- Tipe berkas “aman” dipalsukan, lalu dibuka staf di mesin internal.
Satu detail yang memicu banyak insiden: menyimpan berkas tidak sama dengan menyajikan berkas. Penyimpanan adalah tempat Anda menyimpan byte. Penyajian adalah cara byte itu dikirim ke browser dan aplikasi. Hal yang salah terjadi ketika aplikasi menyajikan unggahan pengguna dengan tingkat kepercayaan dan aturan yang sama seperti situs utama, sehingga browser memperlakukan unggahan sebagai “terpercaya.”
“Cukup aman” untuk aplikasi kecil atau yang berkembang biasanya berarti Anda bisa menjawab empat pertanyaan tanpa mengada-ada: siapa yang bisa mengunggah, apa yang Anda terima, seberapa besar dan seberapa sering, dan siapa yang bisa membacanya nanti. Bahkan jika Anda membangun cepat (dengan kode yang digenerasi atau platform berbasis chat), pembatas itu tetap penting.
Model ancaman sederhana untuk unggahan
Anggap setiap unggahan sebagai input yang tidak dipercaya. Cara praktis menjaga unggahan aman adalah membayangkan siapa yang mungkin menyalahgunakannya dan seperti apa “keberhasilan” bagi mereka.
Kebanyakan penyerang adalah bot yang memindai form unggah yang lemah atau pengguna nyata yang mendorong batas untuk mendapatkan storage gratis, mengikis data, atau mengganggu layanan Anda. Kadang juga pesaing yang menguji kebocoran atau gangguan.
Apa yang mereka inginkan? Biasanya salah satu hasil ini:
- Menjalankan kode di server Anda dengan mengunggah sesuatu yang dieksekusi.
- Mencuri file privat dengan menebak, memakai ulang, atau membagikan URL unduh.
- Merusak ketersediaan dengan membanjiri unggahan atau memaksa pemrosesan mahal.
- Membengkakkan tagihan Anda lewat pertumbuhan penyimpanan atau unduhan berat bandwidth.
Lalu petakan titik lemah. Endpoint unggah adalah pintu depan (file terlalu besar, format aneh, tingkat permintaan tinggi). Penyimpanan adalah ruang belakang (bucket publik, izin salah, folder bersama). URL unduh adalah jalur keluar (terprediksi, berlaku lama, atau tidak terkait ke pengguna).
Contoh: fitur “unggah resume”. Bot mengunggah ribuan PDF besar untuk menaikkan biaya, sementara pengguna yang menyalahgunakan mengunggah file HTML dan membagikannya sebagai “dokumen” untuk menipu orang lain.
Sebelum Anda menambahkan kontrol, putuskan apa yang paling penting untuk aplikasi Anda: privasi (siapa yang dapat membaca), ketersediaan (bisakah Anda terus menyajikan), biaya (penyimpanan dan bandwidth), dan kepatuhan (di mana data disimpan dan berapa lama disimpan). Daftar prioritas itu menjaga keputusan tetap konsisten.
Izin dan kontrol akses yang benar-benar kuat
Kebanyakan insiden unggahan bukanlah hack yang rumit. Mereka adalah bug sederhana “saya bisa melihat berkas orang lain.” Anggap izin sebagai bagian dari unggahan, bukan fitur yang Anda tambal di kemudian hari.
Mulailah dengan satu aturan: default deny. Anggap setiap objek yang diunggah privat sampai Anda secara eksplisit mengizinkan akses. “Privat secara default” adalah baseline yang kuat untuk invoice, berkas medis, dokumen akun, dan apa pun yang terkait ke pengguna. Buat file publik hanya ketika pengguna benar-benar mengharapkannya (seperti avatar publik), dan bahkan saat itu pertimbangkan akses bertempo.
Peran yang sesuai pekerjaan nyata
Sederhanakan peran dan pisahkan tanggung jawab. Pembagian umum adalah:
- Uploader: bisa membuat unggahan untuk akun mereka sendiri
- Viewer: bisa mengunduh berkas yang diizinkan untuk mereka
- Support: bisa mengakses berkas hanya dengan pemberian akses sementara yang tercatat
- Admin: bisa mengelola kebijakan, tetapi sebaiknya tidak otomatis membaca semuanya
Jangan mengandalkan aturan tingkat folder seperti “apa pun di /user-uploads/ aman.” Periksa kepemilikan atau akses tenant saat baca, untuk setiap berkas. Itu melindungi ketika seseorang pindah tim, keluar dari organisasi, atau berkas dipindah.
Pola support yang baik bersifat sempit dan sementara: berikan akses ke satu berkas tertentu, catat, dan kedaluwarsa otomatis.
Memvalidasi tipe berkas tanpa mengandalkan kepercayaan
Sebagian besar serangan unggahan dimulai dengan trik sederhana: berkas yang terlihat aman karena nama atau header browser, tetapi sebenarnya berbeda. Anggap semua yang dikirim klien tidak dipercaya.
Mulailah dengan allowlist: tentukan format exact yang Anda terima (misalnya .jpg, .png, .pdf) dan tolak sisanya. Hindari “semua gambar” atau “semua dokumen” kecuali Anda benar-benar membutuhkannya.
Jangan percaya ekstensi nama file atau header Content-Type dari klien. Keduanya mudah dipalsukan. Berkas bernama invoice.pdf bisa saja executable, dan Content-Type: image/png bisa bohong.
Pendekatan yang lebih kuat adalah memeriksa byte pertama berkas, sering disebut “magic bytes” atau signature berkas. Banyak format umum punya header konsisten (seperti PNG dan JPEG). Jika header tidak cocok dengan yang Anda izinkan, tolak.
Pengaturan validasi praktis:
- Allowlist ekstensi yang Anda terima (daftar sisi server).
- Deteksi MIME type di server (bukan header dari klien).
- Sniff magic bytes untuk format yang Anda dukung.
- Hasilkan nama penyimpanan acak dan simpan nama asli sebagai metadata.
- Blokir format berisiko kecuali benar-benar perlu, terutama HTML, SVG, dan konten mirip skrip.
Penggantian nama lebih penting daripada kedengarannya. Jika Anda menyimpan nama yang diberikan pengguna secara langsung, Anda mengundang trik path, karakter aneh, dan overwrite yang tidak disengaja. Gunakan ID yang digenerasi untuk penyimpanan dan simpan nama asli hanya untuk tampilan.
Untuk foto profil, terima hanya JPEG dan PNG, verifikasi header, dan hapus metadata jika Anda bisa. Untuk dokumen, pertimbangkan membatasi ke PDF dan menolak apa pun yang memiliki konten aktif. Jika nanti Anda memutuskan membutuhkan SVG atau HTML, perlakukan mereka sebagai potensi eksekusi dan isolasi.
Batas ukuran, rate limit, dan dasar DoS
Kebanyakan outage unggahan bukanlah “trik hacker.” Mereka adalah berkas besar, terlalu banyak permintaan, atau koneksi lambat yang mengikat server sampai aplikasi terasa down. Anggap setiap byte sebagai biaya.
Tetapkan batas ukuran yang efektif
Pilih ukuran maksimum per fitur, bukan satu angka global. Avatar tidak perlu batas yang sama dengan dokumen pajak atau video singkat. Tetapkan batas sekecil yang masih terasa normal, lalu tambahkan jalur “unggah besar” terpisah hanya saat benar-benar perlu.
Terapkan batas di lebih dari satu tempat, karena klien bisa berbohong: di logika aplikasi, pada web server atau reverse proxy, dengan timeout unggah, dan dengan penolakan awal ketika ukuran yang dideklarasikan terlalu besar (sebelum membaca seluruh body).
Contoh konkret: avatar dibatasi 2 MB, PDF dibatasi 20 MB, dan apa pun yang lebih besar memerlukan alur berbeda (seperti direct-to-object-storage dengan signed URL).
Rate limit dan kontrol penyalahgunaan
Bahkan berkas kecil bisa menjadi DoS jika seseorang mengunggahnya berulang-ulang. Tambahkan rate limit pada endpoint unggah per pengguna dan per IP. Pertimbangkan batas lebih ketat untuk traffic anonim daripada pengguna yang masuk.
Unggahan yang dapat dilanjutkan membantu pengguna nyata di jaringan buruk, tapi token sesi harus ketat: masa berlaku singkat, terkait ke pengguna, dan terikat pada ukuran dan tujuan berkas tertentu. Jika tidak, endpoint “resume” menjadi pipa gratis ke storage Anda.
Saat Anda memblokir unggahan, kembalikan error yang jelas ke pengguna (file terlalu besar, terlalu banyak permintaan) tetapi jangan bocorkan internals (stack trace, nama bucket, detail vendor).
Pilihan penyimpanan dan penyajian yang aman
Unggahan aman bukan hanya tentang apa yang Anda terima. Juga tentang ke mana berkas pergi dan bagaimana Anda mengembalikannya nanti.
Jauhkan byte unggahan dari database utama Anda. Kebanyakan aplikasi hanya perlu metadata di DB (owner user ID, nama file asli, tipe terdeteksi, ukuran, checksum, storage key, waktu dibuat). Simpan byte di object storage atau layanan file yang dibuat untuk blob besar.
Pisahkan file publik dan privat di level storage. Gunakan bucket atau container berbeda dengan aturan berbeda. File publik (seperti avatar publik) bisa dibaca tanpa login. File privat (kontrak, invoice, dokumen medis) tidak boleh pernah dapat dibaca publik, bahkan jika seseorang menebak URL.
Hindari menyajikan file pengguna dari domain yang sama dengan aplikasi Anda bila memungkinkan. Jika berkas berisiko lolos (HTML, SVG dengan skrip, atau anomali MIME sniffing browser), men-hostingnya di domain utama bisa mengubahnya menjadi pengambilalihan akun. Domain unduh atau domain storage terpisah membatasi radius kerusakan.
Saat mengunduh, paksa header yang aman. Atur Content-Type yang dapat diprediksi berdasarkan apa yang Anda izinkan, bukan klaim pengguna. Untuk apa pun yang bisa ditafsirkan browser, lebih baik mengirimnya sebagai unduhan.
Beberapa default yang mencegah kejutan:
- Gunakan
Content-Disposition: attachmentuntuk dokumen. - Gunakan
Content-Typeyang aman (atauapplication/octet-stream). - Simpan dan sajikan dengan object key yang opak (bukan nama file pengguna).
- Catat unduhan file privat.
Retensi juga bagian dari keamanan. Hapus unggahan yang ditinggalkan, hapus versi lama setelah diganti, dan tetapkan batas waktu untuk file sementara. Data yang disimpan lebih sedikit berarti lebih sedikit yang bisa bocor.
Signed URL: kapan digunakan dan cara tetap ketat
Signed URL (sering disebut pre-signed URL) adalah cara umum untuk membiarkan pengguna mengunggah atau mengunduh file tanpa membuat bucket storage publik, dan tanpa mengirim setiap byte lewat API Anda. URL membawa izin sementara, lalu kedaluwarsa.
Dua alur umum:
- Direct-to-storage upload: aplikasi Anda mengeluarkan signed URL yang singkat dan browser mengunggah langsung ke object storage.
- Upload-through-server: file melewati API Anda dulu, lalu server yang menyimpannya.
Direct-to-storage mengurangi beban API, tapi membuat aturan storage dan batasan URL lebih penting.
Cara menjaga signed URL tetap ketat
Anggap signed URL seperti kunci sekali pakai. Buat spesifik dan kedaluwarsa cepat.
- Kadaluwarsakan write URL dengan cepat (sering 1–5 menit). Simpan read URL juga dalam hitungan menit, bukan hari.
- Ikat URL ke object key tepat yang diharapkan (satu objek, bukan folder).
- Tambahkan batasan bila didukung: content type yang diharapkan, ukuran maksimum, checksum.
- Terbitkan URL hanya setelah pemeriksaan izin.
- Catat siapa yang meminta URL dan alasannya (user ID, object key, tujuan, IP/user agent).
Pola praktis adalah membuat rekaman unggahan dulu (status: pending), lalu mengeluarkan signed URL. Setelah unggahan, konfirmasi objek ada dan cocok ukuran serta tipenya sebelum menandai siap.
Langkah demi langkah: alur unggah aman yang bisa Anda terapkan
Alur unggah aman kebanyakan adalah aturan jelas dan status yang jelas. Anggap setiap unggahan tidak terpercaya sampai semua pemeriksaan selesai.
Tuliskan apa yang diizinkan tiap fitur. Foto profil dan dokumen pajak sebaiknya tidak berbagi tipe berkas, batas ukuran, atau visibilitas yang sama.
Alur praktis (dengan status nyata)
-
Tetapkan tipe yang diizinkan dan batas ukuran per-fitur (misalnya: foto hingga 5 MB; PDF hingga 20 MB). Terapkan aturan yang sama di backend.
-
Buat “rekaman unggahan” sebelum byte tiba. Simpan: pemilik (user atau org), tujuan (avatar, invoice, attachment), nama file asli, ukuran maks yang diharapkan, dan status seperti
pending. -
Unggah ke lokasi privat. Jangan biarkan klien memilih path akhir.
-
Validasi lagi di server: ukuran, magic bytes/tipe, allowlist. Jika lolos, ubah status menjadi
uploaded. -
Pindai untuk malware dan ubah status menjadi
cleanatauquarantined. Jika pemindaian asinkron, kunci akses sambil menunggu. -
Izinkan unduh, preview, atau pemrosesan hanya ketika status
clean.
Contoh kecil: untuk foto profil, buat rekaman terkait user dan tujuan avatar, simpan secara privat, konfirmasi itu benar JPEG/PNG (bukan hanya bernama seperti itu), pindai, lalu hasilkan URL preview.
Pola pemindaian malware dasar (tanpa berjanji berlebihan)
Pemindaian malware adalah jaring pengaman, bukan janji. Ia menangkap berkas berbahaya yang dikenal dan trik jelas, tapi tidak akan mendeteksi semuanya. Tujuan: kurangi risiko dan buat berkas yang tidak dikenal tidak berbahaya secara default.
Pola andal adalah karantina dulu. Simpan setiap unggahan baru ke lokasi privat dan tandai sebagai pending. Hanya setelah lolos pemeriksaan pindahkan ke lokasi “clean” (atau tandai tersedia).
Pemindaian sinkron hanya bekerja untuk berkas kecil dan traffic rendah karena pengguna menunggu. Kebanyakan aplikasi memindai secara asinkron: terima unggahan, kembalikan status “memproses”, pindai di background.
Apa yang biasanya termasuk dalam “pemindaian dasar”
Pemindaian dasar biasanya engine antivirus (atau layanan) plus beberapa pengaman: pemindaian AV, pemeriksaan tipe berkas (magic bytes), batas pada arsip (zip bomb, zip bersarang, ukuran terkompresi sangat besar), dan pemblokiran format yang tidak perlu.
Jika scanner gagal, timeout, atau mengembalikan “unknown,” anggap berkas mencurigakan. Karantina dan jangan berikan link unduh. Di sinilah tim sering rugi: “scan failed” tidak boleh berubah menjadi “kirim saja.”
Saat Anda memblokir berkas, jaga pesan tetap netral: “Kami tidak dapat menerima berkas ini. Coba berkas lain atau hubungi dukungan.” Jangan klaim mendeteksi malware kecuali Anda yakin.
Contoh: foto profil dan unggahan dokumen di aplikasi tipikal
Pertimbangkan dua fitur: foto profil (ditampilkan publik) dan kwitansi PDF (privat, dipakai untuk tagihan atau dukungan). Keduanya adalah masalah unggahan, tetapi tidak seharusnya berbagi aturan yang sama.
Untuk foto profil, tetap ketat: izinkan hanya JPEG/PNG, batasi ukuran (mis. 2–5 MB), dan lakukan re-encode di server sehingga Anda tidak menyajikan byte asli pengguna. Simpan di storage publik hanya setelah pemeriksaan.
Untuk kwitansi PDF, terima ukuran lebih besar (mis. hingga 20 MB), tetapkan privat secara default, dan hindari merendernya inline dari domain utama aplikasi.
Model status sederhana menjaga pengguna terinformasi tanpa mengekspos internals:
- pending: pengguna memilih berkas, unggahan belum dimulai
- uploaded: storage menerima byte
- scanning: job background sedang memeriksa
- clean (atau rejected): berkas tersedia (atau diblokir)
Signed URL cocok di sini: gunakan signed URL singkat untuk unggah (write-only, satu object key). Terbitkan signed URL baca terpisah yang singkat, dan hanya saat status sudah clean.
Catat apa yang Anda butuhkan untuk investigasi, bukan isi berkas: user ID, file ID, tebakan tipe, ukuran, storage key, timestamp, hasil scan, ID request. Hindari mencatat isi mentah atau data sensitif yang ada di dalam dokumen.
Kesalahan umum dan jebakan mudah
Kebanyakan bug unggahan terjadi karena shortcut “sementara” kecil menjadi permanen. Anggap setiap berkas tidak dipercaya, setiap URL akan dibagikan, dan setiap pengaturan “akan kami perbaiki nanti” akan terlupakan.
Jebakan yang sering muncul:
- Mengandalkan pemeriksaan sisi klien saja. Browser bisa dilewati dalam beberapa detik.
- Membiarkan pengguna memengaruhi path, nama file, atau object key.
- Menjadikan unggahan publik “hanya untuk sesaat.”
- Menggunakan signed URL yang hidup terlalu lama atau berlaku untuk banyak pengguna.
- Menyajikan berkas dengan
Content-Typeyang salah, membiarkan browser menafsirkan konten berisiko.
Monitoring adalah hal yang sering di-skip sampai tagihan storage melonjak. Pantau volume unggahan, ukuran rata-rata, top uploader, dan tingkat error. Satu akun yang dikompromikan bisa diam-diam mengunggah ribuan berkas besar dalam semalam.
Contoh: sebuah tim menyimpan avatar dengan nama file yang diberikan pengguna seperti “avatar.png” di folder bersama. Satu pengguna menimpa gambar orang lain. Perbaikan yang membosankan tapi efektif: buat object key di server, simpan unggahan privat secara default, dan buka gambar yang di-resize melalui respons yang terkontrol.
Daftar periksa cepat dan langkah selanjutnya
Gunakan ini sebagai pemeriksaan akhir sebelum Anda rilis. Anggap setiap item sebagai pemblokir rilis, karena sebagian besar insiden datang dari satu pengaman yang hilang.
Daftar periksa cepat
- Validasi di server dengan allowlist, pemeriksaan konten nyata (bukan hanya nama file), dan batas maksimal keras per berkas.
- Simpan unggahan privat secara default, dan periksa izin setiap kali berkas dibaca, diunduh, atau dipreview.
- Jika menggunakan signed URL, buat singkat hidupnya, scoped ke satu object key, dan catat penerbitannya agar bisa melacak penyalahgunaan.
- Karantina dulu, pindai kemudian: jangan buat preview atau izinkan unduh sampai berkas clean.
- Paksa perilaku unduh yang aman:
Content-Typeyang dapat diprediksi, nama file aman, danattachmentuntuk dokumen.
Langkah selanjutnya yang memberi keuntungan
Tuliskan aturan Anda dalam bahasa sederhana: tipe yang diizinkan, ukuran maksimal, siapa yang bisa mengakses apa, berapa lama signed URL hidup, dan apa arti “scan passed”. Itu menjadi kontrak bersama antara produk, engineering, dan support.
Tambahkan beberapa tes yang menangkap kegagalan umum: berkas oversized, executable yang diganti nama, baca tidak berwenang, signed URL kadaluarsa, dan unduh saat “scan pending”. Tes ini murah dibandingkan insiden.
Jika Anda membangun dan iterasi cepat, gunakan workflow yang memungkinkan merencanakan perubahan dan rollback dengan aman. Tim yang memakai Koder.ai (koder.ai) sering mengandalkan mode perencanaan dan snapshot/rollback saat mengetatkan aturan unggah dari waktu ke waktu, tetapi kebutuhan inti tetap sama: backend menegakkan kebijakan, bukan UI.
Pertanyaan umum
Apa hal minimum yang harus saya lakukan agar unggahan file “cukup aman”?
Mulailah dengan privat secara default dan anggap setiap unggahan sebagai input yang tidak dipercaya. Terapkan empat dasar ini di sisi server:
- Siapa yang bisa mengunggah
- Format berkas yang diterima (allowlist)
- Seberapa besar/seberapa sering (batas ukuran + rate limit)
- Siapa yang bisa membacanya nanti (cek izin per berkas)
Jika Anda bisa menjawab itu dengan jelas, Anda sudah lebih aman daripada kebanyakan kasus insiden.
Mengapa unggahan berkas sering jadi insiden keamanan pertama?
Karena pengguna bisa mengunggah sebuah “kotak misteri” yang aplikasi Anda simpan dan mungkin nanti disajikan ke pengguna lain. Itu bisa menyebabkan:
- Akses tidak sah ke dokumen pribadi
- Phishing atau pengambilalihan akun jika berkas disajikan sebagai konten web yang dipercaya
- Gangguan layanan dan tagihan tinggi dari banjir unggahan atau berkas besar
Jarang sekadar “seseorang mengunggah virus.”
Apa bedanya menyimpan berkas dan menyajikan berkas, dan mengapa itu penting?
Menyimpan berarti menaruh byte di suatu tempat. Menyajikan berarti mengirimkan byte itu ke browser dan aplikasi.
Bahaya muncul ketika aplikasi Anda menyajikan unggahan pengguna dengan tingkat kepercayaan dan aturan yang sama seperti situs utama. Jika berkas berisiko diperlakukan seperti halaman normal, browser bisa mengeksekusinya (atau pengguna bisa terlalu percaya padanya).
Default yang lebih aman: simpan secara privat, lalu sajikan melalui respons unduh yang terkontrol dengan header aman.
Bagaimana cara menghentikan pengguna mengunduh berkas pengguna lain?
Gunakan default deny dan periksa akses setiap kali berkas diunduh atau dipreview.
Aturan praktis:
- Setiap rekaman berkas harus punya pemilik (user/org) dan tujuan (avatar, invoice, dll.)
- Saat baca/unduh, verifikasi peminta berhak untuk berkas itu secara spesifik
- Hindari keamanan berbasis folder seperti “apa pun di /uploads/ aman”
- Buat akses support bersifat sementara dan tercatat (izin satu berkas, kedaluwarsa otomatis)
Sebagian besar bug nyata adalah kesalahan sederhana “saya bisa melihat berkas pengguna lain.”
Bagaimana saya memvalidasi tipe berkas tanpa mempercayai nama file atau Content-Type?
Jangan percaya ekstensi nama file atau Content-Type dari browser. Validasi di server:
- Gunakan allowlist format per fitur (mis. JPEG/PNG untuk avatar, PDF untuk tanda terima)
- Deteksi tipe di sisi server dan periksa magic bytes (signature berkas)
- Ganti nama berkas untuk penyimpanan menggunakan ID acak; simpan nama asli hanya sebagai metadata
- Blokir format berisiko kecuali benar-benar dibutuhkan (HTML, SVG, konten mirip skrip)
Jika byte tidak cocok dengan format yang diizinkan, tolak unggahan.
Batas apa yang harus saya tetapkan untuk mencegah DoS berbasis unggahan?
Karena gangguan biasanya berasal dari penyalahgunaan yang membosankan: terlalu banyak unggahan, berkas sangat besar, atau koneksi lambat yang mengikat sumber daya.
Default yang efektif:
- Tetapkan maks per-fitur (avatar kecil, dokumen lebih besar)
- Terapkan batas di beberapa lapisan (app + reverse proxy + timeouts)
- Tambahkan rate limit per pengguna dan per IP, lebih ketat untuk traffic anonim
Anggap setiap byte sebagai biaya dan setiap permintaan sebagai potensi penyalahgunaan.
Haruskah saya menggunakan signed URL untuk unggahan, dan apa default paling aman?
Ya, tapi lakukan dengan hati-hati. Signed URL membiarkan browser mengunggah/mengunduh langsung ke storage tanpa membuat bucket publik.
Default aman:
- Buat write URL kadaluwarsa singkat (sering 1–5 menit)
- Batasi setiap URL ke satu object key, bukan folder
- Terbitkan URL hanya setelah pemeriksaan izin
- Catat siapa yang meminta URL dan untuk berkas apa
Direct-to-storage mengurangi beban API, tapi scoping dan expiry tidak bisa dinegosiasi.
Apa alur unggah langkah-demi-langkah yang aman yang bisa saya terapkan?
Polanya paling aman adalah:
- Buat rekaman unggahan dengan status
pending - Unggah byte ke lokasi privat
- Validasi ukuran + tipe (magic bytes) di server
- Pindai (biasanya async) dan ubah status ke
cleanatauquarantined - Hanya izinkan unduh/preview saat status
clean
Ini mencegah berkas “scan gagal” atau “sedang diproses” dibagikan secara tidak sengaja.
Apakah saya benar-benar perlu pemindaian malware, dan seperti apa “pemindaian dasar”?
Pemindaian membantu, tapi bukan jaminan. Gunakan sebagai jaring pengaman, bukan satu-satunya kontrol.
Pendekatan praktis:
- Karantina dulu: jangan buka link sampai pemindaian selesai
- Pindai secara asinkron untuk skala; tunjukkan status “memproses” ke pengguna
- Jika pemindaian gagal atau timeout, anggap berkas mencurigakan dan tetap blokir
- Tambahkan pengaman untuk arsip (zip bomb, ukuran terkompresi besar) jika Anda memperbolehkannya
Kuncinya adalah kebijakan: “belum dipindai” tidak boleh berarti “tersedia.”
Bagaimana saya harus menyajikan berkas unggahan dengan aman (header, domain, pengunduhan)?
Sajikan berkas sedemikian rupa agar browser tidak menafsirkannya sebagai halaman web.
Default yang baik:
- Set
Content-Disposition: attachmentuntuk dokumen - Gunakan
Content-Typeaman yang dipilih server (atauapplication/octet-stream) - Gunakan kunci storage opak (bukan nama file pengguna) dalam URL
- Lebih baik gunakan domain unduh terpisah untuk konten pengguna jika memungkinkan
Ini mengurangi risiko berkas unggahan berubah menjadi halaman phishing atau mengeksekusi skrip.