Netlify + Supabase Security
Netlify's build-time environment variable injection and Supabase's anon key model require careful separation. Get it wrong and your service_role key ships to every browser.
Why Netlify + Supabase?
Netlify's broad framework support makes it popular for non-Next.js stacks (SvelteKit, Nuxt, Astro) that use Supabase for backend services. The serverless function model pairs naturally with Supabase's PostgREST API.
Common Vulnerabilities
These are the security issues we find most often in Netlify apps using Supabase.
Build-Time Variable Injection into Client Bundle
Framework-specific public variable prefixes (VITE_, PUBLIC_, NUXT_PUBLIC_) can accidentally expose the service_role key if added to the wrong variable name during Netlify setup.
Netlify Functions Without Auth Verification
Netlify Functions that proxy Supabase requests may not verify the caller is authenticated before executing privileged database operations.
RLS Absent on Tables Accessed Directly
Supabase tables called directly from the browser via the JS client are unprotected without RLS — a common pattern in Netlify-hosted static sites.
Deploy Previews with Unrestricted Supabase Access
Branch deploy previews on Netlify may share the same Supabase credentials as production, giving unreviewed code access to live data.
What We Check for Netlify + Supabase
Public Prefix Audit
Check all environment variables for framework-specific public prefixes (VITE_, PUBLIC_, NUXT_PUBLIC_) to ensure service_role key is not accidentally public.
Netlify Function Auth
Test each Netlify Function that touches Supabase to confirm it validates the user's JWT before executing queries.
RLS Verification
Query all Supabase tables with only the anon key to identify which tables have missing or ineffective RLS policies.
Branch Deploy Isolation
Verify branch deploys do not have access to production Supabase credentials by checking Netlify environment variable scoping.
Quick Security Wins
Apply these fixes right now to improve your security.
In Netlify dashboard, scope SUPABASE_SERVICE_ROLE_KEY to 'Functions' context only — never 'All' or build contextAdd the Supabase anon key under the framework's public prefix (e.g., VITE_SUPABASE_ANON_KEY) and verify service_role is not similarly prefixedEnable RLS on all tables and write user-scoped policies before pointing any Netlify deploy at your Supabase projectIn each Netlify Function: verify the Authorization header JWT with supabase.auth.getUser(token) before any data operationCreate a _headers file with X-Frame-Options: DENY, X-Content-Type-Options: nosniff, and Strict-Transport-SecurityThe Bottom Line
Netlify + Supabase is framework-agnostic and powerful. The service_role key and branch deploy isolation are the two security items that require explicit attention on every project.
Secure Your Netlify + Supabase App
Find Row Level Security misconfigurations, exposed credentials, and other vulnerabilities before attackers do.
Start Security ScanFrequently Asked Questions
How does Netlify's environment variable model differ from Vercel's for Supabase?
Netlify does not automatically distinguish between server and client variables — you control this through framework-specific prefixes (VITE_, NEXT_PUBLIC_, PUBLIC_, etc.). The Supabase service_role key must never be assigned one of these prefixes. Check your netlify.toml or Netlify dashboard for any public prefix on sensitive variables.
How do I secure a Netlify Function that talks to Supabase?
Extract the Authorization header from the incoming request, call supabase.auth.getUser(token) to validate it, and only proceed if it returns a valid user. Use the anon key when you want RLS to apply, or service_role key (server-side only) when you need admin access and handle authorisation yourself.
Can I use Supabase Realtime subscriptions on Netlify-hosted apps?
Yes. Supabase Realtime runs in the browser using the anon key. The subscription respects RLS — users only receive events for rows they are authorised to see. Ensure RLS policies are in place before enabling Realtime, as without them all users receive all row changes.
What is the safest way to use Supabase with an Astro or SvelteKit app on Netlify?
Use server-side rendering with Supabase's SSR helpers. Initialise the server Supabase client with the anon key and the user's cookie/JWT on each request. Keep service_role usage limited to Netlify Functions that absolutely require bypassing RLS, and document each usage clearly.