Repository navigation
Apply user-based API rate limits - #1640
Open
skyfallwastaken wants to merge 10 commits into
Open
skyfallwastaken wants to merge 10 commits into
skyfallwastaken wants to merge 10 commits into
Conversation
Contributor
|
skyfallwastaken
force-pushed
the
main
branch
from
September 13, 2026 19:16
f1786c8 to
6101271
Compare
Resolve the real client behind Cloudflare from CF-Connecting-IP when the proxy chain shows a Cloudflare edge, limit rejected credentials by IP before authentication, key OAuth token exchanges by application, share Admin OAuth allowances with the user and only enable Rack Attack in production where cloudflare-rails is loaded.
3kh0
force-pushed
the
feature/authenticated-api-rate-limits
branch
from
October 6, 2026 22:28
e9d0656 to
d6ca4e9
Compare
bin/brakeman runs with --ensure-latest, so the 8.1.0 release made the scan exit early and the SARIF upload fail.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Rack prefers Forwarded over X-Forwarded-For, and neither Cloudflare nor our edge proxy strips it, so a client could choose request.ip and pass req.cloudflare? to skip Rack::Attack's blocklist and IP throttles.
Requests without credentials stay limited by IP. Authenticated requests skip the IP limits and get 600 requests per minute per user, and admin credentials get 5,000 per minute. Credentials that are rejected, or ignored by public stats, are limited by IP so they can't be used to escape the IP limits.
Client IDs are public, so keying only by client let anyone exhaust an integration's token exchange allowance with invalid requests.
This branch has not been deployed
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary of the problem
Rack Attack has been disabled in production since 5720daa. Turning it back on with the old rules would repeat the August outage: integrations such as Lapse make requests for all of their users from one server address, so they shared a single IP allowance and logins started failing with 429 responses.
Behind Cloudflare and the Coolify proxy,
req.ipcan also resolve to a Cloudflare edge address instead of the real client, which would group unrelated users into the same bucket.Describe your changes
require_oauth_scopenow sets a class attribute instead of prepending a callback, so scoped OAuth checks run after this guard.POST /oauth/tokenper OAuth application and client IP, with a higher IP ceiling, instead of the general POST limit. Client IDs are public, so the IP stays in the key to stop others using up an application's allowance.CloudflareClientIpmiddleware. When the trusted proxy chain shows a Cloudflare edge, it prependsCF-Connecting-IPtoX-Forwarded-Forso Rack Attack andrequest.remote_ipsee the real client. The original chain is kept soreq.cloudflare?still passes, and requests that bypass Cloudflare or forge an edge address keep their own IP.Forwardedheader when resolving client IPs. Rack prefers it overX-Forwarded-Forand neither proxy strips it, so clients could previously pick their own IP and pass the Cloudflare check.cloudflare-railsis only bundled there.Screenshots / Media
Not applicable.