How to test cross-tenant file access in a Bubble client portal

Illustration of two separate tenant workspaces with a blocked cross-tenant file path

The question to test

When a Harbor employee knows the exact identifier or URL for a Cedar document, what stops that employee from reading, replacing, or deleting it? A portal’s navigation is not the answer. Hiding Cedar’s row from Harbor’s dashboard may improve the interface, but it does not establish what happens when Harbor sends a direct request.

This article offers a synthetic test plan for a two-organization Bubble client portal. It does not report a completed security test or imply that Bubble2X currently operates a file service. Bubble2X’s customer-facing storage workflow is planned. Use a disposable environment and fake documents, then adapt the matrix to the actual authorization design.

Build the smallest useful fixture

Create Cedar and Harbor as separate organizations. Give each one a normal member and an administrator, plus a signed-out browser session. Create one synthetic PDF or text file under each organization. Record each file’s application record ID, storage object ID or Bubble file URL, owner, and expected allowed actions. Use obvious synthetic contents such as “CEDAR TEST DOCUMENT” so a wrong-tenant response is easy to recognize without exposing customer data.

Add a former Cedar member whose account has been removed from Cedar but still exists. If the portal has share links, include one link holder who has no account. If the portal supports replacement, versioning, or delete, create a file that can safely be changed repeatedly. Keep the fixture documented: a future tester must know whether a denial is due to tenant policy, missing authentication, or a malformed request.

For Bubble-hosted files, review the Bubble files documentation. It describes the uploader’s “Make this file private” setting and the need to attach a file to a database thing whose privacy rules govern access. Bubble’s privacy-rule guide distinguishes hiding a file URL field from denying access to the attached file itself. Your fixture should test both.

For externally stored files, identify the service that decides whether the acting Bubble user may access an object. Cloud Storage signed URLs grant access to a URL holder for a limited time. Therefore the test must cover the decision to issue the URL and the residual access while an issued URL remains valid.

Map every entry point

List all paths by which a file can be reached. Include the portal page, a copied file URL, an API endpoint, a background workflow, a download button, a replacement form, and an administrative view. Bubble’s Data API, if enabled, may expose selected data types under the app’s configuration and privacy rules. An integration service may add its own endpoints. Testing only the visible page misses those surfaces.

Document the authority for each request. Does Bubble derive the current user from its session? Does an external service verify a token, then look up organization membership? Does any endpoint accept a user ID, organization ID, or object path from the request body? Such fields may be useful selectors, but they should never become proof of permission on their own.

Conceptual request boundary

Harbor browser → Bubble page or API → server-side membership check
                                   → file ownership lookup
                                   → Bubble private file or Cloud Storage operation
Harbor browser → Bubble page or API → server-side membership check
                                   → file ownership lookup
                                   → Bubble private file or Cloud Storage operation
Harbor browser → Bubble page or API → server-side membership check
                                   → file ownership lookup
                                   → Bubble private file or Cloud Storage operation

At each arrow, ask what would happen if the browser changed one identifier while keeping its valid Harbor session. The crucial question is whether the server recomputes the tenant relationship from trusted records.

Run the negative-test matrix

Record the request, expected result, observed result, date, and evidence link for each row. “Denied” should mean no file bytes or usable access grant are returned, no object is changed, and the audit record identifies the attempted operation without leaking content.

Actor and attempt

Expected result

What the test reveals

Cedar member uploads to Cedar

Allowed if role permits

Baseline success path

Harbor member changes upload organization ID to Cedar

Denied

Whether client-supplied tenant ID is trusted

Harbor member opens Cedar’s file URL or object ID

Denied

Whether read authorization exists beyond page navigation

Harbor member requests a Cedar download grant

Denied

Whether the signer checks file ownership

Harbor member replaces Cedar’s file using a known ID

Denied; original unchanged

Whether write authorization differs from read authorization

Harbor member deletes Cedar’s file record or object

Denied; both remain

Whether delete checks current tenant membership

Signed-out visitor repeats a copied Bubble private-file URL

Denied unless deliberately public

Whether Bubble file access is enforced beyond hiding the URL

Signed-out visitor uses an active Cloud Storage signed URL

May work until expiry; document the intended lifetime

Whether the team understands temporary bearer access

Former Cedar member requests a new download

Denied

