NeuralOS
GuideIntermediate

Lock down your app before you ship it · the 3 locks AI usually forgets

Building an app with AI is incredible — until you push it to the internet with no protection. And this is the most dangerous moment of the whole journey: AI, in builder mode, focuses on making the app WORK, not on how it can be attacked. The result: gorgeous apps where anyone can see another user's data by changing a number in the URL, APIs that any site in the world can call, and browsers with no defense instructions. This guide covers the 3 most-forgotten locks — RLS, CORS, and security headers — with an analogy for each one, the real risk, and a detailed prompt you paste into your AI so it sets everything up for you. You don't need to know how it works under the hood: just what each thing is called and when to put it in place.

Jun 19, 202612 min
Who is this for?
For anyone who's built an app with AI and is about to ship it — you don't need to code. If your app stores user data (accounts, messages, orders, whatever), this is mandatory before going live on the internet. Each section comes with an analogy, the risk, and a prompt so your AI configures it. You just approve.

When do you do this? (the exact moment)

The moment is clear and non-negotiable: right before you publish your app or hand it to real users. While you're testing on your own machine, nothing happens. But the second your app is on the internet with other people's data, without these locks you're exposing everything. And since AI won't do it on its own (it's thinking about making it work, not about protecting it), it's on you to ask for it explicitly.

The pain this guide was born from
It's the worst scare for anyone who builds with AI: you launch your app, someone changes a number in the URL… and sees ANOTHER user's data. Or worse: a security flaw exposes your entire database. You don't feel it while building —everything "works"— but it's a ticking time bomb. These 3 locks defuse it in minutes.

Lock 1 · RLS (so everyone sees ONLY their own stuff)

Picture it like this
Imagine a giant toy box where everyone stores their things. With no lock, anyone grabs everyone else's stuff. RLS (Row-Level Security) is a magic lock that knows who everyone is: each user only sees and touches their own data, even though it's all in the same box.

Without RLS, a malicious user just needs to change an ID in the URL or in a request to see someone else's data. It's the most common vulnerability in Supabase and PostgreSQL apps — and the easiest to exploit. That's why it's lock #1.

Prompt to turn on RLS (with the performance trick)text
I'm using Supabase with PostgreSQL. I have these tables: [list your tables and their user columns, e.g.: posts (user_id), comments (post_id, user_id)].

Set up Row-Level Security so each user can only view/edit/delete their own records. Follow Supabase's official best practices:

- Enable RLS on ALL tables (ENABLE ROW LEVEL SECURITY).
- Create SEPARATE policies for SELECT, INSERT, UPDATE and DELETE (do NOT use FOR ALL).
- IMPORTANT for performance: wrap the user function as (SELECT auth.uid()), NOT a bare auth.uid(), so Postgres evaluates it once per query instead of once per row.
- Restrict policies to the authenticated role (TO authenticated), not public, so anonymous visitors can't touch the table at all.
- NEVER use user_metadata in policies (the user can modify it).
- Add indexes on the columns the policies use (e.g. user_id).
- Remember: for an UPDATE to work, you also need a SELECT policy.
- Give me the complete SQL ready to paste into the Supabase SQL Editor, and explain in one line what each policy does.
The mistake that makes your app painfully slow (the "init-plan trap")
Almost every tutorial tells you to use auth.uid() directly in the policy. BUT that makes Postgres evaluate it once for every row — on a table with 100,000 rows, the difference is between a 5-millisecond query and a 5-second one! The trick (documented by Supabase): write it as `(SELECT auth.uid())`. That way it's evaluated just once. That's why the prompt above asks for it explicitly.
How do I know it's working?
Create two test users in your app.
Log in as user A and create a record.
Log in as user B: they should NOT see A's record.
Check Supabase's Security Advisor: it warns you if you left any table without RLS.

Lock 2 · CORS (who's allowed to call your API)

Picture it like this
CORS is your API's doorman. It decides which web pages are allowed to knock on the door. Without a doorman, any site in the world can call your backend from your users' browsers and hijack their session.
Prompt to configure CORStext
Configure CORS on my backend so that ONLY my production domain (https://my-app.com) and localhost in development can make requests.

- Do NOT use "*" as an allowed origin in production.
- Only allow the methods I actually use (e.g. GET, POST, PUT, DELETE).
- Only allow the headers I need.
- Explain exactly where to put each thing based on my stack: [tell it your framework/backend].
A mistake you must NEVER make
Leaving Access-Control-Allow-Origin: * with credentials enabled. It's like leaving the door open and hanging a sign that says "come on in, I left the keys inside." If your AI set it up that way "to make it work fast," fix it before you ship.

Lock 3 · Security Headers (defense instructions for the browser)

Picture it like this
Security headers are the house rules your site hands the browser on arrival: "don't put me inside another site's frame," "don't load scripts from sites I didn't authorize," "only talk to me over a secure connection." Without those rules, the browser does whatever — and that opens the door to common attacks.
Prompt to add Security Headerstext
Add the recommended security headers to my app: Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Strict-Transport-Security (HSTS) and Permissions-Policy.

- Explain what each one does in one simple line.
- Give me the config ready for my framework: [tell it which you use, e.g. Next.js, Express].
- Start the Content-Security-Policy in report-only mode so nothing breaks, and tell me how to tighten it afterward.
- Tell me how to verify the result.
Check your grade for free
Once you've set them up, paste your site's URL into securityheaders.com and it gives you a grade from A+ to F. It's the fastest way to confirm they're in place correctly — aim for an A.
securityheaders.com · grades your headers
Paste your site's URL and it gives you a grade (A+ to F) for your security headers.

The habit · check it before every release

Your pre-launch security checklist
RLS enabled on every table with user data (and tested with 2 accounts).
CORS restricted to your domains, never * with credentials.
Headers in place and scoring an A on securityheaders.com.
Your secrets (.env, API keys) NEVER pushed to GitHub (see the series' GitHub guide).
You checked Supabase's Security Advisor and there are no red warnings left.
Pair it with C-A-R
Security is exactly the kind of thing AI's builder mode overlooks. That's why it fits perfectly into the audit phase of the [C-A-R protocol](/recursos/protocolo-car-construir-sin-bugs): when you audit before shipping, add these 3 locks to the list. Building thinks about making it work; auditing thinks about how it gets attacked.
In NeuralOS, security comes built in
In NeuralOS, the apps you build are born with these protections on by default — RLS, restricted origins, and headers — without you having to remember to configure them. The idea is that you can't ship something insecure by accident. The vision is already on the road we're building.
Want to go further? Enterprise-grade hardening (the 8 layers)
These 3 locks are the bare essentials. If you're building something serious, the next level is the 8 layers of defense in depth.
The C-A-R protocol · audit before you ship
The method for getting AI to review its own work — security included — before it reaches production.
#security#supabase#production#rls
Ready to build?

Start building in
under 3 minutes

Join 4,200+ builders. No credit card. Build your first app with AI in minutes.