Skip to main content

Fixing issues flagged by the security dashboard

Step-by-step fixes for every issue the security dashboard can flag in your Bubble app, from privacy rules to API tokens and page access protection.

Written by Sofia Maconi

When the security dashboard flags an issue in your app, use this guide to find the fix. Each section covers what triggers the issue and exactly how to resolve it.

If you've fixed an issue but it still shows as unresolved, run a new security test from your security dashboard to update the status. If it concerns the live version, make sure you've deployed your changes first. Still stuck? Contact our team.


Page Access Protection

To fix the Page Access Protection issue, you need to use a server-side redirect instead of a client-side one. This issue is flagged when a sensitive page uses a client-side redirect, which lets the page load fully before redirecting — meaning all data is already downloaded before the user is turned away.

To illustrate this issue, consider the following scenario:

You have a page called "admin" that is restricted to users with admin access because it contains sensitive data such as private pictures of users, and allows admins to take certain actions.

In this case, you might want to check if the current user has the admin role and, if they do not, redirect them to the homepage. While this may seem like a logical approach, it is important to understand that redirections can be problematic.

It is essential to have a thorough understanding of how redirections work to avoid this type of issue.

Understanding redirections

When you try to load a page, you are making an HTTP request to the Bubble servers to retrieve the content of the page. The response from the server can be one of five different types:

  1. Informational (100 to 199)

  2. Successful (200 to 299)

  3. Redirect (300 to 399)

  4. Client error (400 to 499)

  5. Server error (500 to 599)

As you can see, there are multiple possibilities for redirection codes within the 3rd category. The most important thing to understand about redirection is that if you receive a 3xx response from the server, no content will be downloaded and you will be immediately redirected to the next page.

This is known as a "server-side redirect."

In contrast to a server-side redirect, a "client-side redirect" is a manual redirection that is initiated by a JavaScript instruction. It is important to note that JavaScript needs to be downloaded before it can be executed. This is how a client-side redirect works:

The admin page is downloaded, and then JavaScript is executed to tell the browser to go to another page. However, by this time, all of the data has already been downloaded, making it too late to prevent unauthorized access.

It is important to be aware of the limitations of client-side redirects and to use appropriate security measures to protect sensitive information.

How to set up clean server redirections?

To set up server-side redirections, you need to use the "Go to page" action without relying on any client-side conditions or events.

Note: Only "Go to page" action works in this case. Using the "Go to previous page" won't work here, as it needs the front-end context to know which page to redirect to, and we want this action to run in the back-end.

For example, you could set up a redirection using the « User is logged out" to see what happens. Let’s see what we get:

To verify that you are correctly using a server-side redirect, you can use a redirect checker such as this one. This will allow you to determine whether you are receiving a 3xx or 2xx response from the server.

We indeed have a 302 redirect on the page « redirect », then we’re redirected to the page « index » which is fetched with a 200 code.

All good!

Let’s try another method and use a client-side condition. We will use the « Do when a condition is true » event (that gets executed once the page is loaded), and check if the Current User is an Admin or not:

Let’s check the response code from the redirect checker:

We got a 200 code. This indicates that the page has been completely downloaded and that no server-side redirect has been applied.

Why client-side redirects aren't safe

When a browser loads a page, it first downloads all page content, then executes JavaScript. A client-side redirect (like "Do when a condition is true") runs after the page has loaded — too late to prevent data from being exposed. A server-side redirect (3xx response) prevents any page content from being downloaded in the first place.

Let’s resume client-side and server-side redirections for main events:

Event name

Type

Safe?

Do when a condition is true

Client-side

No

Current User is logged in

Server-side

Yes

Current User is logged out

Server-side

Yes

Page is loaded

Server-side

Yes

How to fix it

To set up a safe server-side redirect, you need to meet all of these requirements:

  • Use one of these events: Current User is logged in, Current User is logged out, or Page is loaded

  • Only include 1 action in the workflow

  • Don't add a client-side condition to the event — doing so converts it back to a client-side redirect

  • Your condition must not rely on a value that requires the page to be loaded (no custom states)

Use only the "Go to page" action. "Go to previous page" won't work here because it needs front-end context.

You can verify you're using a server-side redirect with a redirect checker tool. A safe redirect returns a 3xx response code. A 200 response means the page loaded fully — the redirect is client-side and not safe.


Public Bubble Editor

To fix the Public Bubble Editor issue, set your editor visibility to Private. This issue is flagged when your Bubble editor is accessible to anyone — meaning they can view your app structure and data through the editor.

