// docs / baas security / supabase storage
បញ្ជីត្រួតពិនិត្យសុវត្ថិភាព Supabase storage bucket៖ 22 ធាតុ
Supabase Storage គឺជា wrapper ស្ដើងជុំវិញ bucket ដែលត្រូវគ្នាជាមួយ S3 បូកនឹង model Row-Level Security ដូចគ្នានឹង database។ នោះមានន័យថា pitfall RLS ដូចគ្នាដែលប៉ះពាល់ដល់តារាងប៉ះពាល់ដល់ការចូលប្រើឯកសារ — និងពីរបីដែលជាក់លាក់ដល់ storage ដែលលេចឡើងនៅពេលឧបករណ៍សរសេរកូដ AI ភ្ជាប់ការ upload។ បញ្ជីត្រួតពិនិត្យនេះមាន 22 ធាតុនៅទូទាំងផ្នែកប្រាំ៖ ការកំណត់រចនាសម្ព័ន្ធ bucket, RLS policy, ការផ្ទៀងផ្ទាត់ upload, signed URL និងអនាម័យប្រតិបត្តិការ។ មួយៗអាចផ្ទៀងផ្ទាត់បានក្នុងរយៈពេលក្រោម 15 នាទី។
ធាតុនីមួយៗខាងក្រោមគឺចាំបាច់។ សម្រាប់មេកានិច RLS មូលដ្ឋាន, សូមមើល Supabase RLS scanner។ សម្រាប់ថ្នាក់ការបង្ហាញ key ជាប់នឹង storage, សូមមើល Supabase service role key ត្រូវបានបង្ហាញនៅក្នុង JavaScript។
ការកំណត់រចនាសម្ព័ន្ធ bucket
ចាប់ផ្ដើមជាមួយលំនាំដើមត្រឹមត្រូវ។ Bucket ដែលកំណត់រចនាសម្ព័ន្ធខុសធ្វើឱ្យឯកសារលេចធ្លាយ ទោះបី RLS របស់អ្នកត្រឹមត្រូវ ឬមិនត្រឹមត្រូវ។
- កំណត់ bucket នីមួយៗជាឯកជនតាមលំនាំដើម។ នៅក្នុង Supabase Dashboard → Storage → Buckets, កំណត់ toggle Public bucket ទៅ off លុះត្រាតែអ្នកមានហេតុផលច្បាស់លាស់ (asset marketing, avatar សាធារណៈគ្មាន PII)។ Bucket សាធារណៈរំលង RLS សម្រាប់ប្រតិបត្តិការអាន — នរណាក៏ដោយដែលមានឈ្មោះ bucket អាចរាយ និងទាញយក។
- កំណត់ដែនកំណត់ទំហំឯកសាររឹងលើ bucket នីមួយៗ។ Dashboard → ការកំណត់ Bucket → ដែនកំណត់ទំហំឯកសារ។ 50 MB គឺជាលំនាំដើមសមហេតុផលសម្រាប់ការ upload របស់អ្នកប្រើ; បង្កើនវាដោយចេតនាសម្រាប់ករណីប្រើ video / ឯកសារធំ។ ដោយគ្មានដែនកំណត់, ការ upload អាក្រក់មួយអាចបំបាត់កូតា storage ឬ bandwidth ប្រចាំខែរបស់អ្នក។
- រឹតបន្តឹង MIME type ដែលអនុញ្ញាតក្នុង bucket នីមួយៗ។ បញ្ជី MIME type ដែលអនុញ្ញាត — allowlist ច្បាស់លាស់ មិនមែន blocklist។
image/jpeg,image/png,image/webpសម្រាប់ bucket រូបភាពតែប៉ុណ្ណោះ។ មិនត្រូវអនុញ្ញាតtext/html,application/javascriptឬimage/svg+xmlនៅក្នុង bucket មាតិកាអ្នកប្រើឡើយ — ពួកវាដំណើរការនៅក្នុង browser នៅពេលបម្រើតាមរយៈ signed URL។ - ប្រើ 1 bucket ក្នុង 1 content type, មិនមែន 1 bucket រួមឡើយ។ ការកំណត់តាម bucket (ទំហំ, MIME type, RLS policy) គឺជា granularity ដែលអ្នកមាន។ Bucket
user-avatars, bucketdocument-uploadsនិង bucketpublic-assetsគឺងាយចាក់សោជាង bucket លាយតែមួយ។ - ផ្ទៀងផ្ទាត់ការកំណត់រចនាសម្ព័ន្ធ CORS បើ frontend upload។ បើអ្នកប្រើ upload ដោយផ្ទាល់ពី browser ទៅ signed URL, CORS របស់ bucket ត្រូវរាយ origin ផលិតកម្មរបស់អ្នក។
*ទទួលយកបានសម្រាប់ bucket សាធារណៈតែប៉ុណ្ណោះ — មិនដែលសម្រាប់ bucket ដែលមាន PII របស់អ្នកប្រើឡើយ។
RLS policy លើ storage.objects
Supabase Storage រក្សា metadata ឯកសារនៅក្នុងតារាង storage.objects។ RLS លើតារាងនោះគ្រប់គ្រងថានរណាអាចអាន, upload, update ឬលុបឯកសារ។ ដោយគ្មាន RLS, flag សាធារណៈ/ឯកជនរបស់ bucket គឺជាការការពារតែមួយរបស់អ្នក។
- បញ្ជាក់ថា RLS ត្រូវបានបើកលើ storage.objects។
SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects';ត្រូវត្រឡប់true។ Supabase បើកវាតាមលំនាំដើមនៅលើ project ថ្មី; ផ្ទៀងផ្ទាត់ថាវាមិនត្រូវបានបិទ។ - សរសេរ SELECT policy ដែល scoped ទៅ
auth.uid()សម្រាប់ bucket ឯកជន។CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);។ អនុសញ្ញាគឺត្រូវរក្សាឯកសារក្រោម[user-id]/[filename]និងប្រើstorage.foldername()ដើម្បីស្រង់ម្ចាស់ពីផ្លូវ។ - សរសេរ INSERT policy ដែលអនុវត្តអនុសញ្ញាផ្លូវដូចគ្នា។
CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);។ ដោយគ្មាន WITH CHECK, អ្នកប្រើ authenticated អាច upload ទៅក្នុង folder របស់អ្នកប្រើផ្សេង។ - បន្ថែម UPDATE និង DELETE policy បើកម្មវិធីរបស់អ្នកគាំទ្រការកែសម្រួល ឬលុបឯកសារ។ Command នីមួយៗត្រូវការ policy ផ្ទាល់របស់វា។ ការរំលង DELETE មានន័យថាអ្នកប្រើ authenticated មិនអាចលុបឯកសារផ្ទាល់ខ្លួនរបស់ពួកគេ; ការរំលង UPDATE មានន័យថាការសរសេរជាន់លើឯកសារបរាជ័យដោយស្ងៀមស្ងាត់។
- សាកល្បងការចូលប្រើឆ្លងអ្នកប្រើនៅក្នុង browser session ពីរ។ ចូលជាអ្នកប្រើ A, upload ឯកសារ, ចម្លងផ្លូវ។ ចូលជាអ្នកប្រើ B នៅក្នុង browser ផ្សេង, ព្យាយាមទាញឯកសារតាមរយៈ REST API។ Response ត្រូវជា
403ឬ404, មិនដែល200ឡើយ។
-- Confirm RLS on storage.objects
SELECT rowsecurity
FROM pg_tables
WHERE schemaname = 'storage' AND tablename = 'objects';
-- SELECT policy: scope reads to the owning user's folder.
CREATE POLICY "users_read_own_files"
ON storage.objects
FOR SELECT
USING (auth.uid()::text = (storage.foldername(name))[1]);
-- INSERT policy: enforce the [user-id]/[filename] path convention.
CREATE POLICY "users_upload_own"
ON storage.objects
FOR INSERT
WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);ការផ្ទៀងផ្ទាត់ upload
ផ្ទៀងផ្ទាត់រាល់ការ upload server-side សូម្បីពេល bucket មានដែនកំណត់ MIME និងទំហំ។ ឧបករណ៍សរសេរកូដ AI បង្កើតការផ្ទៀងផ្ទាត់ client-only តាមលំនាំដើម; នោះមិនការពារអ្វីឡើយ។
- ត្រួតពិនិត្យ MIME type ឡើងវិញ server-side ពី byte ពិតប្រាកដនៃឯកសារ មិនមែនពី header
Content-Type។ ប្រើ library ដូចជាfile-type(Node) ឬ magic-byte sniffing។ អ្នកវាយប្រហារអាចអះអាងContent-Type: image/jpegលើឯកសារដែលពិតជា payload polyglot HTML / JavaScript។ - ស្រង់ EXIF metadata ចេញពីរូបភាពដែល upload។ EXIF អាចមានកូអរដោនេ GPS, លេខស៊េរីឧបករណ៍ និង timestamp។ ប្រើ
sharpជាមួយ.withMetadata(false)ឬexif-parserដើម្បីស្រង់មុនការផ្ទុក។ - បដិសេធ SVG ដែលមាន tag
scriptឬ handleronload។ SVG គឺជា XML — ហើយកម្មវិធីបង្កើតដោយ AI ច្រើនអនុញ្ញាតការ upload SVG ជា "គ្រាន់តែជារូបភាព"។ ប្រើDOMPurifyserver-side ឬបដិសេធការ upload SVG ទាំងស្រុង។ - ប្រើឈ្មោះឯកសារ deterministic ដែលមិនអាចទាយបាន។ កុំរក្សាឈ្មោះឯកសារដើម។ ប្រើ UUID ឬ hash នៃមាតិកាឯកសារ។ ឈ្មោះឯកសារដើមលេចធ្លាយ ("
passport_scan_2024_01_15.jpg") និងឈ្មោះដែលអាចទាយបានអនុញ្ញាត enumeration។
Signed URL
Signed URL គឺជារបៀបដែល client ចូលប្រើ bucket ឯកជន។ ការផុតកំណត់, scope bucket និងអ្វីដែលត្រូវបាន log មានសារៈសំខាន់។
- កំណត់ការផុតកំណត់ signed-URL លំនាំដើមទៅ 1 ម៉ោង ឬតិចជាងនេះ។
createSignedUrl(path, expiresIn)របស់ Supabase JS SDK យកវិនាទី។ កុំប្រើតម្លៃដូចជា31536000(1 ឆ្នាំ) — URL ក្លាយជា link សាធារណៈពាក់កណ្ដាលជានិច្ច។ - មិនត្រូវរក្សា signed URL នៅក្នុង database របស់អ្នកឡើយ។ បង្កើតថ្មីៗ server-side លើរាល់ request។ Signed URL ដែលរក្សាជាមួយការផុតកំណត់ 1 ឆ្នាំដែលលេចធ្លាយតាមរយៈ database dump ផ្ដល់ការចូលប្រើរយៈពេលវែង។
- Log ការបង្កើត signed-URL, មិនមែនគ្រាន់តែការ upload ឯកសារ។ បើអ្នកសង្ស័យការសម្របសម្រួលនៅពេលក្រោយ, អ្នកត្រូវដឹងថានរណាបានបង្កើត URL ណានៅពេលណា។ Log
auth.uid()+ bucket + ផ្លូវ object + timestamp។ - ប្រើជម្រើស
downloadAsនៅពេលបម្រើឯកសារដែល upload ដោយអ្នកប្រើ។createSignedUrl(path, expiresIn, { download: '.jpg' })បង្ខំ headerContent-Disposition: attachmentដូច្នេះឯកសារទាញយកជំនួសឱ្យការ render — បំបាត់ថ្នាក់ការដំណើរការ HTML / SVG / HTML-in-PDF។
អនាម័យប្រតិបត្តិការ
ការកំណត់រចនាសម្ព័ន្ធ Storage រសាត់តាមពេលវេលា។ ធាតុប្រតិបត្តិការបួននេះរក្សាផ្ទៃឱ្យតឹង។
- ត្រួតពិនិត្យ bucket ប្រចាំត្រីមាស។ Dashboard → Storage → Buckets។ បញ្ជាក់ស្ថានភាពសាធារណៈ/ឯកជន និងបញ្ជី MIME type ត្រូវនឹងអ្វីដែលកម្មវិធីរំពឹង។ Bucket ដែលបង្កើត "បណ្ដោះអាសន្ន" ក្លាយជាអចិន្ត្រៃយ៍បើគ្មាននរណាលុបពួកវា។
- តាមដានប្រតិបត្តិការ list anonymous។ Log Storage (Dashboard → Logs → Storage) កត់ត្រា request
LIST។ Spike នៃ request list anonymous ប្រឆាំងនឹង bucket ឯកជនមានន័យថានរណាម្នាក់កំពុងត្រួតពិនិត្យវាពីខាងក្រៅ។ - កំណត់ policy រក្សាសម្រាប់ការ upload បណ្ដោះអាសន្ន។ Bucket បណ្ដោះអាសន្ន (image preview, draft upload) គួរលុបដោយស្វ័យប្រវត្តិបន្ទាប់ពី 24-72 ម៉ោងតាមរយៈ function កំណត់ពេល។ ការរក្សាគ្មានកំណត់គឺជាការទទួលខុសត្រូវក្រោម GDPR / CCPA កាតព្វកិច្ច data-minimisation។
- ដំណើរការ FixVibe scan ប្រចាំខែ។ ការត្រួតពិនិត្យ
baas.supabase-storage-publicត្រួតពិនិត្យ bucket ដែលឆ្លើយតបទៅនឹងGET+LISTanonymous។ Bucket ថ្មីត្រូវបានបន្ថែម; bucket ចាស់ផ្លាស់ប្ដូរភាពមើលឃើញ — តែការ scan បន្តចាប់រសាត់។
ជំហានបន្ទាប់
ដំណើរការ FixVibe scan ប្រឆាំងនឹង URL ផលិតកម្មរបស់អ្នក — បញ្ជី storage anonymous លេចឡើងក្រោម baas.supabase-storage-public។ ផ្គូបញ្ជីត្រួតពិនិត្យនេះជាមួយ Supabase RLS scanner សម្រាប់ layer តារាង និង Supabase service role key ត្រូវបានបង្ហាញនៅក្នុង JavaScript សម្រាប់ការជាប់ការបង្ហាញ key។ សម្រាប់ការកំណត់រចនាសម្ព័ន្ធខុសរបស់ storage នៅទូទាំង BaaS provider ផ្សេងទៀត, សូមមើល BaaS misconfiguration scanner។
