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.
- 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/
- 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.
- 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. - Check your token storage. Open DevTools → Application → Local Storage. Look for tokens, JWTs, session IDs. Anything sensitive in localStorage is XSS-readable.
- 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
Related problems
- SSO bypass and auth vulnerabilities — the parallel finding from the same disclosure cycle.
- Vendor lock-in via SDK dependency — the structural reason platform-side security gaps hit hard.
- No SLA — your app is one outage from down — including outages caused by emergency security patches.