How to fix it

Go to Settings > General in your Bubble editor and set the editor privacy to "Private".


Unapproved Collaborator

To fix the Unapproved Collaborator issue, manually approve each collaborator in the security dashboard. By default, all collaborators are unapproved — you need to review and approve them one by one so you always have a clear record of who has access to your app.

How to fix it

In the security dashboard, go to the Collaborators section and click "Approve collaborator" for each person you want to approve.


Unprotected API Workflow

To fix the Unprotected API Workflow issue, require authentication on your backend API workflows. If a workflow is publicly exposed without authentication, anyone — including bad actors — can trigger it.

How to fix it

In your Bubble editor, uncheck the "This workflow can be run without authentication" checkbox on the API workflow. If the workflow is triggered by a third-party service (like Stripe), you can still require authentication by using a Bubble API Token in the webhook URL:

  1. Go to Settings > API in your Bubble editor

  2. Click "Create a new API Token" and name it after the third-party service

  3. Copy the private key and append it to your webhook URL: https://yourappid.bubbleapps.io/version-live/api/1.1/wf/your-endpoint?api_token=XXX

  4. Update the webhook URL in your third-party service

  5. Now you can uncheck the "run without authentication" checkbox


Default Username / Password Combination

To fix the Default Username / Password Combination issue, change your test version credentials from the default values. The default combination (username: "username", password: "password") is known to every Bubble developer and can be easily guessed.

How to fix it

Go to Settings > General and replace the username and password with a strong, randomly generated combination. Use a username generator to create something that can't be guessed — for example: username: $Up%Dl@479L2yOxi, password: *WUgmv5648*iNYWy.


Public Swagger File

To fix the Public Swagger File issue, disable the public Swagger (OpenAPI) specification in your app settings — unless your business requires other developers to access your API documentation. By default, Bubble exposes a Swagger file describing all your API endpoints and data types publicly.

How to fix it

Go to Settings > API and uncheck the option to expose the Swagger file publicly. Note: hiding the Swagger file is not a substitute for proper privacy rules — obfuscation alone isn't security.


No Password Policy

To fix the No Password Policy issue, add minimum password requirements to your app. Without them, users can create weak passwords that are vulnerable to brute-force attacks.

How to fix it

Go to Settings > General and set minimum password requirements. We recommend requiring at least 8 characters, one number, one capital letter, and one non-alphanumeric character.


No Privacy Rules Defined

To fix the No Privacy Rules Defined issue, add privacy rules to any data type that contains sensitive fields. This issue is triggered when: (1) a data type has fields marked as sensitive, and (2) no privacy rules exist to protect them.

How to fix it

Define privacy rules for the flagged data type under Data > Privacy in your Bubble editor. If you believe the data type isn't actually sensitive, update the field sensitivity ratings so the dashboard reflects reality.


Public Sensitive Fields

To fix the Public Sensitive Fields issue, restrict the "Everyone else" privacy rule from seeing all fields. This issue is triggered when a data type has sensitive fields and the "Everyone else" rule is set to "See all fields".

How to fix it

In your Bubble editor, go to the privacy rules for the flagged data type and uncheck the "View all fields" checkbox from the "Everyone else" rule. If you believe public access is appropriate for that data type, you can ignore this issue.


Public Sensitive Parameter in API Call

To fix the Public Sensitive Parameter in API Call issue, mark the parameter as Private in the API Connector. This issue is flagged when an API call contains a parameter — like an API key, private ID, or sensitive endpoint — that's publicly visible.

How to fix it

In the API Connector, find the flagged API call and check the "Private" box on the sensitive parameter. If the parameter needs to be dynamic (set by the user), clear the initialization value from the API call instead — you don't need to re-initialize it. If the AI flagged something you know isn't sensitive, you can ignore the issue.


Public Sensitive URL in API Call

To fix the Public Sensitive URL in API Call issue, treat the endpoint URL as a private parameter. This issue is triggered when an API call uses a URL that could be sensitive — such as an internal Xano endpoint or a private server that doesn't require authentication.

How to fix it

In the API Connector, restructure the API call so the endpoint URL is treated as a private parameter. This prevents it from being visible in the front-end pages of your app. If you're confident the URL isn't sensitive, you can ignore the issue.


Bubble API Token

To fix the Bubble API Token issue, audit your tokens and remove any that are no longer in use. API tokens grant full admin access to your app — they bypass privacy rules entirely — so unused tokens are a real risk.

