Bubble.io Privacy Rules: How to Secure Your SaaS Data Model
Privacy rules are Bubble’s server-side access control layer. Without them correctly configured, any authenticated user can search any data type and see records from every tenant. This guide shows you exactly how to write them — and how to test them before launch.
Privacy Rules: Server-Side, Not Client-Side
Privacy rules are not UI-level hiding. They are database-level query filters that run on Bubble’s server before any data is returned. If a privacy rule blocks a user from viewing a record, that record does not appear in search results, does not load on page navigation, and cannot be accessed via Bubble’s Data API. This is true access control — not conditional visibility that a determined user could bypass.
The Two-Rule Pattern That Governs Every Data Type
Condition:
Search for Memberships [
user = Current User,
workspace = This Project’s workspace,
status = Active
] : count > 0
Permissions: Find in searches ✓ View details ✓ Create ✓
// Rule 2 — Write access: Admin and Owner roles only
Condition:
Search for Memberships [
user = Current User,
workspace = This Project’s workspace,
role is in [Admin, Owner],
status = Active
] : count > 0
Permissions: Edit ✓ Delete ✓
Privacy Rule Reference — All Core Data Types
| Data Type | View Condition | Edit | Delete |
|---|---|---|---|
| Workspace | Active membership for Current User exists | Admin+ | Owner only |
| Membership | Belongs to workspace where Current User is member | Self or Admin+ | Admin+ only |
| Invitation | Same workspace member OR token matches URL param | Never | Admin+ only |
| User | Shares any active workspace with Current User | Self only | Never |
| Plan | Everyone (public pricing data) | Never | Never |
| Audit Log | Active Admin or Owner in log’s workspace | Never | Never |
| All App Types (Project, Task…) | Active membership in this record’s workspace | Member+ (own) or Admin+ | Admin+ only |
How to Test Tenant Isolation Before Launch
The only reliable way to verify tenant isolation is to run two completely isolated browser sessions — signed in as users belonging to different workspaces — and confirm that each user sees zero data from the other workspace.
Sign up as User A, create Workspace A, add some test records. In a separate browser or incognito profile, sign up as User B, create Workspace B with different records. Both must be completely independent accounts.
Signed in as User B, navigate to every page that displays a data type. Confirm that search results contain zero records from Workspace A. Pay special attention to dropdowns, autocomplete fields, and repeating groups that load data.
Copy the URL of a page loaded with a Workspace A record (e.g., /project/1a2b3c). While signed in as User B, navigate to that URL directly. The page should show nothing — not an error, but an empty/unauthorized state.
If you have enabled Bubble’s Data API, use User B’s API token to query data types. The returned results should contain only Workspace B records. If Workspace A records appear, your privacy rules have a gap that must be fixed before launch.
The Security Checklist — Run Before Every Launch
-
✓
Every data type has at least one privacy rule — zero types on “Everyone”
-
✓
Every app data type has a workspace field populated on creation in every workflow
-
✓
Tenant isolation verified with two isolated browser sessions — all data types tested
-
✓
User data type: users can only see co-members, not all system users
-
✓
All destructive workflows have server-side role checks — not just UI hiding
-
✓
File uploads are workspace-scoped and not accessible via public direct URL
-
✕
Never leave a data type with no privacy rules — even “Plan” should be read-only for everyone
-
✕
Never trust URL parameters as authentication — always verify membership server-side
Get a Security Audit Before You Launch
One missed privacy rule is a data breach waiting to happen. Let us audit your app before your customers find it.
