Bolt.new + Supabase Security Blueprint

Share

To secure a Bolt.new + Supabase stack, you need to: (1) verify RLS is enabled on all tables after exporting from Bolt, (2) ensure only the anon key is used in client code while the service_role key stays server-side, (3) review authentication flows for proper session handling, and (4) add explicit user ID checks to data queries. This blueprint covers post-export security tasks with color-coded guidance for each platform.

Setup Time1-2 hours

TL;DR

Bolt.new generates full-stack apps rapidly, but often skips Supabase security configuration. Critical issues: RLS is frequently disabled or misconfigured, service_role keys may be exposed in client code, and authentication flows often lack proper session handling. After exporting from Bolt, immediately configure RLS policies, verify key usage, and add auth checks to any server-side code.

Bolt.new Security Considerations

Bolt.new generates working apps quickly, but security requires post-generation review:

What Bolt Does WellWhat Needs Review
Generates working Supabase client setupRLS policies may be missing or permissive
Creates authentication UISession handling may be incomplete
Scaffolds CRUD operationsAuthorization checks often missing
Sets up environment variablesMay expose service_role key

Part 1: Check Supabase RLS Configuration

Verify RLS is Enabled

After exporting your Bolt project, check Supabase dashboard:

SQL to check RLS status
-- Run in Supabase SQL Editor
SELECT
  schemaname,
  tablename,
  rowsecurity
FROM pg_tables
WHERE schemaname = 'public';

-- If rowsecurity is 'false', enable it:
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;

Add Proper RLS Policies

Common RLS policies for Bolt apps
-- User profiles: only owner can access
CREATE POLICY "Users can view own profile"
  ON profiles FOR SELECT
  USING (auth.uid() = id);

CREATE POLICY "Users can update own profile"
  ON profiles FOR UPDATE
  USING (auth.uid() = id);

-- User's items: full access to own data
CREATE POLICY "Users can manage own items"
  ON items FOR ALL
  USING (auth.uid() = user_id);

-- Public read, authenticated write
CREATE POLICY "Anyone can read posts"
  ON posts FOR SELECT
  USING (true);

CREATE POLICY "Authenticated users can create posts"
  ON posts FOR INSERT
  WITH CHECK (auth.uid() = author_id);

Bolt often generates: allow read, write: if true equivalent policies or skips RLS entirely. Always verify before deploying.

Part 2: Supabase API Key Security

Check Key Usage in Generated Code

Search your exported code for key usage:

Search for potential key exposure
# In your exported project directory
grep -r "service_role" .
grep -r "supabase" . --include="*.ts" --include="*.js"

# Look for hardcoded keys
grep -r "eyJ" . --include="*.ts" --include="*.js"

Correct Key Setup

lib/supabase.ts - Safe client setup
import { createClient } from '@supabase/supabase-js'

// Only use anon key in client code
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY

export const supabase = createClient(supabaseUrl, supabaseAnonKey)

// NEVER do this in client code:
// const supabase = createClient(url, process.env.SUPABASE_SERVICE_ROLE_KEY)

Part 3: Authentication Flow

Verify Session Handling

Bolt-generated auth often needs session persistence fixes:

hooks/useAuth.ts - Proper session handling
import { useEffect, useState } from 'react'
import { supabase } from '../lib/supabase'
import { User, Session } from '@supabase/supabase-js'

export function useAuth() {
  const [user, setUser] = useState<User | null>(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    // Get initial session
    supabase.auth.getSession().then(({ data: { session } }) => {
      setUser(session?.user ?? null)
      setLoading(false)
    })

    // Listen for auth changes
    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (_event, session) => {
        setUser(session?.user ?? null)
      }
    )

    return () => subscription.unsubscribe()
  }, [])

  return { user, loading }
}

Part 4: Data Fetching Security

Add Authorization to Queries

Bolt-generated queries may fetch without checking ownership:

BEFORE: Bolt-generated query (potentially unsafe)
// May fetch all items regardless of owner
const { data } = await supabase
  .from('items')
  .select('*')
AFTER: Scoped to current user
// With proper RLS, this returns only user's items
const { data: { user } } = await supabase.auth.getUser()

if (!user) {
  throw new Error('Not authenticated')
}

const { data } = await supabase
  .from('items')
  .select('*')
  .eq('user_id', user.id)  // Explicit filter (defense in depth)

Security Checklist

Post-Export Checklist for Bolt + Supabase

RLS enabled on all tables

RLS policies restrict access properly

Only anon key used in client code

Service role key not in repository

Auth state properly persisted

Protected routes check authentication

Environment variables not hardcoded

No sensitive data in git history

Alternative Stacks to Consider

      **Bolt.new + Firebase**
      If you prefer Firebase's ecosystem


      **Bolt.new + Supabase + Vercel**
      Add Vercel deployment security


      **Bolt.new + Convex**
      Real-time alternative with built-in functions

Can I trust Bolt-generated Supabase code?

Bolt generates functional code, but security configuration requires manual review. Always check RLS policies, key usage, and authentication flows before deploying to production.

Why does my Bolt app work without RLS?

Without RLS, the anon key grants read/write access to all data. This is convenient for development but dangerous in production. Enable and configure RLS before going live.

How do I add server-side code to a Bolt app?

Export your Bolt project and add API routes or server functions to your deployment platform. Use the service_role key only in server-side code for admin operations.

Exported a Bolt + Supabase app?

Scan for RLS misconfigurations and key exposure.

Start Free Scan
Security Blueprints

Bolt.new + Supabase Security Blueprint