Whether revocation is checked at request time

Member reuses an expired temporary upload or download grant

Denied by storage endpoint

Whether expiry works as configured

Member retries the same upload request

One logical upload or clear conflict

Whether retries create duplicates or overwrite

Do not mark a row “pass” because the UI shows an error while the file was still written. Inspect the actual object, the application record, and any status or audit entry. A browser may report a network error after the server has completed the action. That is especially important for deletion and replacement.

Check Bubble privacy rules directly

If using Bubble’s native file storage, test both the file field and the attached file. A rule that hides a field may prevent a user from discovering the URL through a search, yet a URL learned elsewhere can still matter unless “View attached files” access is configured correctly, as Bubble’s files guide explains. Use a fresh signed-out session and a different authenticated organization to request the copied URL. Then inspect the relevant thing’s privacy rules and uploader settings.

If a plugin uploaded the file, check that plugin’s path separately. Bubble’s documentation notes that plugin behavior may differ from built-in uploader behavior. Do not assume “private” on one element carries over to another plugin or a third-party URL. Inspect both the storage provider and the Bubble record that points to it.

For API endpoints, test the exact credentials and roles used in production. An admin API key is different from a normal user’s session. Bubble’s API authentication documentation describes different workflow access levels. Keep administrative credentials out of browsers and synthetic test captures; otherwise the test no longer represents a normal user.

Check the external storage boundary

In a Cloud Storage design, the integration service should authorize a request for one file and one action before touching storage or signing a temporary URL. Use the Harbor account to request a Cedar object by ID. Try changing both the organization selector and the object name. If either produces a Cedar link, the failure is in the service’s authorization or ownership lookup, even if the bucket itself is private.

Cloud Storage access-control documentation distinguishes IAM, ACLs, and signed URLs. A key prefix such as “cedar/” does not cause Cloud Storage to apply Bubble membership. If the same service identity can read both tenants, the service must enforce the organization boundary before making a request. Where the design uses separate identities or resources, verify their effective permissions too.

Temporary links deserve two tests. First, a user who is no longer a member should not receive a new link. Second, a previously issued link may remain usable until expiration; document and test that window. Avoid putting temporary URLs in analytics, application logs, support tickets, or screenshots, because anyone holding an active link may use it.

Examine state after denial and interruption

Check that a denied write did not create a pending row, a zero-byte object, or a partial replacement. Check that a denied delete did not remove the app record while leaving the storage object orphaned. If an upload was authorized before membership was revoked, define whether the service permits completion, rejects finalization, or quarantines the object. Whatever policy you choose, make it explicit and test it.

Repeat the matrix after changing privacy rules, uploader configuration, API exposure, membership logic, or storage IAM. An independent reviewer should run at least the wrong-tenant and signed-out cases. Keep the evidence compact: synthetic IDs, redacted request metadata, response status, storage state, and the result of a read-back check. Do not archive real customer files or temporary signed URLs as proof.

The outcome is a decision record, not a badge. If one row fails, document the affected operation and fix that boundary before claiming tenant isolation. If an exception is intentional, identify its business owner and the exact sharing rule. The broader file-upload security checklist helps assign the rest of the controls.

Request early access to discuss your client-portal file workflow and the access controls your team needs.

Test matrix showing allowed own-tenant file requests and denied cross-tenant requests

Help shape the cloud layer for Bubble apps

Help shape the cloud layer for Bubble apps

Help shape the cloud layer for Bubble apps

Bubble2X is building a Bubble-to-Google-Cloud integration for controlled customer-file workflows.

Newsletter

Get tips, product updates, and insights about building with Bubble2X.

Subscribe to Bubble2X updates. See our Privacy Notice.

© 2026 Bubble2X. Product in development.

Bubble2X is building a Bubble-to-Google-Cloud integration for controlled customer-file workflows.

Newsletter

Get tips, product updates, and insights about building with Bubble2X.

Subscribe to Bubble2X updates. See our Privacy Notice.

© 2026 Bubble2X. Product in development.

Bubble2X is building a Bubble-to-Google-Cloud integration for controlled customer-file workflows.

Newsletter

Get tips, product updates, and insights about building with Bubble2X.

Subscribe to Bubble2X updates. See our Privacy Notice.

© 2026 Bubble2X. Product in development.