BASE44DEVS

FIX · SECURITY · CRITICAL

Fix Base44 Stored XSS That Leaks Authentication Tokens

The Base44 stored XSS disclosed by Imperva in July 2025 let malicious JavaScript saved in apps execute on the trusted Base44 domain and steal auth tokens from localStorage. Base44 patched it within hours, but you should still audit user-generated HTML in your own app for injection points, move tokens out of localStorage into HttpOnly cookies, set strict Content-Security-Policy headers, and rotate tokens issued during the exposure window.

Last verified
2026-05-01
Category
SECURITY
Difficulty
MODERATE
DIY possible
YES

What's happening

In July 2025, Imperva published a security disclosure on Base44 detailing a stored cross-site scripting vulnerability in the platform's /apps-show/ endpoint. The endpoint rendered user-controlled HTML without escaping. An attacker could embed malicious JavaScript in their app's content. When another user — including the platform owner or a paying customer — viewed the affected app, the script executed in the context of the trusted base44.com domain.

Imperva's published finding: "Injected code had access to authentication tokens stored in browser local storage." Combined with parallel findings on JWT leakage to user apps, the impact was full account takeover, not just app-level compromise. Wiz and Imperva published in the same window. Securityweek and Dark Reading covered both disclosures.

Base44 patched the XSS path within hours of disclosure. The patch closed the specific injection vector. It did not retroactively invalidate tokens captured during the exposure window, did not produce a comprehensive customer notification, and did not introduce structural protections (like HttpOnly cookie tokens or strict CSP) that would prevent the next similar bug from causing the same impact.

If you operate an app on Base44 today, the platform-level patch is in place. Your application-level vulnerabilities and your token-storage hygiene are still on you.

Why this happens

XSS is one of the oldest vulnerability classes on the web. It is also one of the most common in code-generation products. Two structural reasons compound on Base44.

Agent-generated code routinely uses unsafe HTML rendering. When the AI agent is asked to render a user's bio, a chat message, or a markdown body, it frequently emits dangerouslySetInnerHTML={{ __html: content }} or the equivalent without sanitization. The pattern is statistically common in training data, the agent does not understand the security implications, and the platform does not lint for it. Multiple feedback-board entries describe variations of "my user bio renders raw HTML and someone embedded a script."

Token storage is browser-local by default. Base44's SDK stores authentication tokens in browser localStorage by default. localStorage is readable by every script that runs on the page, full stop. The convenience is that page reloads keep the user logged in. The cost is that any successful XSS exfiltrates the token. HttpOnly cookies, the standard solution, are not used by the platform SDK by default.

The platform-level XSS was a single sanitization gap on one endpoint. The structural fragility — XSS-prone rendering patterns plus localStorage tokens — means that any future sanitization gap reproduces the same blast radius.

Sources: imperva.com/blog/critical-flaws-in-base44-exposed-sensitive-data-and-allowed-account-takeovers, wiz.io/blog/critical-vulnerability-base44, securityweek.com/flaw-in-vibe-coding-platform-base44-exposed-private-enterprise-applications.

How to test if you're affected

The original platform-level XSS is patched and not directly exploitable. What you can and should test is whether your own app code has similar rendering patterns.

  1. Search your codebase for unsafe rendering APIs:
grep -rn "dangerouslySetInnerHTML" src/
grep -rn "v-html" src/
grep -rn "innerHTML" src/
grep -rn "outerHTML" src/
grep -rn "document.write" src/
  1. For each match, identify the data source. If the rendered HTML comes from user input (any field a user can write to), you have a stored-XSS surface.
  2. Test each surface manually. Save a record with <script>alert(1)</script> in the relevant field. View the record as a different user. If the alert fires, you have stored XSS.
  3. Check your token storage. Open DevTools → Application → Local Storage. Look for tokens, JWTs, session IDs. Anything sensitive in localStorage is XSS-readable.
  4. Check your HTTP response headers. Run curl -i https://yourapp.base44.app/. Look for Content-Security-Policy. If absent, you have no CSP defense.

Step-by-step fix

You cannot patch the platform. You can audit and harden your own app, and you can wrap the platform's auth model with a more secure session layer.

1. Sanitize all user-generated HTML

Replace every dangerouslySetInnerHTML and equivalent with a sanitized variant. Use DOMPurify for browser-side rendering or sanitize-html for server-side.

import DOMPurify from "isomorphic-dompurify";

function UserBio({ html }: { html: string }) {
  const safe = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ["p", "br", "strong", "em", "a", "ul", "ol", "li"],
    ALLOWED_ATTR: ["href", "target", "rel"],
  });
  return <div dangerouslySetInnerHTML={{ __html: safe }} />;
}

The default DOMPurify config is overly permissive. Lock down the allowed tags and attributes to the minimum your feature needs.

2. Prefer rendering markdown over rendering HTML

If the user is writing long-form text, store markdown and render it through a markdown library (react-markdown, marked with a sanitizing renderer). Markdown rendering escapes HTML by default, which prevents most XSS by design.

3. Move authentication tokens out of localStorage

Build a backend-function auth proxy. Users authenticate against Base44 normally, but your function exchanges the platform token for an HttpOnly session cookie scoped to your domain. Frontend code calls your backend functions, which read the cookie and use the platform token server-side.