Best practices for API tokens

  • Create one unique API token per third-party service — never share a token between services

  • Name each token after the service it belongs to so you can trace any misuse

  • Delete tokens for services you no longer use

  • Do a monthly check to confirm every token in your app is actively used

How to fix it

Go to Settings > API and review all API tokens. If a token is genuinely in use, mark the issue as resolved. If it's no longer needed, delete it.


Temporary Password Vulnerability

To fix the Temporary Password Vulnerability issue, move the "Assign a temporary password" action to a backend API workflow instead of running it on a front-end page. Front-end actions are visible to anyone via the App JSON object, which exposes the credentials.

How to fix it

  1. In the backend section of your app, create a new API Workflow (e.g. "assign-temporary-password") with a user-email parameter of type text

  2. Reproduce the same logic your original front-end workflow was doing

  3. Go back to your original front-end workflow, delete all its actions, and replace them with a single action that triggers the new API workflow with the email parameter

The most secure approach is to use the "Reset Password" action instead. The "Assign a temporary password" action is intended for admin use only — don't build it into an end-user-facing flow.


Clear Data in Login Action

To fix the Clear Data in Login Action issue, replace any hardcoded email or password values in your login action with dynamic data entered by the user. Hardcoded credentials are visible to everyone on the page through the App JSON object.

How to fix it

Update your login workflow so the email and password fields reference dynamic input elements (e.g. an Email Input's value and a Password Input's value), rather than static text you typed in directly.


Test Version Protection

To fix the Test Version Protection issue, enable username/password protection on your test version. Without it, your test pages and test data are publicly accessible. This issue only appears on paid plans — the free plan doesn't support test version protection.

How to fix it

Go to Settings > General in your Bubble editor, check the box to limit access to the test version with a username and password, then define a strong, unique combination. Don't use the default "username" / "password" combination.


Database Exposure Risks

To fix the Database Exposure Risks issue, define proper privacy rules for the affected data types so each role only accesses the data it needs. The security dashboard detects this by checking your app as a non-logged-in user and looking for data leaks based on your Database Sensitivity settings.

How to fix it

Go to Data > Privacy in your Bubble editor and create rules for the flagged data types. Make sure every role is limited to only the data it should see.

Watch out: conditionals that are always true

A common mistake is writing a privacy rule condition that accidentally evaluates to true for unlogged users. For example: a rule that says "This Invoice's Company = Current User's Company" will also match invoices where the Company field is empty, because an unlogged user also has no company — and empty equals empty.

Fix this by adding an "is not empty" check: "This Invoice's Invoiced Company is not empty AND equals Current User's Company".

Issue only appears on one version?

If Database Exposure Risks only shows on one version (test or live), it's usually because:

  • Privacy rules differ between versions — push your app live to sync them

  • The test database is empty, so no data leak can be detected on the test version


Unsafe Google Maps API Token

To fix the Unsafe Google Maps API Token issue, restrict your Google Maps API key to only work from your app's domain. Your Google Maps API key is always public — the risk is that anyone can copy it and use it at your expense if it's not restricted.

How to fix it

  1. Log in to Google Cloud Console and go to APIs & Services > Credentials (direct link: console.cloud.google.com/apis/credentials)

  2. Click the API key you want to restrict

  3. Under "Set an application restriction", choose "Websites"

  4. Add your app domain and your Bubble app URL (both the normal version and the version-test version)

  5. Click Save


Public File Uploader

To fix the Public File Uploader issue, enable the "Make this file private" checkbox on the file uploader element. Without it, all uploaded files are publicly accessible — including sensitive documents like invoices or ID files.

How to fix it

In your Bubble editor, select the file uploader element, check the "Make this file private" checkbox, and link it to the appropriate data type.


Public Picture Uploader

To fix the Public Picture Uploader issue, enable the "Make this file private" checkbox on the picture uploader element. Without it, all uploaded images are publicly accessible.

How to fix it

In your Bubble editor, select the picture uploader element, check the "Make this file private" checkbox, and link it to the appropriate data type.


iFrame Restriction

To fix the iFrame Restriction issue, block your app from being rendered inside an iframe. Allowing your app to be embedded in an iframe opens it up to clickjacking, phishing, and malware distribution attacks. If your business logic requires iframe embedding, you can ignore this issue.

How to fix it

Go to Settings > General in your Bubble editor and find the "Allow to render the app in a frame/iframe (X-Frame-Options)" setting. Set it to "Block all frames".

Did this answer your question?