Security
This page lays out best practices when it comes to making your app and your data secure.
Overview
The security of any application is crucial. And it must be approached with the utmost knowledge about how Bubble works, and about all the possibilities offered by this platform to protect the data of the app owner and its users.
No app should be considered complete if at least the following security recommendations have not been followed.
Make sure you have read, understood, and applied the following security guidelines in your app.
Your Bubble account
The security of the application starts with the security of your own Bubble account.
If the security of your account is compromised, an attacker could take control of the app.
Make sure that:
You have 2FA enabled in your account.
You are using a secure password.
You don't leave your Bubble session open in unattended computers.
Other users with app access also have to contemplate this rules.
Bubble editor Settings Tab
Please review the following settings and apply them in your app editor Settings tab when applicable, thanks!
Username/password
While the application is on an Agency plan, both version-test and version-live are password protected. But when the app moves to a paid plan, password protection is not mandatory.
However, we must maintain the password for the version-test as a method of ensuring that future developments remain hidden from the public eye.
You can set up them in the Settings tab > General
of your app.
Also, we must use a username and password other than 'username' and 'password', or anyone could easily access our unpublished app (or the test-version of the already published one), since that combination is the default one in all Bubble apps.
Set minimum password requirements
Use the Define a password policy
functionality found in Settings > General
section of the Bubble editor to set the minimum length, capital letter requirements, etc.
We recommend setting a minimum password length of 8 characters and requiring 1 capital letter and 1 number.
Block all iFrames of app
If your app allows other websites to display it in an iFrame, then other developers can much more easily impersonate your website or use its content to show on their own websites. Impersonating your website is useful in the case of a phishing attack.
It is okay to allow all iFrames or iFrames from the same origin if your app has a valid reason for doing so and you are aware of the minor risks involved. Otherwise, it's best to block all iFrames of your site.
Enable SSL
SSL ensures that the data transmitted between the server and the browser is encrypted - make sure to set it up by checking the box located in the Settings > Domain/email
section of the Bubble Editor.
API
Internal API Workflows
Any API workflow exposed as public is a security risk. To avoid it, if you add a workflow that it's going to be used only internally, uncheck the Expose as a public API workflow.
Public API Workflows
Any API workflow exposed publicly is an endpoint that anyone outside our app can reach. There will be two types of them, those that:
can be run without authentication: some workflows have to be accessible without authentication, some webhooks for example.
needs authentication: most of our API workflows will need some kind of authentication. Authentication can be made:
With a temporary token: your app users can authenticated themselves via API and receive a temporary token. Once authenticated, they can access workflows and data but following the privacy rules set up for them in the editor (unless the 'Ignore privacy rules when running the workflow' is checked).
With an API Token: be careful as users authenticated with an API Token (
app editor > Settings tab > API > Generate new API Token
) have administrative privileges and full access to the database (privacy rules don't apply here).
Be careful: users authenticated with an API Token have administrative privileges and full access to the database.
As said before, while there may be some API workflows that need to be exposed and executed without authentication, this will not be the usual. For most cases with public API workflows we have to:
Limit them so they cannot be run without authentication.
Do not ignore privacy rules.
Data API
If you have your Data API enabled, make sure that only the Data types you need are enabled. Also, there should be privacy rules always in place to protect those Data types for unwanted modifications via the Data API.
As a rule of thumb, no unauthenticated user should be able to Create, Delete, or Modify objects via API.
Swagger
The Swagger Specification is a standard way to describe an API. It can be used to generate a documentation, or to let other tools integrate with the API. Bubble provides a Swagger Specification out-of-the-box when you activate the API for your application. To get it you can hit the endpoint:
https://appname.bubbleapps.io/api/1.1/meta/swagger.json
or
https://yourdomain.com/api/1.1/meta/swagger.json
You can read here more details about the Swagger Specification standard.
You should hide your Swagger file if you don't want others to access your endpoints. Even though your endpoints should be already secured if you had built them correctly, you don't want to expose them for an attacker to try to access them.
Collaborators
Granting access to the app is something that cannot be done lightly. Adding collaborators to the app with full access could be a dangerous security hole for your app.
Be very careful who can access live data as there are multiple regulations protecting privacy, access, and data management.
Follow this rules to minimize the security risks that collaborators can pose to the app:
Only add new collaborators if they need to have access to the app.
Only add the permissions the user needs to do his/her job.
Remove users once they have finished their work on the app.
Permissions are granular: App access, Data access, Log access. And not every collaborator needs access to all of them. Assign them on a "needs to know" basis.
API Connector
Don't use private API keys/tokens on the page
If you need to make an API call that uses a secret key or a token, make sure that it's not populated on any page but is instead in one of these 2 places:
In the API connector, marked as "Private": if the value is fixed.
In a backend workflow: If we need the value to be populated dynamically but we don't want it to be exposed in the page.
This will ensure that the user's browser never sees the API key/token.
Be careful with 'Attempt to make the call from the browser'
All API calls that you make from the API Connector are made from Bubble's server except if you check the 'Attempt to make the call from the browser' option.
Note that if the API or API call configuration have any headers, non-private parameters, or shared headers/parameters, the checkbox will disappear, since any such call cannot be done from the browser.
This feature is useful, for example, if we are dealing with an API that limit the number of calls made from a single IP address. If all API calls with such limits go through Bubble it could end up reaching that limit quickly, as all apps in the same server would “shared” the same limit. With this feature, this should won't happen, and each user’s browser will have its own limit.
Uncheck a parameter that should be private to be able to make the call from the browser is a serious breach in our app security and it cannot be done.
Some examples of API calls that won't be made from the browser in any case: API Calls that happen in Actions, API calls that happen from the editor (e.g. call to initialize the API Call). Anything requiring headers or authentication.
Building your app
Create privacy rules
Having robust privacy rules is essential in making sure that your server doesn't set data to a browser that the user is not supposed to see.
Privacy rules are the foundation of any Bubble app and have to be carefully thought and set up from the moment you start planning the app and its database.
See link below for more information about setting those up.
Database / privacy rules https://docs.airdev.co/canvas/using-bubble/database#privacy-rules
We also have a video walkthrough for Bubble Privacy Rules.
Understanding client vs server
It's important to understand the difference between:
'client': the frontend, the page, what the user sees in her/his computer.
and the 'server': the backend, where some actions take place: recurring events and database change trigger events.
You have to understand one thing: any data that's already in the client (the page, the user browser) is already exposed. Even though you can hide something on the frontend, or not show it, or not access it, an attacker could access it and/or change it.
Consequently:
Don't try to hide information by hiding an element in the page.
Don't download any data to the client that you don't want exposed (searches, variables, etc.).
A practical example of this is applying a condition to a workflow: Let's imagine that you want only users with the Role 'Boss' to make a change to a thing.
To do so, you apply a condition to the action to check that the user role is Boss, and you use the 'var - Current user role', a variable hosted in a group in the page:
That condition can be hacked because is checked in the page, hence an attacker could change the value of the 'var - Current user role' as that info is already in the page.
If, instead, you use this condition:
This condition cannot be hacked because is checked in the Server. An attacker cannot change the value of the user role in Bubble servers.
Just remember: any important check has to be performed in the server, not in the page.
How to access data protected by privacy rules
Sometimes you need to check, compare or access some data that is protected behind privacy rules.
For example: you need someone to enter their email and you check to see if there's a matching record and return an ID without exposing all the search results. In this case you can trigger an API worflow vs. running a search query in the page.
User roles
Canvas uses a combination of two Option sets, 'Role' and 'Bubble Pages', and a workflow in the 'header' reusable to redirect users out of a page if they don't have the appropriate role.
You have to remember to update the 'Bubble page' Option set, adding new pages to it as you add them to the app, and setting up its attributes correctly:
Add new pages to the 'Bubble page' Option set.
Set their attributes correctly: Is private? and Roles.
Make sure that all pages have their Bubble page Option set correctly set up.
Add the action to check the role, and redirect the user if needed, to new pages added to the app that don't have the 'header' reusable.
Careful: If set up correctly (second screenshot), the redirection prevents the user from loading any content in the page if he/she tries to enter and load the page, but if the user is already in the page, and then his/her role is changed, an enough tech savvy user could still be able to stop the redirection and access all the data already in the page.
No "paywall" popups
In Bubble, you can create a popup that blocks the user from visually seeing or interacting with the page. However, these popups can be closed relatively easily using Developer Tools in the browser.
To put this in specific "Bubble-ese": you shouldn't rely on a popup with the setting This popup can't be closed by pressing Esc
to lock users out of pages.
Don't store sensitive data in an unencrypted format
If your application needs to store very sensitive data, like Social Security numbers, credit card numbers, etc. in encrypted format. Better yet, find another company (like Stripe or Paypal) that can handle these very risky transactions, and integrate them into your app through Bubble plugins or using the API Connector.
Bubble does encrypt all data at rest, which makes data storage and data usage more safe if you have authentication and privacy rules properly set up. But if you've accidentally made your privacy rules more loose than they should be, someone may get a hold of your data. We would recommend encrypting the values that go into those sensitive fields yourself and then decrypting them before they're used.
Scanning files for malware
When users have the ability to upload files to your app that other users can download, ideally they should be scanned for malware. Some API based solutions for this include Scanii and Cloudmersive. Filestack also offers this option along with their file storage service, but is quite pricey.
This will help protect both admin users and standard users - if admins open these files somewhere in the admin portal or are sent these files via email, that would be an issue.
Note that some browsers (e.g. Chrome in Windows) have some built-in file scanning ability as well to prevent downloading files tagged as malware, so there are some built-in protections here for many users.
Other security risks
Risks from plugins and custom code
Using community plugins and custom HTML in your Bubble app carries some inherent security risks with it.
One of those risks is that the plugin developer could be malicious and steal data from you, like by tracking all browsers which load the plugin on the front end.
Only use plugins from trusted developers.
And, if the plugin has been published with an Open Source license, its code is visible and can be reviewed to ensure it's secure to use.
XSS (cross site scripting)
Another risk is the possibility that plugins will allow raw user data to run javascript in other users' browsers.
Bubble's native elements should all have protections built in to prevent users from executing javascript when users' data is shown to other users. Plugins, however, may not all have this set up. (The Bubble HTML element, of course, is an exception here, as it is intended to be able to include HTML and javascript.)
This is a risk when showing data on the front-end to users - for example, if I have a calendar plugin and I use it to display data from many users to each other, it's possible that one user will enter some executable code in a text field and that the plugin will execute that code when trying to display it. There are many different ways to exploit XSS vulnerabilities, so the specific ways to test this will not be covered here.
CSV injection
When allowing for CSVs of user-entered data to be downloaded from an app, programs like Excel will read Formulas that are included in those CSVs. If a user's "About" field has a formula, they can use it to execute programs outside of Excel, or hit APIs and export the app data. More info about the vulnerability here: https://owasp.org/www-community/attacks/CSV_Injection
For a Bubble-specific guide on how to deal with this bug, see here:
This is a known bug with Canvas' CSV export flow in the admin portal. We've decided to leave this vulnerability there for the moment, as it would add quite a bit of complexity to the app to remove it. All app admins should be made aware of this vulnerability.
Unsafe HTML in emails (phishing)
Emails can be used as a vector to steal user data, user credentials and other sensitive info. This relatively simple attack has been the cause of several high-profile cybersecurity breaches over the past few years.
Other resources
Forum resources
If you're interested in learning more about how Bubble secures data in general, and some other security recommendations, you can read these security guidelines from early 2019 posted in the Bubble Forum by Josh (Bubble CTO and co-founder).
Testing privacy rules
To test whether privacy rules are set up correctly, it can be helpful to use a web browser's developer tools to examine what data is available to the user. Here's a page that shows how to do that with Chrome.
Privacy rules
Check whether your privacy rules are properly set up with Chrome dev tools.
Bubble documentation on setting up privacy rules.