[VUL-78] Add IP-based lockout to login endpoint#18947
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
2 issues found across 8 files
Confidence score: 3/5
- There is some merge risk because the highest-severity finding is concrete and high-confidence: in
packages/worker/src/middleware/ipLockout.ts, the non-atomic IP lockout counter update can let concurrent requests bypass rate limits. - In
packages/worker/src/api/routes/global/auth.ts, evaluating email lockout before IP lockout means blocked IP traffic can still trigger email-related DB lookups, increasing unnecessary load and weakening the intended short-circuit behavior. - Pay close attention to
packages/worker/src/middleware/ipLockout.tsandpackages/worker/src/api/routes/global/auth.ts- fix lockout atomicity and enforce IP lockout earlier to prevent bypass and avoid extra DB work.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
adrinr
approved these changes
Jun 9, 2026
IP lockout only requires a Redis read, while email lockout performs a database lookup. Checking the IP first avoids the DB query for requests that would be rejected anyway.
30 attempts per 15-minute window was too permissive for a brute-force protection mechanism. 10 is still generous enough for legitimate use behind corporate NATs while meaningfully limiting automated attacks.
Replace the non-atomic get/store pattern with cache.increment(), which maps to Redis INCR. Concurrent requests could previously read the same counter value and write back the same incremented result, bypassing the limit. INCR is atomic so each request is counted exactly once. TTL is set via EXPIRE only on the first increment (count === 1), which is the standard Redis rate-limiting pattern.
Contributor
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds IP-based rate limiting to the login endpoint (
POST /api/global/auth/:tenantId/login), complementing the existing per-email lockout introduced earlier on this branch.Why
A security audit (Budibase/vulns#78) demonstrated that the login endpoint had no restriction on authentication attempts, allowing an attacker to run an automated brute-force attack (829 requests, no blocking). The CVSS score is 6.5 (
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N).The email-based lockout already present on this branch protects accounts whose email address is known. The IP lockout adds a second layer that limits volume from any single source regardless of which accounts are targeted.
Screen recording
Screen.Recording.2026-06-09.at.11.43.08.mov
Addresses
https://github.com/Budibase/vulns/issues/78
Summary by cubic
Adds IP-based lockout to
POST /api/global/auth/:tenantId/loginto block brute-force attempts from a single source. Addresses VUL-78 by returning 429 withRetry-Afterand using an atomic Redis counter with TTL refreshed on each increment.New Features
ipLockoutmiddleware that counts attempts per IP withcache.increment(atomic), refreshes TTL (LOGIN_LOCKOUT_SECONDS) on each request, and responds with 429 andRetry-Afteronce the limit is exceeded.ipLockoutbeforeemailLockouton the login route to avoid unnecessary DB lookups; added unit/integration tests.LOGIN_IP_LOCKOUT_LIMITenv var (default 10).Refactors
incrementin@budibase/backend-coreand re-exported asgeneric.increment.lockout.tstoemailLockout.tsand updated imports/tests.Written for commit c92b573. Summary will update on new commits.