Base44 app security starts with the generated data layer
Base44 generates a full-stack app from a description: the frontend, a hosted URL, user logins, and a backend with a data layer, all wired up so the app works on the first run. That is the appeal, and it is also why a base44 app security review has to focus on the part you did not write by hand. The frontend is visible; the data-access rules behind it are not, and they are where the launch risk concentrates.
The concrete risk is this: the app can return data to a caller who should not have it. That happens in a few specific ways, and they are not equally observable. Some you can confirm from a clean browser in minutes. One of them, whether the backend enforces the right per-user and per-record rules, is a configuration decision that does not show up reliably from the outside and needs a look at the actual settings.
So this note splits the review into two columns. First, the checks you can run yourself on your own public URL while logged out. Second, the questions a public check cannot settle, which is most of the authorization story. Keep those separate, because a clean result on the first column does not answer the second.
What you can check from the public surface, logged out
Open your deployed app in a private or incognito window, with no account signed in. That is the state a stranger or a crawler arrives in, and it is the right vantage point for these four checks.
Each of these tells you something real about your own exposed surface. None of them tells you whether the data that is reachable is correctly scoped per user. That is the next column.
- Which routes respond without authentication. Walk the app while logged out and watch what loads. A marketing page or a login screen responding is expected. A page that shows real records, a dashboard, or anything you assumed required a login responding with data is the suspicious result. Note the routes that render content you did not expect to be public.
- Whether data endpoints answer to an anonymous caller. Open DevTools, go to the Network tab, and watch the requests the app makes as it loads. Base44 apps read and write through a backend data API, so you will see calls to data endpoints. The question is what they return with no session. An endpoint that returns an empty list or an authentication error for data that should be private is the safe result. An endpoint that returns rows of real records to a logged-out caller is the one to flag. Test reads and, carefully on your own app only, whether a write is accepted.
- Security headers on the hosted URL. Read the response headers on your home page and on an app route. Missing Content-Security-Policy, no framing protection (X-Frame-Options or a frame-ancestors directive), and no nosniff mean the browser falls back to its most permissive behavior. This is configuration, not application logic, so it is a fast win to confirm and to fix.
- Admin or management routes that are reachable. Try the obvious paths while logged out: an admin route, a settings or management page, anything that controls the app rather than uses it. A redirect to login or a clean denial is the safe result. A management screen that renders, even partially, without a session is a finding.
Why Base44 apps land here
Base44 generates the authentication and the data layer automatically, which is the feature. It also means the access decisions are made by the generator and your prompt, not by a deliberate per-entity review. Base44's own model gives each data entity row-level and field-level security rules, so the controls exist. The gap is that whether they are set tightly is determined when the entity is created, and a prompt that says "store user notes" produces a working table and a working screen without forcing you to decide who may read each row.
That is the same generated-insecure-default pattern that shows up across AI builders; the broader catalog is in AI-generated insecure defaults. The specific shape here is:
- The app works end to end on the first run, so a too-permissive rule is invisible from inside the app. Everything you test as the logged-in builder looks correct.
- Authentication being wired up can read as "the data is protected," but authentication only proves who is calling. Whether that caller is allowed to read a given record is authorization, a separate rule.
- The hosted URL exists immediately, so the public surface is live before anyone audits which endpoints answer and to whom.
What to tighten, and what the public checks do not cover
For the things you confirmed from the outside, the fixes are direct. Gate the routes that returned content to a logged-out caller so they require a session. Add the missing security headers in your app configuration. Put admin and management paths behind an authorization check, not just behind a hidden URL. Re-run the same logged-out checks afterward to confirm the behavior changed.
The harder part is the data-access rules, and this is where honesty matters more than a checklist. Whether your Base44 entities enforce the right per-user and per-record authorization is set in the entity security rules, and that is a configuration and code-level decision. You verify it by reviewing those rules entity by entity and by testing what a second, different logged-in account can read, not by reading response headers. A rule that returns every record to any authenticated user is still "authenticated," and it will pass a login check while leaking across users.
So the public checks give you a real, reproducible answer about your exposed surface, and they are worth running before the URL spreads because that surface is the easiest thing for anyone to inspect. They do not certify that the authorization model is correct. Treat them as the first pass.
Authentication and authorization are different gates. A logged-out check tells you whether the door is open to strangers. It does not tell you whether two logged-in users can see each other's data. That second question lives in the per-entity rules and needs manual review.
Where VibeCodeGuard fits, and what it does not prove
VibeCodeGuard's Launch Check probes the Base44 public URL the way an outside visitor would: it looks for API routes that respond without authentication, data endpoints that return content to an anonymous caller, and missing security headers on the hosted URL. Those are the observable defaults, and the scan returns each finding with severity and fix direction. It checks what a stranger can actually reach from the link.
What it cannot see is whether the backend enforces correct per-record authorization. That is not visible from the public surface, because the response to a logged-in caller can look entirely normal while still returning data the caller should not have. Confirming it means reviewing your entity security rules and testing across two accounts, which is manual work on the code and configuration, not a URL scan.
Next step: open your deployed app in an incognito window, walk the routes and watch the Network tab to see what answers with no session, then run a focused Launch Check against the public URL before you share it. Pair that with a manual pass over your entity security rules, which is the part the scan cannot reach. For the wider pre-share list across builders, see the AI-built app launch security checklist.
A clean Launch Check means the obvious doors are shut to anonymous callers. It is not a guarantee that your authorization rules are correct, and it is not a penetration test or a code review. Treat a flagged endpoint as a launch blocker and a clean result as one signal among several.
> launch check
Scan the public surface before launch.
Get severity, evidence, and practical fix guidance for the checks VibeCodeGuard can run from the outside.