Skip to content
LockShip

Guide · Base44 · Updated

Is my Base44 app secure? A plain check before you launch

You described an app to Base44, it built the pages, the database and the login, and now there is a .base44.app address you’re about to send to real people. That moment is exciting, and it is also the moment to slow down for one evening. Look at the app the way a stranger would. This is the list we would work through on our own app, in plain words, with yours open in the next tab. Nobody can promise you an app is secure, us included. What you can do is check the handful of places where the trouble usually is.

New to this? Start with our vibe coding security checklist, eleven checks for any AI-built app, whatever tool made it. This guide goes deeper on apps built with Base44.

The honest short answer

Base44, which is owned by Wix, does a lot for you. Its security overview lists a security scan on every plan, data permissions it sets up as it builds, an encrypted place for API keys, optional single sign-on, and platform work like SOC 2 Type II and ISO 27001 certification and encryption at rest and in transit. Then, in a warning box near the top, it says the sentence that matters most: “You are responsible for your app’s security settings. Base44 provides the tools, but always review your permissions and run a security scan before you publish.”

We like that they say it out loud, because it is true for every builder. Base44 can keep its own platform safe. It can’t know that your customers should only see their own bookings, or that only you should be able to change prices. So the useful question isn’t “is Base44 secure?” It’s “does every table and every function in my app check who is asking, and is everything I published meant to be open?” You can find out yourself, and most of it takes an evening.

What happened in July 2025

It helps to know the one big Base44 incident, because it shows what “private” can mean on a shared platform. On 9 July 2025, Wiz Research reported a flaw to Base44 and Wix. Two sign-up endpoints, api/apps/{app_id}/auth/register and api/apps/{app_id}/auth/verify-otp, answered anyone. All they needed was the app’s app_id, and that was no secret: Wiz found it in every app’s address and in its manifest.json path. With it, a stranger could create a verified account on a private app, even one set to SSO only, and then sign in. Wiz says it confirmed this on several company apps used for internal chatbots, knowledge bases, and HR and personal data.

Wix fixed it in less than 24 hours, so that registration now checks the app’s privacy setting. Wiz verified the fix the next day, and Wix said it found no evidence that anyone had abused the flaw. Because the fix was on Base44’s side, there is nothing for you to patch. The Hacker News covered the same disclosure. If you ran a private app back then, Wiz suggested looking at your app’s analytics for unusual visits and registrations from that period.

The lesson we take from it is a quiet one. Your app’s address and ID are public. Anything that is meant to be private has to be enforced by a rule somewhere, every time someone asks, and it is worth checking that rule yourself instead of trusting a label.

What your Base44 app is made of

  • Pages that run in your visitor’s browser.
  • Data tables, which Base44’s developer docs call entities. Each table has its own data permissions for Create, Read, Update and Delete.
  • Login and roles. Built-in login, register and password reset pages, with email and password, Google and other sign-in methods. Every app starts with two roles, Admin and User.
  • Backend functions, small pieces of server code that run on Base44. The functions docs say each one gets its own address at /functions/ followed by its name.
  • Secrets, where API keys for other services go. Base44 says they are encrypted and only reachable from your app’s backend.

The browser asks Base44 for data, and the rules on each table decide what comes back. That makes data permissions the main lock, the same role Row Level Security plays in a Lovable or Bolt app built on Supabase. Backend functions are the second lock, because anyone can call their address.

The eight checks

Do them in order. The first three are settings you can fix in minutes. Checks 4, 5 and 6 take longer, and they’re the ones most likely to matter. Only test an app you own, and write down anything you change.

  1. Run Base44’s security scan, and read every finding
  2. Decide who the app is for before you share the link
  3. Look at who can sign up, and who already has
  4. Give every table a rule, and don’t leave personal data on All Users
  5. Try to open another person’s record on purpose
  6. Knock on your backend functions without signing in
  7. Keep keys in secrets, and paid calls out of the browser
  8. Turn on the browser protections Base44 lets you set

01

Run Base44’s security scan, and read every finding

