Lovable runs basic security scans upon release, but automated scans cannot prove that business authorization is correct.
Especially for the Supabase project, “RLS is enabled” and “the policy will not exceed authority” on the table are two different things.
First draw clear identity and data boundaries
List anonymous users, logged in users, administrators, and background tasks.
Then list the owner fields and tenant fields of each table.
|
|
It is difficult to write reliable strategies for tables without clear ownership fields.
Confirm that RLS is enabled for each business table
Query the true status in Supabase SQL Editor.
|
|
RLS is most easily missed when adding new tables.
Save the results as an online audit attachment.
The strategy must cover four operations respectively
The risks of SELECT, INSERT, UPDATE and DELETE are different.
Allowing one’s own rows to be read does not mean that all fields should be allowed to be modified.
Use WITH CHECK when inserting to verify new row ownership.
When updating, check the visibility of the old row and the legality of the new row at the same time.
Deletion operations generally require stricter roles.
Multi-tenant strategy don’t just compare user_id
Team products often rely on membership tables.
The policy should verify that the current user belongs to the target organization.
Also check whether the member status is valid and whether the role allows the operation.
Deactivated members should not continue to read old tenant data.
Invitation records cannot be equivalent to official members.
Use two accounts to do unauthorized testing
Create tenant A user Alice and tenant B user Bob.
Have Alice create an identifiable test record.
Bob attempts a list query, query by ID, update, and delete the record.
Don’t just test the UI.
Copy the request in the browser developer tools, replace the resource ID and replay.
All unauthorized requests should return empty results or authorization errors.
Service Role Key must not enter the front end
It bypasses RLS and must only exist on controlled servers.
Search repositories and build products:
|
|
If it has been submitted before, it does not end by deleting the file.
Keys should be rotated immediately and Git history and deployment logs should be checked.
Anon Key can be made public but the permissions cannot be relaxed
Supabase anon key is originally used on the client side.
Its security relies on RLS and database permissions.
Don’t ignore the cost of a request if it’s misused just because it’s public.
Added rate limits and verification codes for high-cost interfaces.
Storage also requires an independent policy
Check if bucket is public or private.
Private files use short-lived signed URLs.
The object path should preferably contain a trusted user or tenant prefix.
Don’t deduce ownership from client filenames alone.
Try passing another tenant’s object path to the download interface.
Edge Function validates the token instead of trusting the parameters
The function should authenticate the user from the Authorization header.
Do not accept user_id in the request body as a basis for identity.
Administrator action requeries the role on the server side.
Do not print the full JWT, cookie, or payment information in the logs.
Database function check SECURITY DEFINER
|
|
The SECURITY DEFINER function runs with owner privileges.
search_path must be fixed, execute permissions restricted, and dynamic SQL censored.
Change back to default caller permissions if not necessary.
Hidden buttons on the front end are not authorized
Lovable generated pages may hide admin buttons based on role.
An attacker can still call the API directly.
All permissions must be enforced again in database policy or on the server side.
UI judgment only improves the experience and does not constitute a security boundary.
Perform negative testing before release
Test without login access.
Test expired tokens.
Test that ordinary users call the administrator interface.
Test cross-tenant UUIDs.
The test batch interface mixes an unauthorized record.
Test uploading very large files and forging MIME types.
Test old tokens from deleted accounts.
Only when all negative use cases pass does it mean that the policy not only covers the normal path.
Processing sequence after discovering the problem
Tighten the policy or suspend the affected functions first.
Re-rotate the leaked keys.
Check the audit log to confirm whether it has been exploited.
After fixing retest with two tenants.
Finally the front end was re-released.
Don’t just leave security issues to new natural language prompts to “optimize a little more.”
Final Checklist
-
All business table RLS status has been exported.
-
There are clear strategies for the four types of database operations.
-
Multi-tenant authorization is verified by membership.
-
The Service Role Key does not enter the client or Git.
-
Storage bucket and object policies tested.
-
Edge Function independently verifies identity and role.
-
SECURITY DEFINER functions are reviewed one by one.
-
The two account unauthorized tests cover reading, writing and deleting.
-
Key rotation and event response paths are executable.
Automated scanning is suitable for finding common configuration errors; multi-tenant business rules still require manual design and adversarial testing.
Supabase Security Information
Use SQL to view existing policies instead of just looking at the interface
|
|
After exporting the results, check them table by table. qual determines which old rows are visible, and with_check determines whether new rows after writing are allowed to exist; writing only one of them may cause asymmetry in the reading and writing rules.
Review ideas for a multi-tenant read strategy
|
|
Real strategies also need to combine roles and business needs. When reviewing, make sure that organization_id is indexed, otherwise each query may scan memberships and the security policy will become a performance bottleneck.
Prevent users from modifying ownership fields
Allowing a user to update the title should not also allow the user to change the owner_id or organization_id to another value. You can restrict updates to columns, or require ownership to remain valid in WITH CHECK.
API tests should explicitly send the ownership field instead of relying on the front-end form not displaying it. An attacker can directly construct a JSON request.
Race conditions in the invitation process
The team invitation contains at least a random token, expiration time, target email, organization and status. Check and mark the token as used in a database transaction when accepting the invitation.
Submitting the same invitation link twice concurrently can only create one membership. Invitations that have been revoked or expired must fail, and checks cannot be skipped just because the user is logged in.
Storage Perform secondary verification after uploading
The client’s Content-Type can be forged. The server or asynchronous task reads the file header, confirms the true format, and sets independent size limits for images, PDF and other types.
The public bucket does not store ID cards, contracts, and user export files. The signed URL of the private bucket has a short validity period, and the log does not record the complete signed URL.
CORS of Edge Function is not authorized
CORS only controls whether the browser can read cross-domain responses and cannot prevent curl or server requests. Functions still need to verify JWT, tenant membership, and specific operation permissions.
Preflight requests only return necessary methods and headers. Don’t use any combination of origin and credentials to eliminate browser errors.
The backup also contains sensitive data
Supabase backups, SQL dumps, and local torrent files use the same protection level as production data. Confirm disk encryption and access permissions before downloading to the development computer.
Recovery drills use quarantine items. Immediately after the recovery is completed, the tokens, Webhook secrets, and third-party credentials brought with the data in the test environment are rotated.
Continuous inspection after going online
Monitor the number of RLS rejections, abnormal batch reads, Storage traffic, and Edge Function error rates. A single rejection is usually a normal input error, while traversing a large number of UUIDs in a short period of time may be an unauthorized detection.
The security checklist is re-executed every time a new table, bucket or function is added. Just because the first online audit passes, it does not mean that all functions generated thereafter will automatically inherit the correct policy.