SCAN YOUR TEMPO APP FOR VULNERABILITIES
ENTER YOUR TEMPO APP URL
Enter your deployed app URL to check for security vulnerabilities.
Tempo (tempo.new) pairs a drag-and-drop visual editor with AI agents that generate React (Vite) code, typically on a Supabase backend. The architecture makes the security story unusually concrete: the Supabase anon key ships in the client bundle by design, so Row Level Security is the entire server-side access-control layer. Everything the React app appears to protect — route guards, hidden pages, premium features — is decoration unless an RLS policy or Edge Function enforces it.
“It’s a frontend on Supabase” is the trap. The Vite bundle is public: every VITE_-prefixed variable and every inline string compiles into JavaScript served to all visitors, and the visual workflow’s storyboards and component playgrounds can survive into the production build. Add the platform’s defining feature — designers and PMs shipping real code changes with no engineer in the loop — and gaps land silently, and regenerations quietly reintroduce ones you already fixed.
VibeEval scans the deployed app from outside, with the anon key and a browser, the way an attacker would.
Common vulnerabilities we find in Tempo apps
The recurring shapes in Tempo-generated React + Supabase apps, and how each one gets exploited.
Missing or broken Row Level Security
Tables created mid-session as the app grows frequently launch with RLS never enabled — and the anon key in the bundle queries the Supabase REST API directly, so a table without RLS is readable and often writable by any visitor with one curl call. RLS enabled but scoped wrong is the subtler version: SELECT gets a policy, UPDATE and DELETE stay open. Fix direction: enable RLS on every table with auth.uid() = user_id policies for all four operations, and verify from outside with the Supabase RLS Checker.
Client-side-only authentication
Tempo’s generated route guards check the session in React — if (!session) navigate("/login") — which hides the page and protects nothing. The data API is the Supabase endpoint, reachable with the anon key and no React app at all. The exploit: take the anon key from the bundle, query the “protected” table from curl. Fix direction: every real restriction exists as an RLS policy or inside an Edge Function that verifies the JWT; the route guard is UX only.
Storyboard and dev routes in production
The visual workflow generates storyboards, component playgrounds, and preview routes during development, and nothing forces their removal from the production build. Left in, they render your components — sometimes wired to live Supabase data — outside any auth flow, and they map your internal UI for attackers. The exploit is guessing /storyboard, /tempobook, or /playground on the production URL. Fix direction: exclude dev routes from production builds (import.meta.env.DEV conditionals) and verify they 404 after every deploy.
API keys compiled into the Vite bundle
A key pasted into a component during prototyping — OpenAI, Stripe secret, Resend, or worst of all the Supabase service_role key, which bypasses RLS entirely — is compiled into the bundle and served to every visitor. The exploit: grep -rE 'sk_(live|test)_|sk-|service_role' dist/, which scrapers run against deployed apps continuously. Fix direction: only the Supabase URL and anon key belong client-side; move everything else into Edge Functions and rotate any key that ever appeared in the bundle. The Token Leak Checker runs this check against your deployed URL.
Cross-user data access (BOLA)
Policies scoped to authenticated instead of the owner are the Supabase flavor of broken object-level authorization: auth passes, ownership was never checked, and any logged-in user reads every row of user-scoped data. The test: sign up as user A, create a record, sign in as user B, fetch it through the Supabase client — anything other than an empty result is a policy bug. See BOLA in AI-generated CRUD. Fix direction: rewrite policies to auth.uid() = user_id with WITH CHECK on writes, and re-run the two-account test per table.
Self-escalating privilege fields
RLS policies are row-level, not column-level: if profiles has a role, is_admin, or plan column and owners can update their own row, a user runs update profiles set role = 'admin' where id = auth.uid() and walks into the admin panel. Generated schemas ship this constantly because the “users can edit their profile” policy is technically correct. Fix direction: guard privileged columns with a trigger or column check, or route all privilege changes through an Edge Function that verifies the caller’s role server-side.
How VibeEval works with Tempo
- Enter your deployed URL. Point VibeEval at the Tempo-hosted app or your production domain — no code access, no Supabase credentials beyond what the app already ships publicly.
- The agent attacks the app in a real browser. It extracts the anon key and route table from the bundle, enumerates Supabase tables and tests RLS from outside, runs two-account BOLA replays and privilege-escalation writes, probes storyboard and dev routes, and checks the bundle for third-party key prefixes, source maps, and missing headers.
- Read the report, paste the fixes. Findings arrive ranked by severity, naming the table, policy, or route affected — each with a paste-ready fix prompt you can drop into Tempo’s AI chat for one-shot remediation.
Manual testing vs VibeEval
| Manual review | VibeEval | |
|---|---|---|
| Time per full pass | Hours with the Supabase dashboard open: policy list per table, bundle grep, route probing | Minutes, run against the deployed URL |
| Cross-user (BOLA) coverage | Two test accounts replayed by hand per table — high effort, so it gets spot-checked | Two-account replay attempted on every discovered user-scoped table |
| RLS verification | Reading policies table by table and trusting your interpretation | Tested from outside with the anon key — the ground truth, not the intent |
| After each AI edit | Full re-check, because regeneration can restore a dev route or rewrite a policy you fixed | Re-scan on demand; regressions surface as new findings |
| Visual-editor changes | Requires an engineer diffing code the workflow was built to hide | Every deploy gets the same pass, no engineer in the loop |
| Cost | Engineer-hours per deploy | Flat, repeatable after every edit session |
The honest framing: a human still needs to review business logic and decide each table’s access model. The scanner wins on repeatability — Tempo’s whole model is fast AI and visual edits, and every one of them deserves the same security pass without the same hours.
Frequently asked questions
Does VibeEval have special support for Tempo?
Yes. VibeEval recognizes the React (Vite) + Supabase stack Tempo generates and runs the probes specific to it: anon-key table enumeration against RLS, two-account ownership tests, privilege-field escalation attempts, storyboard and dev-route discovery, and Vite bundle checks for prototype keys.
Is the Supabase anon key in my Tempo bundle a leak?
The anon key itself is designed to be public — it is safe if and only if RLS is enabled and correctly scoped on every table, which is exactly what the scan verifies from outside. What is a leak: the service_role key or any third-party secret in the bundle. Those bypass or sit outside RLS entirely and need immediate rotation.
Can I scan during Tempo development?
Scan the hosted URL or a staging deploy before sharing it with real users, then again before launch. Because the anon key and RLS policies are live from the first deploy, the findings on staging are the same ones production would have.
What authentication issues are common in Tempo apps?
Client-side route guards with no RLS enforcement behind them, policies scoped to “any authenticated user” on user-scoped tables, owner-writable role columns, and OAuth redirect URLs left over from development. The common thread: the React layer implies restrictions the Supabase layer never enforces.
Should I re-scan after AI edits in Tempo?
Yes — this is the platform where it matters most. Regeneration can reintroduce fixed gaps: a new table without RLS, a rewritten policy, a restored storyboard route, a key pasted back into a component. Re-scan after each significant AI edit or visual-editing session, and always before launch.
Related Tempo resources
- How to Secure Tempo — the step-by-step hardening checklist: RLS patterns, bundle hygiene, dev-route cleanup, auth settings.
- Is Tempo Safe? — in-depth analysis of the Tempo generation pattern and the six areas to harden.
- Tempo Security Checklist — severity-ordered pre-launch checklist, including the after-every-regeneration routine.
- Supabase RLS Checker — free outside-in check that every table actually enforces RLS.
- Token Leak Checker — free check for prototype keys compiled into your deployed bundle.
Test your Tempo app before launch
The visual editor shows you a polished app; it cannot show you the table the anon key reads without asking. Run a scan against your deployed URL, paste the fix prompts back into Tempo, and ship the version where RLS — not the React router — is doing the protecting.
SCAN YOUR APP
14-day trial. No card. Results in under 60 seconds.