Start with what Base44 already gives you. Click Dashboard, then Security, then Run Security Scan. Base44’s scan docs say it is available on every plan, including the free one, and checks for seven kinds of issue: data permission issues, exposed secrets, unauthenticated backend functions, credit protection, app dependencies, code vulnerabilities, and security header recommendations. The code vulnerability part needs the Builder plan or above. If your workspace already uses Wiz, you can also connect it and see its findings on the same page.

Three things in those docs are worth knowing before you click anything. The scan doesn’t apply fixes on its own, so read what each one changes. When you publish, the publish panel shows your security status, but in Base44’s words, “It warns you, but it doesn’t stop you from publishing.” And an issue you mark as Ignore stays ignored on every later scan, so only ignore something you understand. Each fix creates a checkpoint in the AI chat first, so if a fix breaks a page, you can roll it back.

Run it again after any big change, like a new table, new permissions or a new integration. Then keep going, because the scan checks patterns. It doesn’t know who your app is for.

02

Decide who the app is for before you share the link

This sounds too simple to matter. It is the one that got thousands of vibe-coded apps into the news. In May 2026, WIRED reported that the security firm RedAccess had found more than 5,000 apps built with Lovable, Replit, Base44 and Netlify with “virtually no security or authentication of any kind,” many of them found with ordinary searches for the builders’ hosting domains.

Open Dashboard, then Overview, and look at App Visibility. Base44’s access docs list three levels:

  • Public: anyone on the internet can open it. Base44’s FAQ adds that on a Public app, “anyone can create an account from your register page and sign in.”
  • Private: only people you invite, and they have to sign in. This needs a paid plan.
  • Workspace: everyone in your Base44 workspace, signed in.

Base44 picks a starting point for you. Apps that act like public sites, such as landing pages or portfolios, are set to Public without login automatically. So ask the plain question: who is this app for? If the answer is “my team” or “a few clients,” it shouldn’t be Public. If the answer is “anyone who signs up,” Public is right, and then the rules on your tables are the lock. If you’re not sure what yours is set to, ask the AI chat in Discuss mode:

Prompt for Base44
Tell me this app's current App Visibility setting (Public, Private or Workspace), whether people have to sign in, and whether anyone can register on their own. This app is for: [describe it, e.g. "only my team" or "anyone who signs up"]. If the setting doesn't match that, tell me what to change before you change anything.

A bad result here is an app full of customer or team data that says Public and lets anyone register. Fix that before anything else.

03

Look at who can sign up, and who already has

Open Dashboard, then App Users, and read the list slowly. Are there accounts you don’t recognise? Old test accounts with the Admin role? People who left the project? You can remove anyone from the same screen, and Base44 keeps removed users under Recently deleted in case you remove the wrong one.

Two details from Base44’s access docs are easy to miss. On a Public app, people with the ordinary User role can invite other people, while on a Private app only admins can. And anyone you add as a collaborator, so they can help in the editor, is given the Admin role in your live app by default. If they only need to build, check their role afterwards.

Then open the Authentication settings and look at which sign-in methods are switched on. Turn off any you don’t use. If your app is meant for one company, SSO with that company’s accounts is the strongest option Base44 offers. That was also the setting the 2025 flaw got around, which is why we still check this list by hand.

04

Give every table a rule, and don’t leave personal data on All Users

This is the check we would bet on. Broken access control sits at the top of the OWASP Top 10, and on Base44 it lives in one place: the permissions on each table. Base44’s developer docs for creating entities put the risk in one sentence: “If no RLS is defined, all records are accessible to all users.”

Click Dashboard, then a table under Data, then Permissions in the top right. A warning icon on that button means Base44 already thinks something is off. The permissions docs describe four rules:

  • All Users: anyone can do this, “even without signing in.” Right for a product catalogue or blog posts. Wrong for anything personal.
  • Creator Only: people only reach records they created. The usual choice for orders, messages and form submissions.
  • Entity-User Field Comparison: a field on the record has to match the signed-in person, like an assigned_to field matching their email.
  • User Property Check: only people with a certain role or property, like Admin, can do it.