// backend/functions/login.ts
import { base44 } from "@base44/sdk";

export default async function handler(req: Request) {
  const { email, password } = await req.json();
  const session = await base44.auth.signIn({ email, password });

  // Issue an HttpOnly cookie scoped to your domain.
  const cookie = `app_session=${session.token}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=86400`;
  return new Response(JSON.stringify({ ok: true }), {
    status: 200,
    headers: {
      "set-cookie": cookie,
      "content-type": "application/json",
    },
  });
}

This requires your frontend to call your backend functions instead of the SDK directly. It is more work. It eliminates the localStorage XSS exposure entirely.

4. Deploy a strict Content-Security-Policy

Use a Cloudflare Worker or Vercel rewrite to set CSP headers in front of your Base44 app.

// cloudflare-worker.js
addEventListener("fetch", (event) => {
  event.respondWith(handle(event.request));
});

async function handle(request) {
  const response = await fetch(request);
  const headers = new Headers(response.headers);
  headers.set(
    "Content-Security-Policy",
    "default-src 'self'; " +
      "script-src 'self' 'unsafe-inline' https://*.base44.app https://*.base44.com; " +
      "style-src 'self' 'unsafe-inline'; " +
      "img-src 'self' data: https:; " +
      "connect-src 'self' https://*.base44.app https://*.base44.com; " +
      "frame-ancestors 'none'; " +
      "base-uri 'self';"
  );
  headers.set("X-Content-Type-Options", "nosniff");
  headers.set("X-Frame-Options", "DENY");
  return new Response(response.body, { status: response.status, headers });
}

Tighten the directives over time — start permissive enough that the app still works, then progressively remove unsafe-inline from script-src by moving to nonce-based or hashed scripts.

5. Rotate any third-party API keys held during the window

Same logic as the SSO bypass remediation. Rotate Stripe, Twilio, OpenAI, and partner integration keys. Update them in Base44's environment.

6. Add ongoing XSS detection

Set up an OWASP ZAP or similar scanner to run weekly against staging. Flag any new injection points the agent introduces in code generation.

DIY vs hire decision

DIY this if: You have one or two user-generated-content surfaces, you can pause feature work for 1-2 days to audit them, and you do not need to swap to HttpOnly cookies.

Hire help if: You handle PII or regulated data, you need the HttpOnly cookie session layer (which is non-trivial to build correctly), or you need a written security audit suitable for customers or regulators. Our complex-fix engagement audits every rendering surface, ships sanitization, builds the auth proxy with HttpOnly cookies, deploys CSP via Cloudflare, and produces a written remediation report.

Need a security audit and remediation?

Our complex-fix engagement audits XSS surfaces across your app, builds the HttpOnly cookie auth layer, deploys CSP, and verifies via a third-party scanner before handoff. Includes a written remediation report.

Start a complex-fix engagement for XSS remediation

QUERIES

Frequently asked questions

Q.01What was the exact Imperva XSS finding?
A.01

Imperva disclosed in July 2025 that the /apps-show/ endpoint rendered user-controlled content without escaping, letting attackers inject script tags that executed on the Base44 domain. Their published quote: 'Injected code had access to authentication tokens stored in browser local storage.' Combined with the JWT-leakage finding, an attacker could capture the victim's session and access their full Base44 account, not just the affected app.

Q.02Was my app vulnerable?
A.02

If your app accepted any user input that ended up rendered in another user's browser session — a chat message, a profile bio, a public listing description — there is a parallel risk in your own app code regardless of the platform-level patch. The platform-level XSS was patched. Application-level XSS in your own components is your responsibility and is common in agent-generated code that uses dangerouslySetInnerHTML or v-html without sanitization.

Q.03Should I move tokens out of localStorage?
A.03

Yes for any app handling sensitive data. localStorage is accessible to every script that runs on the page, including XSS payloads. HttpOnly cookies cannot be read by JavaScript and survive XSS. Base44's SDK does not give you direct control over token storage, so the practical move is to layer your own session management on top — a backend-function auth proxy that issues HttpOnly session cookies after Base44 authentication completes.

Q.04What is a Content-Security-Policy and how do I add one in Base44?
A.04

CSP is an HTTP header that restricts where scripts, images, and other resources can load from. A strict CSP prevents most XSS payloads from executing even if injection succeeds. Base44 does not let you set custom HTTP headers from the application layer, so you have to deploy CSP via a proxy (Cloudflare Workers, Vercel rewrites). It is one of the highest-leverage security controls available for a platform-hosted app.

Q.05Do I need to notify customers about the July 2025 incident?
A.05

Depends on your jurisdiction and the data your app holds. The vulnerability was platform-wide, not specific to your app, so most customer-facing communication about it should reference Imperva and Wiz's disclosure rather than your own incident. If you have a regulated workload (HIPAA, PCI, GDPR-significant), consult counsel — the question is whether tokens issued through your app during the exposure window count as a reportable incident under your applicable rules.

NEXT STEP

Need this fix shipped this week?

Book a free 15-minute call or order a $497 audit. We will respond within one business day.