FOR PEOPLE SHIPPING BASE44 APPS

What Base44 apps get wrong

In round 2026-11 of the Vibe Security Index we scanned 50 public repositories carrying Base44's scaffold marker with all 223 rules. These are the security findings that repeated, why this particular workflow produces them, and the prompt change that prevents each one.

Read this first

  • →This is not a claim that Base44's product is insecure. We measured public repositories carrying its scaffold marker (@base44/sdk in package.json), edited by humans for an unknown period afterwards. The marker proves the project started from the scaffold. It does not prove any particular line was generated rather than written, and attributing a finding to the builder is not something this design supports.
  • →50 repositories, drawn from a universe of 1,856. Every rate on this page is stated with the count behind it, because a percentage over 50 is a different kind of object than a percentage over 1,856: the finest distinction 50 repositories can draw is one repository. Differences of a few points here are noise.
  • →The enforcement this platform relies on is usually not in the repository. Base44 apps talk to a hosted backend, and the permission rules that actually protect the data usually live there rather than in the repository. Our scan does not evaluate them. That shapes several findings below, and each one says so rather than letting you assume the scan covered it.
  • →No repository is ever named publicly. Not here, not on the Index, and not in any published data: results identify each repository only by a salted hash, and the repository list stays in private working files used to clone the sample. Publishing the list would mean pointing at live vulnerabilities in other people's projects, so the results are aggregate only and the per-repository rows are anonymised by design.
  • →Static analysis has false positives, including ours. A finding is something a person should look at, not a proven breach. Where a finding that has its own section below is partly our own noise, the section says so.

Round 2026-11, generated November 3, 2026. Full method, sampling frame and limitations: Index methodology.

The shape of the sample

42%

had at least one critical finding in their own code

21 of 50

100%

had at least one high or worse

50 of 50

27

median findings per project, application code only

across 50 projects

101

median scanned files per project

size is a confound on every rate above

Why the loudest findings are not on this page

Sorted by raw occurrence count, the top of this builder's results is code quality, not security. Magic Numbers in Code (456 occurrences across 47 of 50 projects), Empty Catch Block (161 occurrences across 24 of 50 projects), Synchronous File Operations (124 occurrences across 15 of 50 projects) and Console.log Left in Production Code (86 occurrences across 26 of 50 projects) are all info severity, a call this codebase made deliberately and has not changed. They are worth cleaning up. They are not what someone shipping an app to real users is asking about, and a security page that led with them would be counting lines instead of answering the question.

So the list below is filtered by severity and then ordered by severity, with how many projects a finding appeared in as the tiebreaker. Occurrence count never decides the order, because a finding that repeats many times inside a few projects would otherwise outrank one that reached more of them. There is a second filter on top of that one. The finding at the very top of the severity sort is a missing response header, Missing Content Security Policy (CSP), present in 44 of 50 projects, which describes where the app is hosted rather than the code in it. So the page leads with one of the most severe findings that is actually in the repository: Unvalidated Redirect, in 21 of 50 projects. The header cluster still gets its own section, at the end.

Security findings that repeat, application code only

From round 2026-11. n = 50 repositories. “Projects” is how many of them contained the finding at least once; occurrences is the total across all of them.

FindingSeverityProjectsOccurrences
Missing Content Security Policy (CSP)VC020high88%44 of 5070
Unvalidated RedirectVC016high42%21 of 5061
API Route Missing AuthenticationVC003high34%17 of 5095
Missing Security Meta Tags / HeadersVC027medium88%44 of 50138
Clickjacking — Missing X-Frame-OptionsVC056medium88%44 of 5076
Timing-Unsafe Secret ComparisonVC043medium32%16 of 5041

This is the round's top-rules list with info and low severity removed. It is not the complete finding list for any project, and a check that never made this builder's top ten can still be the one that matters in yours. API Route Missing Authentication, Timing-Unsafe Secret Comparison appear in the table without a section below — real, but less specific to this workflow than the rest.

Each one, and what stops it coming back

Fixing the finding fixes one line. Changing the instruction that produced it fixes every line the next prompt writes, which is the only version of this that scales when the code is arriving faster than it can be read.

highVC016 · 21 of 50 projects · 61 occurrences

Navigation that goes wherever it is told

Unvalidated Redirect

Why this workflow produces it

Read the two numbers in the header of this section together: it reached a large minority of the sample and fired about two and a half times per project on average. That is not one login redirect. That is a navigation pattern the app reuses.

These projects are single-page dashboards, and the generated navigation helper takes its destination from something dynamic — a query parameter, a stored return-to value, a field on a record — and hands it to the router or straight to the browser's location.

The behaviour it implements is genuinely useful, which is why it never gets removed: send the user back where they came from after signing in, or forward to the thing they clicked before they were asked to authenticate. The only missing piece is that the destination is never checked against the set of places you are willing to send somebody.

The result is a link on your own domain that quietly bounces a visitor onto someone else's, carrying your app's credibility with it. On a page people reach while signed in, that is a working phishing setup that costs the attacker nothing to build.

The change that prevents it

Resolve destinations against an allowlist of your own routes instead of passing a URL through. A redirect parameter should name a route, not supply a location.

Paste this into your project instructions, or into the prompt itself:

Never pass a value from a query string, a stored value or a
record field directly to router.push, navigate or
window.location. Redirect targets must be looked up in an
allowlist of internal route names defined in code. If a
value does not match one, fall back to the home route
rather than following it.

The scan that verifies it

Scan, then try it: load your own app with a redirect parameter pointing at an external domain and see whether it follows. That single test answers the question faster than reading every hit.

npx xploitscan@latest scan . -f json \
  | jq '[.findings[] | select(.rule == "VC016")] | length'