Go through every table and say out loud who should read it. A contact form is a good example from Base44’s own docs: All Users on Create so anyone can send a message, and an admin-only check on Read, Update and Delete so only you see them. If a person matches any one rule, they get in, so one stray All Users on Read opens the whole table no matter what else is there. That is the bad result to look for. If you see a Permission risks detected banner, read the recommendation before you apply it. To set everything in one go, describe your app in your own words:

Prompt for Base44
Here is who should see what in this app: [describe it, e.g. "each customer sees and edits only their own bookings; staff can see all bookings; only admins can delete"]. Go through every data table and set Create, Read, Update and Delete so that rule holds. Use Creator Only or an Entity-User Field Comparison for anything personal, and a User Property Check for admin-only actions. Don't use All Users on Read for any table that holds personal data. List every table, what its rules were, what they are now, and which ones still allow All Users on purpose.

Two more things. Base44 locks down the built-in Users table, so if a member profile page only works for admins, don’t open that table up; the access docs suggest a separate UserProfile table instead. And if you or a developer ever change permissions through the API, Base44 warns that the change can be replaced the next time the table’s file is saved. Make permission changes on the Permissions page or through the AI chat, so they stick.

05

Try to open another person’s record on purpose

Check 4 is about reading the rules. This one is about seeing them hold. The mistake behind most data leaks in apps like these has a name, broken object level authorization, and it looks like this: someone is signed in, opens their own booking, changes one thing in the address, and is looking at somebody else’s.

Base44 makes this test easy. On a table’s Permissions page, click Test Permissions in preview, or use Act as a user from the editor’s menu, and pick a person. You see the app exactly as they do. Make two sample users, add a record as the first, then switch to the second and try to reach it: from the list, from the detail page, and by pasting the first person’s address for that record. Base44’s security docs say a blocked list comes back empty and a blocked single record looks like it doesn’t exist, so “nothing there” is the good result. Seeing the first person’s record is the bad one.

Do the same with an ordinary user against every admin screen. A hidden menu isn’t a lock; the rule on the table has to say no. Base44 warns that anything you change while acting as someone is saved to their data, so use sample people, or turn on a separate test database first.

06

Knock on your backend functions without signing in

Backend functions are where table rules can quietly stop applying. Base44’s security docs say a function can use base44.asServiceRole, which “bypasses both RLS and FLS entirely,” and that “your function is responsible for any access checks it needs.” The functions docs add that each function has its own web address, and when it’s called directly, with curl or as a webhook, “there’s no authenticated user context.” Put those together and a function that reads with the service role and never asks who is calling will hand anyone every record.

The scan’s Unauthenticated backend functions section is the first place to look. If your app requires login, each open function shows as Anyone can run this function, and Fix with AI makes it require a signed-in user. Base44 warns that this can break a page for signed-out visitors, a webhook, or an integration that calls the function, so test those afterwards. If your app doesn’t require login, every function is open by design, and the riskier ones, such as those that write data or use AI, are marked High.

To see it for yourself, find your function names on Dashboard, API, under Backend Functions. Pick one that only reads data, and call it the way a stranger would, with no login:

Terminal
# Replace YOUR-APP and FUNCTION_NAME. Only for a function that reads data.
curl -i -X POST https://YOUR-APP.base44.app/functions/FUNCTION_NAME \
  -H "Content-Type: application/json" -d '{}'

A function that checks who is asking, like the example in Base44’s own docs, answers 401 with Unauthorized. A 200 with real records in it is the bad result. This really runs the function, so don’t do it for one that sends email, writes records, takes payments or calls an AI model; for those, read the scan’s list and ask the AI chat to show you the check at the top of the code. To fix them all at once:

