[{"data":1,"prerenderedAt":272},["ShallowReactive",2],{"blog-checklists/supabase-security-checklist":3},{"id":4,"title":5,"body":6,"category":249,"date":250,"dateModified":250,"description":251,"draft":252,"extension":253,"faq":254,"featured":252,"headerVariant":257,"image":258,"keywords":258,"meta":259,"navigation":260,"ogDescription":261,"ogTitle":258,"path":262,"readTime":258,"schemaOrg":263,"schemaType":264,"seo":265,"sitemap":266,"stem":267,"tags":268,"twitterCard":270,"__hash__":271},"blog/blog/checklists/supabase-security-checklist.md","Supabase Security Checklist: 24-Item Guide for RLS and Beyond",{"type":7,"value":8,"toc":244},"minimark",[9,16,19,22,46,72,75,86,105,124,127,133,152,168,183,188,191,213,232],[10,11,12],"tldr",{},[13,14,15],"p",{},"Enable RLS on every table. Write policies for SELECT, INSERT, UPDATE, DELETE. Keep the service role key server-side only. Configure storage bucket policies. This 24-item checklist covers all Supabase security essentials. 7 critical items must be fixed before launch, 10 important items within the first week, and 7 recommended items when you can.",[13,17,18],{},"Supabase gives you a Postgres database with a direct API, which is powerful but means misconfigured RLS can expose your entire dataset to the internet. I have seen too many projects ship with RLS disabled \"temporarily\" and forget about it. Walk through each item here, especially if you set up your tables in a hurry.",[20,21],"print-button",{},[23,24,26,29,34,38,42],"checklist-section",{"title":25},"Quick Checklist (5 Critical Items)",[13,27,28],{},"::checklist-item{label=\"RLS enabled on ALL tables\" description=\"Check each table - \"RLS Enabled\" should be green\"}\n::",[30,31],"checklist-item",{"description":32,"label":33},"Service role bypasses RLS - only use server-side","service_role key NEVER in browser",[30,35],{"description":36,"label":37},"Users should only see their own data","SELECT policies defined for all tables",[30,39],{"description":40,"label":41},"Compare user_id column with auth.uid() for ownership","Policies use auth.uid() correctly",[30,43],{"description":44,"label":45},"Search for your Supabase project URL in code","No keys hardcoded in source code",[23,47,50,53,57,61,65,69],{"title":48,"count":49},"Row Level Security (RLS)","6",[13,51,52],{},"::checklist-item{label=\"RLS enabled on ALL tables\" description=\"Check each table in Supabase dashboard - \"RLS Enabled\" should be green. How to set up Supabase RLS\"}\n::",[30,54],{"description":55,"label":56},"Users should only see their own data unless intentionally public. How to write RLS policies","SELECT policies defined",[30,58],{"description":59,"label":60},"Verify user can only insert records for themselves. How to write RLS policies","INSERT policies defined",[30,62],{"description":63,"label":64},"Users can only update their own records. How to write RLS policies","UPDATE policies defined",[30,66],{"description":67,"label":68},"Users can only delete their own records. How to write RLS policies","DELETE policies defined",[30,70],{"description":71,"label":41},"Compare user_id column with auth.uid() for ownership checks. How to test RLS policies",[13,73,74],{},"Example RLS policy for user-owned data:",[76,77,82],"pre",{"className":78,"code":80,"language":81},[79],"language-text","-- Users can only see their own profiles\nCREATE POLICY \"Users can view own profile\"\nON profiles FOR SELECT\nUSING (auth.uid() = user_id);\n\n-- Users can only update their own profile\nCREATE POLICY \"Users can update own profile\"\nON profiles FOR UPDATE\nUSING (auth.uid() = user_id);\n","text",[83,84,80],"code",{"__ignoreMap":85},"",[23,87,90,94,97,101],{"title":88,"count":89},"API Keys","4",[30,91],{"description":92,"label":93},"The anon/public key is safe for client-side use WITH RLS enabled. How to separate client/server keys","anon key used in browser",[30,95],{"description":96,"label":33},"Service role bypasses RLS - only use server-side. How to protect service role key",[30,98],{"description":99,"label":100},"Store in .env.local (not committed) or hosting platform secrets. How to configure env variables","service_role key in environment variables",[30,102],{"description":103,"label":104},"Search for your Supabase project URL to find any hardcoded keys. How to secure API keys","No keys in source code",[23,106,108,112,116,120],{"title":107,"count":89},"Storage Buckets",[30,109],{"description":110,"label":111},"Each storage bucket should have appropriate access policies. How to configure storage policies","Bucket policies configured",[30,113],{"description":114,"label":115},"Only make buckets public if the content should be world-readable. How to configure public buckets","Public buckets are intentionally public",[30,117],{"description":118,"label":119},"Restrict uploads to expected file types (images, documents, etc.). How to secure file uploads","File type restrictions",[30,121],{"description":122,"label":123},"Set maximum file size to prevent abuse. How to set file size limits","File size limits",[13,125,126],{},"Example storage policy:",[76,128,131],{"className":129,"code":130,"language":81},[79],"-- Users can upload to their own folder\nCREATE POLICY \"Users can upload own files\"\nON storage.objects FOR INSERT\nWITH CHECK (\n  bucket_id = 'avatars' AND\n  auth.uid()::text = (storage.foldername(name))[1]\n);\n",[83,132,130],{"__ignoreMap":85},[23,134,136,140,144,148],{"title":135,"count":89},"Authentication",[30,137],{"description":138,"label":139},"Require email verification before account access. How to configure email confirmation","Email confirmations enabled (if needed)",[30,141],{"description":142,"label":143},"Configure minimum password requirements in Auth settings. How to set password requirements","Password strength requirements",[30,145],{"description":146,"label":147},"Redirect URLs and scopes properly configured. How to configure OAuth","OAuth providers configured securely",[30,149],{"description":150,"label":151},"Balance security (shorter) vs UX (longer) for token expiry. How to configure JWT expiry","JWT expiry configured",[23,153,156,160,164],{"title":154,"count":155},"Edge Functions","3",[30,157],{"description":158,"label":159},"Check Authorization header and verify JWT in Edge Functions. How to verify JWT in Edge Functions","Functions verify JWT",[30,161],{"description":162,"label":163},"Only allow requests from your domains. How to configure CORS","CORS configured properly",[30,165],{"description":166,"label":167},"Validate and sanitize all input to Edge Functions. How to validate on server","Input validation in functions",[23,169,171,175,179],{"title":170,"count":155},"Database",[30,172],{"description":173,"label":174},"Check API settings for which schemas are exposed. How to manage schema exposure","No public schemas exposed unnecessarily",[30,176],{"description":177,"label":178},"Use column grants or views to hide sensitive fields. How to hide sensitive columns","Sensitive columns excluded from API",[30,180],{"description":181,"label":182},"Pro plan includes Point-in-Time Recovery. How to configure backups","Database backups enabled",[184,185,187],"h2",{"id":186},"how-to-use-this-checklist","How to Use This Checklist",[13,189,190],{},"Go through each item before deploying your Supabase project. If you find an issue, fix it before moving on. Use the Supabase Dashboard's \"API Docs\" to test your RLS policies. Try accessing data as different users to verify policies work correctly.",[192,193,194,201,207],"faq-section",{},[195,196,198],"faq-item",{"question":197},"What is Row Level Security (RLS) in Supabase?",[13,199,200],{},"Row Level Security is a PostgreSQL feature that allows you to control which rows a user can access. In Supabase, RLS policies ensure users can only read, insert, update, or delete rows they're authorized to access based on their authentication status.",[195,202,204],{"question":203},"What's the difference between anon key and service role key?",[13,205,206],{},"The anon key is safe for browser use and respects RLS policies. The service role key bypasses all RLS and should ONLY be used server-side. Never expose the service role key in client-side code.",[195,208,210],{"question":209},"Do I need RLS if I only access Supabase from the server?",[13,211,212],{},"Yes. Even with server-only access, RLS provides defense in depth. If your server-side code has a bug or vulnerability, RLS can prevent unauthorized data access. It's an important security layer.",[214,215,216,222,227],"related-articles",{},[217,218],"related-card",{"description":219,"href":220,"title":221},"Complete security guide for Supabase projects","/blog/guides/supabase","Supabase Security Guide",[217,223],{"description":224,"href":225,"title":226},"Step-by-step guide to hiding your keys","/blog/how-to/secure-api-keys","How to Secure API Keys",[217,228],{"description":229,"href":230,"title":231},"15 items to check before deploying","/blog/checklists/cursor-security-checklist","Cursor Security Checklist",[233,234,237,241],"cta-box",{"href":235,"label":236},"/","Start Free Scan",[184,238,240],{"id":239},"automate-this-checklist","Automate This Checklist",[13,242,243],{},"Our scanner checks all these items automatically and catches issues you might miss.",{"title":85,"searchDepth":245,"depth":245,"links":246},2,[247,248],{"id":186,"depth":245,"text":187},{"id":239,"depth":245,"text":240},"checklists","2026-02-06","Complete 24-item Supabase security checklist covering Row Level Security, API key handling, storage rules, and database security. Essential for vibe coders.",false,"md",[255,256],{"question":197,"answer":200},{"question":203,"answer":206},"green",null,{},true,"Complete Supabase security checklist. RLS policies, API keys, storage, and more.","/blog/checklists/supabase-security-checklist","[object Object]","HowTo",{"title":5,"description":251},{"loc":262},"blog/checklists/supabase-security-checklist",[269],"Security Checklist","summary_large_image","aB0PhehE7uPif_d0bog5UImAExsTIzgVTDPe4QEzLlw",1775843930560]