Honest caveat. This check cannot always tell an internal route constant from a value someone else controls, so expect a share of these to be internal navigation that was never a risk. It is also worth being accurate about the impact — in a client-side router this is a phishing and trust problem, not a server-side request forgery. Worth an hour, not a weekend.

highVC020 · 44 of 50 projects · 70 occurrences

The response headers a static host does not set for you

Missing Content Security Policy (CSP)

Why this workflow produces it

This is really three findings in the table above — the missing content-security policy, the missing frame-ancestors control, and the missing content-type and referrer policies. They travel together because they have one cause.

A Base44 project ships as a static bundle served by a host, and response headers have to come from that host. The Base44-hosted apps we checked sent X-Frame-Options, nosniff and a referrer policy, but no content-security policy; other hosts may add none.

Nothing looks broken as a result, because none of these headers change how a working app behaves. They only change what happens during an attack, which is why they survive every round of testing you do before launch.

The change that prevents it

Add them where the host reads them: a _headers file on Netlify or Cloudflare Pages, the headers array in vercel.json on Vercel. The content-security policy is the one worth real time and the one most likely to break something, so run it in report-only mode first and read the reports before you enforce it. The rest are close to free.

The scan that verifies it

Scan for all three, then check the live response and confirm the headers actually arrive: curl -sI https://your-app.example. The scan reads your repository; only the response proves a header is really being sent.

npx xploitscan@latest scan . -f json \
  | jq '[.findings[] | select(.rule == "VC020" or .rule == "VC027" or .rule == "VC056")] | length'

VC027 and VC056 are outside the free rule set. The free scan runs 30 of the 223 rules, so a free plan never evaluates them. This command also counts VC020, which a free scan does run — so the number it returns on a free plan is the VC020 count alone, and it says nothing either way about VC027 and VC056.

Honest caveat. This cluster fired on most of the sample, which says more about the scaffold than about any developer — and part of it is a measurement limit on our side. The scanner reads your repository, so a host that already injects these headers still reads as missing. Check the live response before you spend an afternoon on it.

The one we are still bad at, stated plainly

Everything above is a pattern our rules match directly in the code. This section is the opposite: a separate research pass over the same sampling frame went looking for request handlers with no authentication check, and the honest result was that our rules flagged well under half of them in Base44-shaped code.

118

handlers in the Base44 slice where the analysis could find no authentication check

39%

of those 118 that our rules flagged when this pass was run (July 2026); VC003 has changed since and this has not been re-measured — a point estimate, not the middle of the interval below

95% confidence interval 31%–48%

The count on the left is worth a second look on this builder in particular. A platform whose whole premise is a hosted backend might be expected to have almost no server code of its own in these repositories, and 118 handlers says otherwise: a meaningful share of these projects add their own server functions or routes alongside the SDK. Those are the parts of a Base44 app where the platform's permission model is not protecting you, and they are also the parts our rules currently miss most of.

This is not a builder ranking. The research pass behind these figures states in its own limitations that it does not support comparing one builder against another, so this page reports its own slice and nothing relative to anyone else's.

For context from the same pass, across all four builders and 174 repositories: 51% [44%–58%] had any server-side handler at all, and of those, 69% [58%–77%] had at least one handler with no authentication check the analysis could find. Those two figures are round-level, not Base44-specific, and are labelled that way on purpose — the research pass does not break them out per builder, so neither does this page.

What that does not mean

  • •A shape is not a vulnerability. Nothing was exploited and no request was ever sent to a running application. A handler in this class is one where a static pass could not find an auth check. Some fraction are protected by means the method cannot see.
  • •47.5% of handlers were undecidable from a single file and were classified as such rather than guessed at. A handler goes to that bucket whenever protection might exist somewhere the analysis cannot look — middleware mounted before the route table, for instance. Every rate above excludes them, so these describe the decidable slice, not the whole corpus.
  • •The related ownership check is not settled enough to quote. The pass also looked for handlers that authenticate the caller but never scope the record to them. In the Base44 slice that class measured 2 handlers under the strict definition and 10 under the loose one. A class whose size moves fivefold with where you draw the line is not a number we are willing to headline, so it is here as a range and nowhere else.
  • •Handler counts are concentrated. A handful of large repositories contribute most of the handlers, so a handler-level percentage is closer to a statement about those projects than about a typical one.

We publish this because a scanner that only advertises what it catches is not much use for deciding whether to trust it. If your project has server-side functions alongside the SDK, read them yourself with one question in mind: who is this endpoint willing to answer? Our benchmark page carries a related disclosure: a held-out access-control case we only catch after studying it and changing the rule, so it is excluded from our blind score.

The findings we do not count against you

Every number above covers application code only. A Base44 project also arrives with a copied-in component library, and findings there are separated before any headline figure is computed. They are reported, never hidden, and they never touch a grade.

In this round 34% of the 50 projects (17 of 50) had a critical finding in that copied-in code — against the 42% in their own code. That column is mostly our false positive. One component in the suite sets CSS variables through a raw-HTML style block, which trips a critical cross-site-scripting rule. It is CSS-variable theming, not an injection sink, and a rule that flags it is our bug rather than yours or the builder's.

Because every project that copies this component in gets the same code, the hit reflects the component library rather than anything the builder or the user wrote. Reading it as a security signal would mean ranking projects by how much of a component library they happened to copy in. This is also why your grade is computed on your own code by default — you can opt into the stricter view with xploitscan scan . --grade-vendored if you want everything counted.

Find out which of these are in your project

Same application-versus-scaffold split, run against your repository with npx xploitscan@latest scan . in your project folder. No credit card and no signup for the first scan — that one runs the 30 free rules rather than the 223 this round used, and the full set comes with a paid plan.

Numbers on this page are read from the published Vibe Security Index round 2026-11 at build time. Method and limitations: methodology.