Prompt for Base44
Go through every backend function. For each one that reads or changes user data, make it call base44.auth.me() first and return 401 if there is no signed-in user, then only read or change records that belong to that user. Don't use asServiceRole unless the function truly needs it, and if it does, check ownership in the code before touching any record. For webhooks that must stay open, verify the caller with the provider's signature or a shared secret instead. List every function, whether it needed a check, and what it checks now. Don't change anything else.

07

Keep keys in secrets, and paid calls out of the browser

Keys for OpenAI, Stripe, Resend or anything else belong in secrets. Base44’s API reference says secrets are made available to backend functions as environment variables, and the CLI docs show how functions read them. The scan’s own FAQ gives the rule in one line: handle all requests to third-party services in backend functions and store the keys as secrets. A key written into a page is a key every visitor can download.

There is a cost side to this too. The scan has a Credit protection check for AI, image and email features that can be reached from outside your app, including AI calls made from your pages in the browser. Someone who finds them can spend your credits. If you see Prevent unauthorized credit usage, take it seriously, and fix it before you share the link anywhere busy.

Prompt for Base44
Find every place the pages of this app hold an API key, token or password for another service, or call a paid service (AI, email, image generation) straight from the browser. Move each of those calls into a backend function, store the key as a secret, and read it there. Remove the key from anything a visitor's browser downloads. List what you moved. Don't change anything else.

Then check what your live app really ships. On your own computer, this downloads the scripts your homepage loads and searches them for key-shaped strings:

Terminal
APP=https://YOUR-APP.base44.app

# 1. The scripts your homepage loads
curl -s "$APP/" | grep -oE '(src|href)="/[^"]+\.js"' | cut -d'"' -f2 | sort -u \
  | while read -r f; do curl -s "$APP$f"; done > app.js

# 2. Anything shaped like a secret key
grep -ohE "sk-(proj|ant)-[A-Za-z0-9_-]{20,}|sk_live_[A-Za-z0-9]+|rk_live_[A-Za-z0-9]+|whsec_[A-Za-z0-9]+|AKIA[0-9A-Z]{16}|re_[A-Za-z0-9]{8}_[A-Za-z0-9]{20,}" app.js | sort -u

Nothing printed is what you want. A real key in the output means you should treat it as already public. Rotate it at the provider first, then put the new one in secrets and move the call into a backend function. Our guide to leaked API keys in your frontend bundle has a longer script that follows every file a page loads later, and the order to rotate in.

One more key to guard: the personal access tokens your app’s API page asks for. Base44 says they work like a password for your app’s data and warns against pasting them into an AI chat, a shared document or a screenshot. If one gets out, delete it on the access tokens page and make a new one.

08

Turn on the browser protections Base44 lets you set

Headers matter less than everything above, and a missing one won’t leak data on its own. Base44 is unusually clear about what you can set. Its security overview says you can choose which websites may show your app in an iframe and keep content from other sites from using the camera, microphone and location, and that “Other HTTP-level headers, such as Content-Security-Policy and Strict-Transport-Security, are not configurable at the individual app level.” CORS is managed by Base44 too, and its public endpoints are rate-limited by default.

So turn on what you can. Click Dashboard, then Settings, and under Browser Security set iFrame embedding to No websites unless you really embed the app somewhere, and switch on Protect camera and location. The scan docs say these are the two header settings the scan checks. Then see what your live app sends:

Terminal
curl -sI https://YOUR-APP.base44.app \
  | grep -iE "^(x-frame-options|content-security-policy|permissions-policy|strict-transport-security|x-content-type-options|referrer-policy)"

One detail from the same overview is worth knowing: Base44 stores sign-in tokens in the browser’s localStorage, and HttpOnly cookies aren’t available. That means any script running on your page could read them, which is one more reason not to paste third-party scripts or widgets into your app casually. If you later put your own domain behind a proxy that can add headers, our security headers guide has a tested starter policy, and MDN explains what each part does. Base44’s domain docs cover connecting your own domain.

What a clean result means

If you got through all eight and found nothing, that’s genuinely good news, and you earned it. It means nothing obvious is open today, not that the app is safe forever. The next table the AI creates gets its own permissions, and the next function can skip its check. Repeat checks 4, 5 and 6 whenever you add something that saves or shows data, and run Base44’s scan before every publish.

