CVE-2026-73306 Overview
Budibase is an open-source low-code platform used to build internal tools and business applications. Versions prior to 3.39.25 contain an information disclosure flaw in the tenant login endpoint POST /api/global/auth/:tenantId/login. The failure counter in packages/worker/src/api/controllers/global/auth.ts was incremented only for existing users, while the middleware in packages/worker/src/middleware/emailLockout.ts returned X-Account-Locked and Retry-After headers only for locked identifiers. An unauthenticated attacker can send repeated login failures and compare responses to enumerate valid email addresses and temporarily lock those accounts. The issue is fixed in version 3.39.25.
Critical Impact
Unauthenticated attackers can enumerate valid Budibase user accounts and induce account lockouts, enabling targeted follow-on phishing or denial-of-service against known users.
Affected Products
- Budibase versions prior to 3.39.25
- Budibase Worker service (packages/worker)
- Self-hosted and cloud Budibase deployments exposing the global auth API
Discovery Timeline
- 2026-08-12 - CVE-2026-73306 published to NVD
- 2026-08-12 - Last updated in NVD database
Technical Details for CVE-2026-73306
Vulnerability Analysis
The vulnerability is a response discrepancy classified under [CWE-204: Observable Response Discrepancy]. The login controller applied lockout accounting asymmetrically based on whether the submitted email corresponded to a real account. When the passport local strategy returned an error, the previous implementation only called onFailed(email) if a database user (dbUser) existed. As a result, valid emails accumulated failure counts and eventually produced lockout responses, while invalid emails did not.
The emailLockout middleware compounds this by attaching X-Account-Locked: true and Retry-After headers only when the identifier is present in the lockout store. An attacker scripts repeated authentication attempts against a target email and observes whether the account transitions into the locked state. Presence of the lockout headers, or a change in response timing and status, confirms that the email is registered in the tenant.
Root Cause
The root cause is inconsistent security handling between known and unknown user paths in the authentication flow. Because failure tracking was gated on dbUser, the system's observable behavior diverged for existing versus non-existing accounts, violating the principle of uniform authentication responses.
Attack Vector
The attack requires no authentication or user interaction. An attacker with network access to the tenant login endpoint issues repeated failed logins with candidate email addresses. Valid emails will eventually return lockout indicators after crossing the failure threshold, while unknown emails will not. The same technique also enables a denial-of-service primitive against known accounts by intentionally triggering lockouts.
// Security patch in packages/worker/src/api/controllers/global/auth.ts
"local",
async (err: any, user: User, info: any) => {
if (err || !user) {
- if (dbUser) {
- await onFailed(email)
- }
+ await onFailed(email)
if (await isLocked(email)) {
return handleLockoutResponse(ctx, email)
}
// Source: https://github.com/Budibase/budibase/commit/eaae816ab81615c07eb10e4619af078d00e2a706
The fix removes the dbUser conditional so that onFailed(email) is invoked for every failed login regardless of whether the email maps to a real account. This aligns lockout behavior across identifiers and eliminates the enumeration oracle.
Detection Methods for CVE-2026-73306
Indicators of Compromise
- High volumes of POST /api/global/auth/:tenantId/login requests from a single source with varying email addresses and identical or missing password fields.
- HTTP responses containing X-Account-Locked: true and Retry-After headers appearing shortly after bursts of failed authentication attempts.
- Sudden spikes in helpdesk tickets from legitimate users reporting locked accounts without prior failed access on their part.
Detection Strategies
- Parse Budibase worker access logs for authentication endpoints and alert when the ratio of failed logins to distinct email addresses exceeds a reasonable baseline per source IP.
- Correlate 401/423-class responses with source IP and user-agent to identify enumeration sweeps that touch many accounts in a short window.
- Deploy WAF or reverse-proxy rules that count failed login attempts per source IP across all tenants and emit an alert on threshold breach.
Monitoring Recommendations
- Ingest reverse-proxy and Budibase worker logs into a centralized log platform and build dashboards for authentication failure rates per tenant.
- Monitor for outbound response headers X-Account-Locked and track their frequency as a proxy for both enumeration attempts and lockout DoS activity.
- Track anomalous geographic or ASN distribution of login attempts against the /api/global/auth path.
How to Mitigate CVE-2026-73306
Immediate Actions Required
- Upgrade all Budibase worker instances to version 3.39.25 or later, which contains the aligned lockout logic.
- Audit recent authentication logs for enumeration patterns and notify users whose accounts show unexplained lockouts.
- Place the global auth endpoint behind a rate-limiting reverse proxy or WAF if not already deployed.
Patch Information
The fix is available in Budibase release 3.39.25. The corrective change is documented in the GitHub commit eaae816 and discussed in pull request #19108. See the GHSA-cr7p-cr3q-h5cm security advisory for the vendor disclosure.
Workarounds
- Enforce per-source-IP rate limits on POST /api/global/auth/:tenantId/login at the ingress layer to blunt automated enumeration.
- Restrict access to the Budibase management interface via IP allowlists or VPN where deployment topology permits.
- Strip or normalize X-Account-Locked and Retry-After response headers at the reverse proxy until the patched release can be deployed.
# Example NGINX rate limit for the Budibase login endpoint
limit_req_zone $binary_remote_addr zone=bb_login:10m rate=5r/m;
server {
location ~ ^/api/global/auth/.+/login$ {
limit_req zone=bb_login burst=5 nodelay;
proxy_pass http://budibase_worker;
}
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

