CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-cr7p-cr3q-h5cm: Budibase: Account Enumeration via Login Lockout Response Differential

mediumCVSS 5.3
Summary The login lockout mechanism in Budibase creates an observable response discrepancy that allows unauthenticated attackers to enumerate valid email addresses. When an existing user's account is locked after 5 failed login attempts, the server returns a distinct 403 response with X-Account-Locked: 1 and Retry-After: 900 headers plus the message "Account temporarily locked." For non-existing users, the response is always a generic 403 "Unauthorized" regardless of attempt count, because the lockout counter is never incremented. Details The vulnerability exists in two files that implement the login lockout feature: packages/worker/src/middleware/lockout.ts:18-36 — The lockout middleware only blocks requests for users that exist in the database AND are locked: export default async (ctx: Ctx, next: Next) => { const email = ctx.request.body.username if (!email) { return await next() } const dbUser = await userSdk.db.getUserByEmail(email) if (dbUser && (await isLocked(email))) { // line 26: non-existing users skip this entirely ctx.set("X-Account-Locked", "1") ctx.set("Retry-After", String(env.LOGIN_LOCKOUT_SECONDS)) ctx.throw(403, "Account temporarily locked. Try again later.") } return await next() } packages/worker/src/api/controllers/global/auth.ts:127-141 — The login handler only increments the failure counter for existing users: if (err || !user) { if (dbUser) { // line 129: non-existing users never trigger onFailed() await onFailed(email) } if (await isLocked(email)) { return handleLockoutResponse(ctx, email) } // ... return passportCallback(ctx, user as any, err, info) } Execution flow for existing users (after 5 failed attempts): 1. lockout middleware → getUserByEmail returns user → isLocked returns true → 403 + X-Account-Locked: 1 + Retry-After: 900 + "Account temporarily locked" Execution flow for non-existing users (any number of attempts): 1. lockout middleware → getUserByEmail returns null → dbUser && isLocked is false → passes through 2. Login

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
medium — CVSS 5.3
Published
2026-07-24
Last updated
2026-07-24
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-cr7p-cr3q-h5cm

More from GitHub Security Advisories