Where LockShip fits

We built LockShip because the outside-in parts of this list are easy to forget and dull to repeat. You paste your app’s address and prove you own it with a meta tag, a file at /.well-known/lockship.txt, or a DNS record if you use your own domain. Then the scan reads your app the way a stranger would. It downloads your homepage and a few pages linked from it (GET only, skipping links that look like logout, delete or checkout), follows the scripts they load, reads any public source maps, and searches all of it for secret keys such as OpenAI, Anthropic and Stripe keys. It tries /.env and /.git. It reads your headers, the cookie your homepage sets, your CORS answer to a made-up origin, and your certificate. If your pages use Supabase or Firebase, it checks what their public keys can read.

On a Base44 app, it matters even more to say what it doesn’t do. It doesn’t recognise Base44 by name yet, so its fix prompts are the general ones rather than written for Base44’s chat. It never signs in, so it can’t see your dashboard, your app visibility, your users, your table permissions or your secrets, and it can’t do the two-account test in check 5. It only calls addresses your JavaScript names that look like /api/ routes or Supabase functions, once each, with a plain GET, so it won’t knock on your Base44 backend functions for you. Since Base44 doesn’t let you set a content security policy or HSTS on its own hosting, the scan may report those as missing, and on Base44 hosting the honest fix is the workaround in check 8 or accepting it. It is a point-in-time, best-effort check, not a penetration test. A clean result means “nothing obvious from the outside right now,” not “safe.”

The summary is free: a score and the single worst thing we found. If you want everything, the $39 Launch Safe certificate includes every finding with a fix prompt you can paste into Base44’s chat, a PDF, and seven days of re-scans while you fix things. A passing re-scan gives you a badge you can put on your site.

Want a second pair of eyes from the outside?

Paste your Base44 app’s address, prove you own it, and see what a stranger can read. The summary is free.

Run a free scan

Before you rely on a result, read the disclaimer.

Questions people ask

Base44 already has a security scan. Do I still need to do this?

Keep the scan, and run it before you publish. But Base44’s own docs say you are responsible for your app’s security settings, and the scan warns you without stopping you from publishing. It also can’t know your rules, like “customers only see their own bookings.” Checks 4, 5 and 6 are about exactly that, and they take an evening.

Was my app affected by the Base44 vulnerability Wiz found?

Wiz reported it on 9 July 2025 and Wix fixed it within 24 hours. Anyone who knew an app’s app_id, which is visible in the app’s address, could register a verified account on a private app, even one set to SSO only. Wix said it found no evidence of abuse, and the fix was on Base44’s side, so there is nothing to patch. Wiz suggested reviewing your app’s analytics for unusual visits and registrations on private apps from that period.

Is my Base44 app public?

Check App Visibility under Dashboard, Overview. Public means anyone on the internet can open it, and anyone can create an account from your register page. Private means only invited people, and needs a paid plan. Workspace means everyone in your Base44 workspace. Base44 sets apps that look like public sites, such as landing pages, to Public without login automatically, so look rather than assume.

What happens if a table has no permission rules?

Base44’s developer docs say that if no row level security is defined, all records are accessible to all users. In the permissions editor, All Users means anyone can do that action, even without signing in. That is fine for a product catalogue and wrong for orders, messages or anything personal.

Can LockShip check my Base44 permissions?

Not from the inside. A LockShip scan only sees what a stranger’s browser sees at your public address. It never signs in and never sees your dashboard, so it can’t read your permission rules, your app visibility, your users or your secrets. It also doesn’t recognise Base44 by name yet, so its fix prompts are the general ones. Use it next to Base44’s own scan, not instead of it.

Keep reading

Sources

We read each of these on 19 October 2026. Base44’s menus and plans change quickly, so if something here disagrees with its docs, trust the docs and tell us at hi@lockship.dev. The commands above are for apps you own; we didn’t run them against anyone else’s.