Page security

This section covers security on pages, elements and workflows

As we explored in the section about client-side and server-side operations, Bubble downloads data to and completes a number of processes directly on the user's device.

In principle, every piece of data that reaches the user's device is no longer secure. As long as you are only sending data that the user should have access to, this is not a vulnerability but the only way your app can work.

If you are new to Bubble or web development in general, it's not necessarily obvious what this entails, so in this article, we'll have a look at the precautions you should take to avoid sharing more data with your users than you intended.

Think of the page as a bank and app's data types as a collection of safety deposit boxes. If a user gets access to the bank (page), the private information is still safely contained within the safety deposit boxes (database), and they are all locked (privacy rules).

All the intruder sees is the lobby.

Bubble's JavaScript/JSON files

Whenever a user loads a page in your app, their browser downloads a collection of JavaScript and JSON files. Some of them make up the "engine" that's common to all Bubble apps, while others contain code and data tailored to your specific app and the currently loaded page – everything that makes your app and page different from any other page of any other Bubble app.

These files contain code that allows your app to communicate with the Bubble server, and send and receive data and commands between the two computers (your user's device and the Bubble server).

These files are stored on the user’s device, and a tech-savvy user can open up the downloaded files and look at the code. This is not in itself a vulnerability, but it means you as a Bubble developer need to be mindful of what kind of data you place in that code.

As a no-code platform, Bubble automatically generates the code for your app, which can inadvertently introduce vulnerabilities if you're not cautious about the information you store in your pages.

Option sets

Option sets are a useful way to store static data that you can reference anywhere in your app. Option sets are downloaded along with the rest of your app's code and is decrypted and stored as plaintext on your user's device. As such, you should never place any sensitive data in an Option set. This includes the name of the set itself, and its different options and attributes, as well as the data stored in them.

App texts (translation strings)

The app text feature found in Settings - Languages is a useful way to translate static text strings so that your users can see your app in different languages. Bubble downloads the strings that are relevant for the current user’s language. These strings should not be considered secure: never store sensitive information in app texts in any language.

Elements

Whenever you store static data in an element, you should assume that the data becomes part of your application's code. For example, let's say you place a text input element on the screen that has the Placeholder text "Name", that placeholder will be visible in the app's code.

Avoid placing any kind of sensitive information in your elements, even if they are hidden on page load.

Page name

Bubble downloads the name of all your pages on each page load. In other words, even if a user is just loading one page, the code still contains the name of all other pages. Don't give your pages names that contain any sensitive data, and don't assume that a page that you are not linking to is secure – a user looking at the app's code can identify the names of each one.

You can also consider giving important, secure pages names that differ from the norm: for example, a page called admin or login may be targeted by bot networks simply because it shares such a widely used label. If you use a more uncommon name, you may avoid the wide net that's cast looking for standard names.

Bear in mind that while this adds a layer of obscurity, it shouldn't be seen as a standalone security measure. It will not stop an unwelcome visitor from finding the page, but may make it slightly more difficult.

Workflows

Just like with elements, when static data is stored in workflows, it becomes a part of Bubble's codebase. Some data is sent to the user's device when a workflow's result is processed, and this information might become accessible on that device. This includes any data kept in an element's state during the workflow, as these element states reside on the client side.

Additionally, the IDs (but not the fields) of objects that the workflow altered are included. These IDs are necessary to ensure that the changes are immediately visible in the browser. While this data sharing is part of the regular function of the web app, it's something to be aware of as you manage what information is passed between the server and the client.

Data types

The following information about all data types is also visible in the code:

  • The name of each data type

  • The name of all the fields saved on all data types

  • The default value of those fields as specified in Data - Data types

The data that you store in these data types in the database are encrypted and secure while in storage.

API Connector Calls

The API Connector allows you to set up different calls to be used in actions and as . The following information will be visible in the app code:

  • The name of each call

  • The key and value of each parameter, unless they are set to private

  • The URL of each call, unless you specify the URL in a parameter by using []

Deleted fields, data types, option sets and option set attributes

When you delete one of the things specified in the header, they are not permanently deleted, but are kept around in case you want to undo the action. You can clean out this deleted info by using the Optimize app feature.

To access the Optimize app feature, go to Settings - General and click the Optimize app button.

Conditions

Conditions can be processed directly on the client or needs to involve the server, depending on the that you use. If you use a condition on an important workflow event or action, it's more secure to set up a condition that involves the server; that way, the processing is done out of reach of the user.

To make sure a condition is processed server-side, you can involve anything having to do with the database or user authentication. For example, Current user is logged in and Do a search for:count > 0 are both conditions that Bubble will query the server to process.

Additionally, if the condition is placed on a server-side action, both the condition and the action will be processed on the server. The exception is if the condition can't be processed on the server. For example, Element X is visible needs to be checked on the page, and can result in a more vulnerable condition.

Redirects

users from one page to another can be done in two ways:

  • redirects occur directly in the user's browser. When a certain condition is met or an event occurs (like clicking a button) and the Got to page action runs, a script running in the user's browser will change the current URL, causing the browser to load a new page. This happens without any interaction with the server.

  • redirects, occur when the server responds to a request from the browser by instructing it to load a different page. This too is done with the Go to page action, but only under the following conditions:

    • It happens before the page has loaded

    • One of the events below triggers the redirect:

      • User is logged in

      • User is logged out

      • Page is loaded

    • The workflow contains only one action (Go to page)

    • The redirect does not (such as within the URL)

Server-side redirects are more secure than client-side redirects, since Bubble will redirect to the new page before any data from the first page is downloaded. A client-side redirect, on the other hand, will redirect after the page has loaded, using JavaScript executed in the browser.

It's important to keep in mind that while you should try to ensure server-side redirects for secure pages, all data and workflows on the page still need to be protected by Privacy Rules and conditions.

Summary

In principle, everything that reaches your user's device is no longer encrypted and private, but is stored as plaintext on that device. While it may not be visible to most users, a tech-savvy user can open up the downloaded files and track the data coming and going through the network to see its content. This is why it's important to:

  • Set up privacy rules for all data types and fields that are private

  • Never store sensitive data like personal information and API keys in elements, events, actions or conditions

  • Set up server-side redirects to guide users away from pages to which they shouldn't have access

  • Treat the page as a bank: it may be closed, but if people manage to break in, all the valuables are still locked safely inside locked safety deposit boxes

Last updated

#829: Flusk: more detailed Issue Descriptions

Change request updated