// docs / baas security / supabase storage
Supabase storage bucket-ի անվտանգության ստուգաթերթ․ 22 կետ
Supabase Storage-ը S3-համատեղելի bucket-ի բարակ թաղանթ է գումարած նույն Row-Level Security մոդելը, ինչ որ տվյալների բազան։ Դա նշանակում է, որ նույն RLS թակարդները, որոնք ազդում են table-ների վրա, ազդում են ֆայլերի մուտքի վրա — և մի քանի storage-specific թակարդներ, որոնք ի հայտ են գալիս, երբ AI-ի կոդավորման գործիքները լարում են upload-ները։ Այս ստուգաթերթը 22 կետ է հինգ բաժնում․ bucket-ի կարգավորում, RLS policy-ներ, upload-ի վավերացում, signed URL-ներ, և գործառնական հիգիենա։ Յուրաքանչյուրն ստուգելի է 15 րոպեից պակաս ժամանակում։
Ստորև յուրաքանչյուր կետ էական է։ Հիմքում ընկած RLS մեխանիզմների համար տես Supabase RLS սկաներ։ Storage-ին հարակից բանալու-բացահայտման դասի համար տես Supabase service role key-ը բացահայտված JavaScript-ում։
Bucket-ի կարգավորում
Սկսիր ճիշտ լռելյայններից։ Սխալ կարգավորված bucket-ը արտահոսում է ֆայլեր՝ անկախ նրանից, թե քո RLS-ը ճիշտ է, թե ոչ։
- Լռելյայն դարձրու յուրաքանչյուր bucket մասնավոր։ Supabase Dashboard → Storage → Buckets-ում, Public bucket toggle-ը դարձրու անջատված, քանի դեռ չունես հստակ պատճառ (մարքեթինգային ակտիվներ, հանրային avatar-ներ առանց PII)։ Հանրային bucket-ները շրջանցում են RLS-ը ընթերցման գործողությունների համար — ցանկացած ոք bucket-ի անունով կարող է թվարկել և ներբեռնել։
- Սահմանիր ֆայլի չափի կոշտ սահման յուրաքանչյուր bucket-ի վրա։ Dashboard → Bucket settings → File size limit։ 50 MB-ը ողջամիտ լռելյայն է օգտատերերի upload-ների համար. գիտակցորեն բարձրացրու վիդեո / մեծ ֆայլի օգտագործման դեպքերի համար։ Առանց սահմանի, մեկ վնասակար upload-ը կարող է սպառել քո storage quota-ն կամ քո ամսական bandwidth-ը։
- Սահմանափակիր թույլատրված MIME-տիպերը bucket-ի համար։ Allowed MIME types ցուցակ — բացահայտ allowlist, ոչ blocklist։
image/jpeg,image/png,image/webpմիայն-պատկեր bucket-ների համար։ Երբեք չթույլատրեսtext/html,application/javascriptկամimage/svg+xmlօգտատերերի-բովանդակության bucket-ում — դրանք գործարկվում են զննարկիչում, երբ սպասարկվում են signed URL-ի միջոցով։ - Օգտագործիր մեկ bucket մեկ բովանդակության տեսակի համար, ոչ թե մեկ ընդհանուր bucket։ Bucket-ի կարգավորումները (չափ, MIME-տիպեր, RLS policy-ներ) գրանուլյարությունն են, որ ունես։
user-avatarsbucket-ը,document-uploadsbucket-ը ևpublic-assetsbucket-ը ավելի հեշտ է փակել, քան մեկ խառը bucket։ - Ստուգիր CORS կարգավորումը, եթե ֆրոնտէնդը upload է անում։ Եթե օգտատերերն ուղղակիորեն upload են անում զննարկիչից signed URL-ին, bucket-ի CORS-ը պետք է թվարկի քո production origin-ը։
*-ը ընդունելի է միայն հանրային bucket-ների համար — երբեք օգտատերերի PII պարունակող bucket-ների համար։
RLS policy-ներ storage.objects-ի վրա
Supabase Storage-ը պահում է ֆայլերի մետատվյալները storage.objects table-ում։ RLS-ն այդ table-ի վրա վերահսկում է, թե ով կարող է կարդալ, upload անել, թարմացնել կամ ջնջել ֆայլեր։ Առանց RLS-ի, bucket-ի public/private flag-ն քո միակ պաշտպանությունն է։
- Հաստատիր, որ RLS-ը միացված է storage.objects-ի վրա։
SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects';պետք է վերադարձնիtrue։ Supabase-ն այն լռելյայն միացնում է նոր նախագծերում. ստուգիր, որ այն չի անջատվել։ - Գրիր SELECT policy, որ սահմանված է
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-ի, վավերացված օգտատերը կարող է upload անել մեկ այլ օգտատիրոջ թղթապանակ։ - Ավելացրու UPDATE և DELETE policy-ներ, եթե քո հավելվածն աջակցում է ֆայլի խմբագրումներ կամ ջնջումներ։ Յուրաքանչյուր հրաման ունի իր սեփական policy-ի կարիքը։ DELETE-ը բաց թողնելը նշանակում է, որ վավերացված օգտատերերը չեն կարող հեռացնել իրենց սեփական ֆայլերը. UPDATE-ը բաց թողնելը նշանակում է, որ ֆայլի վերագրումներն լուռ ձախողվում են։
- Ստուգիր օգտատերերի միջև մուտքը երկու զննարկչի սեսիաներում։ Մուտք գործիր որպես Օգտատեր Ա, upload արա ֆայլ, պատճենիր ուղին։ Մուտք գործիր որպես Օգտատեր Բ մեկ այլ զննարկչում, փորձիր ֆայլը ստանալ REST API-ի միջոցով։ Պատասխանը պետք է լինի
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 սերվերային կողմից, նույնիսկ երբ bucket-ը MIME-ի և չափի սահմանափակումներ ունի։ AI-ի կոդավորման գործիքները լռելյայն գեներացնում են միայն-հաճախորդի վավերացում. դա ոչինչ չի պաշտպանում։
- Կրկին ստուգիր MIME տիպը սերվերային կողմից ֆայլի փաստացի բայթերից, ոչ թե
Content-Typeheader-ից։ Օգտագործիր գրադարան՝file-type(Node) կամ magic-byte sniffing-ը։ Հարձակվողը կարող է հայտարարելContent-Type: image/jpegայնպիսի ֆայլի վրա, որ իրականում polyglot HTML / JavaScript payload է։ - Հանիր EXIF մետատվյալները upload արված պատկերներից։ EXIF-ը կարող է պարունակել GPS կոորդինատներ, սարքի սերիական համարներ և ժամանակացույցեր։ Օգտագործիր
sharp.withMetadata(false)-ով կամexif-parser՝ պահելուց առաջ հանելու համար։ - Մերժիր SVG-ները, որոնք պարունակում են
scripttag-եր կամonloadhandler-ներ։ SVG-ն XML է — և շատ AI-գեներացված հավելվածներ թույլ են տալիս SVG upload-ներ որպես «պարզապես պատկեր»։ ՕգտագործիրDOMPurifyսերվերային կողմից կամ ընդհանրապես հրաժարվիր SVG upload-ից։ - Օգտագործիր որոշակիորեն չկռահելի ֆայլերի անուններ։ Մի պահպանիր սկզբնական ֆայլի անունը։ Օգտագործիր UUID կամ ֆայլի բովանդակության hash։ Սկզբնական ֆայլի անունները արտահոսում են («
passport_scan_2024_01_15.jpg») և կանխատեսելի անունները հնարավորություն են տալիս թվարկման։
Signed URL-ներ
Signed URL-ները այն են, ինչպես հաճախորդները մուտք են ունենում մասնավոր bucket-ներին։ Ժամկետի սպառումը, bucket-ի շրջանակը և թե ինչ է գրառվում՝ կարևոր է։
- Լռելյայն signed-URL ժամկետը 1 ժամ կամ պակաս դարձրու։ Supabase JS SDK-ի
createSignedUrl(path, expiresIn)-ը վերցնում է վայրկյաններ։ Երբեք մի օգտագործիր այնպիսի արժեքներ, ինչպիսին31536000-ն է (մեկ տարի) — URL-ը դառնում է մշտական կիսա-հանրային հղում։ - Երբեք մի պահպանիր signed URL-ները քո տվյալների բազայում։ Գեներացրու թարմ URL-ներ սերվերային կողմից յուրաքանչյուր հարցման ժամանակ։ Պահպանված signed URL՝ 1 տարի ժամկետով, որ արտահոսում է տվյալների բազայի dump-ի միջոցով, շնորհում է երկարատև մուտք։
- Գրառիր signed-URL-ի գեներացումը, ոչ միայն ֆայլի upload-ները։ Եթե հետագայում կասկածում ես կոմպրոմիսի, պետք է իմանաս, թե ով է գեներացրել որ URL-ը երբ։ Գրառիր
auth.uid()+ bucket + object ուղի + ժամանակացույց։ - Օգտագործիր
downloadAsտարբերակը, երբ սպասարկում ես օգտատերերի upload արած ֆայլեր։createSignedUrl(path, expiresIn, { download: '.jpg' })-ը պարտադրում էContent-Disposition: attachmentheader, որպեսզի ֆայլը ներբեռնվի՝ ռենդրման փոխարեն — հաղթահարում է HTML / SVG / HTML-in-PDF գործարկման դասը։
Գործառնական հիգիենա
Storage-ի կարգավորումը ժամանակի ընթացքում շեղվում է։ Այս չորս գործառնական կետերը մակերեսը պահում են ամուր։
- Աուդիտ արա bucket-ները եռամսյակային։ Dashboard → Storage → Buckets։ Հաստատիր, որ public/private վիճակը և MIME-տիպերի ցուցակները համապատասխանում են այն բանին, ինչ հավելվածն ակնկալում է։ «Ժամանակավորապես» ստեղծված bucket-ները դառնում են մշտական, եթե ոչ ոք չհանի դրանք։
- Հետևիր անանուն list գործողություններին։ Storage log-երը (Dashboard → Logs → Storage) գրառում են
LISTհարցումները։ Անանուն list հարցումների աճ մասնավոր bucket-ի դեմ նշանակում է, որ ինչ-որ մեկը այն ստուգում է դրսից։ - Սահմանիր պահպանման policy անցողիկ upload-ների համար։ Ժամանակավոր bucket-ները (պատկերի նախադիտում, սևագիր upload-ներ) պետք է ինքնաջնջվեն 24-72 ժամ հետո՝ պլանավորված ֆունկցիայի միջոցով։ Անժամկետ պահպանումը պարտավորություն է GDPR / CCPA տվյալների-նվազեցման պարտավորությունների ներքո։
- Գործարկիր FixVibe սկան ամսական։
baas.supabase-storage-publicստուգումը ստուգում է bucket-ները, որոնք պատասխանում են անանունGET+LIST-ին։ Նոր bucket-ներ ավելանում են. հները փոխում են տեսանելիությունը — միայն շարունակական սկանավորումը գտնում է շեղումը։
Հաջորդ քայլեր
Գործարկիր FixVibe սկան քո production URL-ի դեմ — անանուն storage listings հայտնվում են baas.supabase-storage-public-ի տակ։ Զուգակցիր այս ստուգաթերթը Supabase RLS սկաներ-ի հետ table շերտի համար և Supabase service role key-ը բացահայտված JavaScript-ում-ի հետ՝ բանալու-բացահայտման հարակցության համար։ Այլ BaaS մատակարարների storage-ի սխալ կարգավորումների համար տես BaaS սխալ կարգավորման սկաներ։
