Moltbook left its Supabase database open to read and write
Wiz found that Moltbook, a social network for AI agents whose founder said he vibe-coded it, shipped a Supabase key in its JavaScript with no Row Level Security behind it. Anyone could read and write the database, including 1.5 million agent API tokens and 35,000 email addresses.
What it is
Wiz (2 February 2026): a Supabase publishable key in Moltbook’s client-side JavaScript granted “unauthenticated access to the entire production database - including read and write operations on all tables.” The key is meant to be public; the missing RLS policies were the problem.
Exposed data included 1.5 million agent API authentication tokens (enough to take over any agent), 35,000 email addresses and 4,060 private agent-to-agent conversations, some with plain-text OpenAI API keys. Wiz could also edit live posts.
The founder had said publicly: “I didn’t write a single line of code for @moltbook.” Moltbook fixed it with Wiz over several rounds within hours on 31 January–1 February. Researcher Jameson O’Reilly found the same misconfiguration independently.
How to check
- Find the Supabase URL and anon or publishable key in your site’s JavaScript, then query a table with only that key (see code). Any rows mean RLS isn’t protecting it.
- Also try a PATCH or POST. Read-only fixes can leave write access open, as happened here.
How to fix
- Enable RLS on every table and add policies per operation: public read only where content is meant to be public, writes only by the row’s owner.
- Never store credentials (agent tokens, other services’ API keys) in tables the client can read. Rotate anything that was exposed.
-- Check (logged out):
-- curl "https://<project>.supabase.co/rest/v1/agents?select=*&limit=1" -H "apikey: <publishable-key>"
alter table public.posts enable row level security;
create policy "Anyone can read posts" on public.posts for select using (true);
create policy "Authors edit own posts" on public.posts for update to authenticated
using ((select auth.uid()) = author_id) with check ((select auth.uid()) = author_id);
-- Tables holding tokens: RLS on with no policies = no client access at all
alter table public.agents enable row level security;