fix: add rate limiting for API authentication and token validation - #2366
Merged
Conversation
elphizu
marked this pull request as ready for review
August 26, 2026 12:00
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
app/main/controllers/api/RTMediaJsonApi.php:342
Retry-Afteralways advertises a fresh full window, but this is a fixed-window counter whose expiry starts at the first failure. If the limit is reached near the end of that window, the login can be retried much sooner than this header says, so compliant clients may wait almost five unnecessary minutes. Return the remaining lifetime of whichever blocking bucket(s) are active (the maximum when both IP and identifier buckets block) rather thanget_window().
header( 'Retry-After: ' . $rate_limiter->get_window() );
app/main/controllers/api/RTMediaJsonApiFunctions.php:179
- This also sends the configured full window instead of the token bucket's remaining lifetime. For a fixed window that is nearly expired, clients are told to wait up to five minutes even though validation will be accepted seconds later. Expose the token bucket's remaining TTL from the rate limiter and use that value for
Retry-After.
header( 'Retry-After: ' . $rate_limiter->get_window() );
Contributor
Author
|
good catch by copilot fixed by returning the remaining TTL for the blocking IP or username/email bucket. when both buckets are blocking |
the-hercules
approved these changes
Aug 27, 2026
stack merge was automatically disabled
August 27, 2026 09:44
Pull Request is not mergeable
elphizu
force-pushed
the
fix/api-token-rate-limiter
branch
from
August 27, 2026 09:48
9432de9 to
1f8b110
Compare
Contributor
|
Unable to PHPCS or SVG scan one or more files due to error running PHPCS/SVG scanner:
The error may be temporary. If the error persists, please contact a human (commit-ID: d42bc33). |
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.
Description
This PR adds rate limiting to rtMedia API authentication and token validation endpoints to reduce brute-force and token-guessing attempts.
Changes
RTMediaApiRateLimiterfor tracking failed authentication attempts.20 attempts per 5 minutes.5 attempts per 5 minutes.20 attempts per 5 minutes.429 Too Many Requestswith aRetry-Afterheader when a limit is reached.200006for rate-limited login attempts.invalid username or passwordresponse to prevent username enumeration.Implementation details
When a persistent object cache such as Redis or Memcached is active, counters use
wp_cache_add()andwp_cache_incr().When no persistent object cache is configured, counters fall back to WordPress transients.
By default, only
REMOTE_ADDRis used to identify the client. Forwarded headers are not trusted automatically because they may be spoofed unless a trusted reverse proxy sanitizes them.Limitations
Counter atomicity
Rate-limit increments are atomic only when the configured persistent object-cache backend provides atomic
addandincrementoperations.The transient fallback is not atomic. Concurrent requests can read the same counter value and overwrite one another, causing some attempts to go uncounted. Rate limiting therefore remains best-effort on installations without a persistent object cache.
There is also a small expiration race with persistent caches: if a key expires between
wp_cache_add()andwp_cache_incr(), the fallbackwp_cache_set()may overlap with another request. This does not disable rate limiting, but exact counting is not guaranteed at the window boundary.REMOTE_ADDRand reverse proxiesREMOTE_ADDRmay represent a load balancer, CDN, or reverse proxy rather than the original client. On these installations, multiple users can share one rate-limit bucket and potentially rate-limit one another.The
rtmedia_api_client_ipfilter allows an installation to resolve the client IP from infrastructure-specific headers. The callback must only accept headers that are stripped and rewritten by a trusted proxy.IP-format validation alone does not make a forwarded header trustworthy - a client can still supply a syntactically valid but forged IP address if the proxy does not sanitize that header.