AI-coded apps

    Can ChatGPT Safely Generate Supabase RLS Policies?

    A ChatGPT-generated Supabase RLS policy being reviewed for a missing WITH CHECK clause and an auth.uid() check that only confirms the user is logged in.

    ChatGPT can generate Supabase Row Level Security policies that are syntactically valid, but it cannot be trusted to generate secure ones without review, because it does not know your data model or your threat model and, like AI-generated code in general, tends to produce policies that are too permissive or incomplete. The classic failures are a policy that effectively allows everyone, an ownership check that only confirms the user is logged in rather than that they own the row, and a missing write-side check that lets a user create or change rows belonging to someone else. The function it uses to identify the user, auth.uid(), is itself safe; the mistakes are in the policy logic around it. So use ChatGPT to draft a policy, but review it, test it as different users, and never deploy an AI-generated policy unverified.

    Short answer

    ChatGPT is a useful drafting aid and an unreliable security author for Row Level Security, so treat its output as a starting point you must verify. Per Supabase's Row Level Security docs, a policy must be enabled on the table and must correctly scope access, using USING for what rows are visible and WITH CHECK for what can be written, and getting either wrong exposes data. Research supports the caution: a Stanford study found developers with AI assistants wrote less secure code while being more confident it was safe. So let ChatGPT draft policies, then confirm Row Level Security is enabled, both clauses are present, and access is denied when you test as another user.

    Can ChatGPT write RLS policies at all?

    Yes, ChatGPT can produce Row Level Security policies that are valid SQL and often look correct, which is exactly what makes relying on them risky. It knows the syntax of a policy, the common patterns like comparing the authenticated user to an owner column, and the Supabase helper functions, so its output usually runs without error.

    The problem is that correct syntax is not the same as correct security. ChatGPT does not know which of your tables hold sensitive data, who should see what, or how an attacker might abuse a gap, so it fills those gaps with plausible defaults that are frequently too open. So the honest position is that ChatGPT can write a policy, but whether that policy actually protects your data is a question only you can answer by reviewing and testing it, which the rest of the sections show how to do.

    The most common ChatGPT RLS mistakes

    The failures cluster into a short, predictable list. The most dangerous is a policy that is effectively open, such as one that permits any row, which grants everyone access and defeats the point of Row Level Security. Close behind is an ownership check that only verifies the user is authenticated rather than that they own the specific row, which lets any logged-in user reach any row. Then there is omitting the write-side check, so read access is scoped but a user can still insert or update rows they should not.

    Two structural mistakes round out the list. ChatGPT may hand you a policy while forgetting that Row Level Security has to be enabled on the table for the policy to take effect, so nothing is actually enforced. And it may write a policy for one operation, typically reading, while leaving other operations ungoverned or applying the policy to the wrong database role.

    The auth.uid() mistakes

    The function ChatGPT uses to identify the current user, auth.uid(), is safe and correct: it returns the authenticated user's id from their token, evaluated on the server where the client cannot forge it, so basing access on it is the right approach. The mistakes are not in the function but in how the generated policy uses it. The frequent one is a policy whose condition is only that auth.uid() is not null, which merely checks that someone is logged in and therefore lets any authenticated user access every row, when the intent was to restrict each user to their own.

    The correct pattern compares auth.uid() to the row's owner column, so a user sees and changes only rows where they are the owner. Other errors ChatGPT makes include comparing auth.uid() to the wrong column, or scoping reads with it but forgetting to apply the same ownership condition to writes. So when you review an AI-generated policy, check that auth.uid() is compared to the right ownership column, not merely tested for being logged in, and that the same ownership logic governs both reads and writes.

    USING versus WITH CHECK

    A specific and costly ChatGPT mistake is omitting WITH CHECK, and understanding the difference is what lets you catch it. In a Row Level Security policy, the USING clause decides which existing rows are visible to a query and which existing rows an update or delete is allowed to touch, while the WITH CHECK clause decides which new or modified rows are allowed to be written. So USING protects reads and the targeting of writes, and WITH CHECK protects the content of writes.

    If ChatGPT gives you a policy with only USING, a user might be correctly limited to their own rows for reading, yet able to insert a row that claims a different owner, or update a row to reassign it, because nothing checks the values being written. So an insert or update policy needs a WITH CHECK clause that enforces the same ownership condition on the written data, for example that the owner column of the new row equals the authenticated user. When reviewing a generated write policy, the first thing to confirm is that WITH CHECK is present and matches your ownership rule.

    Enable RLS and cover every operation

    Two setup steps are easy for ChatGPT to skip and easy for you to forget. First, Row Level Security must be enabled on the table, because a table without it is fully accessible to anyone with the public key regardless of any policy you wrote, while a table with it enabled and no matching policy denies all access.

    Second, policies are per operation, so you need to account for select, insert, update, and delete rather than assume one policy covers everything. ChatGPT often produces a read policy and stops, leaving writes either wide open or fully blocked depending on your setup. So confirm that each operation your app performs has an appropriate policy, and that the policies target the correct role, typically the authenticated role rather than the anonymous one, so access matches who should be doing what.

    What about Postgres injection?

    For ordinary Row Level Security policies, SQL injection is not the main risk, because a policy that compares auth.uid() to a column is a fixed condition with no place for attacker input, so a standard ownership policy is not injectable.

    Injection becomes a concern only when generated code goes beyond a simple comparison, for example a helper function that a policy calls which builds dynamic SQL from input, or a policy that references user-controllable data unsafely. If you ask ChatGPT for a more complex policy or a SECURITY DEFINER function, review it for any string-concatenated SQL and make sure inputs are handled as parameters, not spliced into a query. So the rule is that plain auth.uid()-based policies are safe from injection, while any generated function or dynamic query needs the same injection review you would give any SQL.

    The common mistakes at a glance

    Knowing what to look for turns review into a checklist. The table below maps the frequent ChatGPT RLS errors to the fix.

    MistakeWhy it is unsafeFix
    Effectively open policyGrants everyone accessScope to the owner with auth.uid()
    Only checks logged inAny user reaches any rowCompare auth.uid() to the owner column
    Missing WITH CHECKUsers can write others' rowsAdd WITH CHECK with the ownership rule
    RLS not enabledThe policy does nothingEnable Row Level Security on the table
    Only one operation coveredWrites ungoverned or blockedAdd policies for all needed operations

    Read the first three rows as the high-severity checks, since an open policy, a logged-in-only check, or a missing WITH CHECK each exposes data outright.

    How to verify an AI-generated policy

    Working through these checks confirms a generated policy is actually safe. The checklist below covers them.

    StepActionDone?
    Enable RLSConfirm Row Level Security is on for the table[ ]
    Check ownership logicauth.uid() compared to the owner column[ ]
    Confirm WITH CHECKWrite policies enforce ownership on new rows[ ]
    Cover all operationsPolicies for select, insert, update, delete[ ]
    Review any functionNo unsafe dynamic SQL in helpers[ ]
    Test as another userA second user cannot see or change your rows[ ]

    The step teams skip most is testing as another user, since that is the only check that proves the policy denies access it should deny, rather than merely looking correct.

    Where a scan fits

    Because an AI-generated policy can look right while leaving data open, verifying the result rather than trusting the generator is where safety comes from, and an objective check helps you find what a review misses.

    A scanner like PTKD.com analyzes your app build and flags issues such as tables exposed without Row Level Security, access relied on from the client without server-side rules, and an exposed service role key, mapped to OWASP MASVS. To be clear about the boundary: PTKD does not write or grade your Row Level Security policies, which are your Supabase setup, and it does not replace testing them as different users. It helps you catch the exposures that an AI-generated policy most often leaves, so a policy ChatGPT drafted does not ship as an open door.

    What to take away

    • ChatGPT can generate syntactically valid Supabase Row Level Security policies, but not reliably secure ones, so treat its output as a draft to review and test.
    • The common failures are effectively open policies, ownership checks that only confirm the user is logged in, and missing WITH CHECK clauses that let users write other people's rows.
    • auth.uid() is safe because it comes from the verified token; the mistakes are in the policy logic, so compare it to the owner column and apply the same rule to writes.
    • Enable Row Level Security on the table and cover select, insert, update, and delete for the right role, since a policy without RLS enabled does nothing.
    • Plain auth.uid() policies are not injectable, but review any generated function for unsafe dynamic SQL, and use a tool like PTKD.com to catch tables left exposed.
    • #supabase
    • #row level security
    • #chatgpt
    • #ai-generated code
    • #auth.uid

    Frequently asked questions

    Can ChatGPT generate Supabase RLS policies?
    Yes, ChatGPT can produce Row Level Security policies that are valid SQL and often look correct, since it knows the syntax, the common patterns, and Supabase's helper functions. The problem is that correct syntax is not the same as correct security: ChatGPT does not know which tables hold sensitive data, who should see what, or how an attacker might abuse a gap, so it fills gaps with plausible defaults that are frequently too open, and it cannot test the policy against your data. So it can write a policy, but whether that policy protects your data is something only you can confirm by reviewing and testing it.
    What auth.uid() mistakes does ChatGPT make in RLS policies?
    The function auth.uid() is safe, since it returns the authenticated user's id from their verified token, evaluated on the server. The mistakes are in how the generated policy uses it. The frequent one is a condition that only checks auth.uid() is not null, which merely confirms the user is logged in and lets any authenticated user access every row, when the intent was to restrict each user to their own. Other errors include comparing auth.uid() to the wrong column, or scoping reads with it but forgetting to apply the same ownership condition to writes. Compare it to the correct owner column, for reads and writes.
    What is the difference between USING and WITH CHECK in an RLS policy?
    The USING clause decides which existing rows are visible to a query and which existing rows an update or delete may touch, while the WITH CHECK clause decides which new or modified rows are allowed to be written. So USING protects reads and the targeting of writes, and WITH CHECK protects the content of writes. ChatGPT frequently omits WITH CHECK, so a user is correctly limited for reading but can insert a row claiming a different owner or reassign a row, because nothing checks the values written. An insert or update policy needs a WITH CHECK enforcing the same ownership rule.
    Can an AI-generated RLS policy have a SQL injection flaw?
    For ordinary policies, no. A policy that compares auth.uid() to a column is a fixed condition with no place for attacker input, and the user id comes from the verified token rather than client text, so a standard ownership policy is not injectable. Injection becomes a concern only when generated code goes further, such as a helper function a policy calls that builds dynamic SQL from input, or a policy referencing user-controllable data unsafely. So review any generated function or dynamic query for string-concatenated SQL and ensure inputs are parameterized, but plain auth.uid()-based policies are safe from injection.
    How do I verify a ChatGPT-generated RLS policy is safe?
    Confirm Row Level Security is enabled on the table, since a policy does nothing without it. Check that the ownership logic compares auth.uid() to the owner column rather than only checking the user is logged in. Confirm write policies include a WITH CHECK enforcing ownership on new rows, and that you have policies for select, insert, update, and delete targeting the correct role. Review any helper function for unsafe dynamic SQL. Most importantly, test as a second authenticated user and confirm they cannot see or change your rows, which is the only check that proves the policy denies what it should.
    Is it safe to use ChatGPT for database security rules?
    Only as a drafting aid you then verify, not as a trusted author. Research found developers using AI assistants wrote less secure code while feeling more confident it was safe, and using AI to write access rules has led to real breaches when the generated policies were left open. So ChatGPT can accelerate writing a Row Level Security policy, but the security depends on your review: enable Row Level Security, check the ownership logic and the WITH CHECK clause, cover all operations and the right role, and test as another user before deploying anything it produced.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free