feat(security): add per-IP rate limiting on guest-order endpoints (#19) #29
|
|
@ -15,6 +15,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
|||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import se.bilhalsning.dto.ErrorResponse;
|
||||
import se.bilhalsning.security.GuestOrderRateLimitFilter;
|
||||
import se.bilhalsning.security.JwtAuthenticationFilter;
|
||||
import se.bilhalsning.security.JwtService;
|
||||
|
||||
|
|
@ -41,7 +42,8 @@ public class SecurityConfig {
|
|||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http,
|
||||
JwtAuthenticationFilter jwtAuthenticationFilter) throws Exception {
|
||||
JwtAuthenticationFilter jwtAuthenticationFilter,
|
||||
GuestOrderRateLimitFilter guestOrderRateLimitFilter) throws Exception {
|
||||
http
|
||||
.csrf(csrf -> csrf.disable())
|
||||
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
|
|
@ -64,6 +66,7 @@ public class SecurityConfig {
|
|||
writeError(response, HttpStatus.UNAUTHORIZED, UNAUTHENTICATED_MESSAGE))
|
||||
.accessDeniedHandler((request, response, ex) ->
|
||||
writeError(response, HttpStatus.FORBIDDEN, FORBIDDEN_MESSAGE)))
|
||||
.addFilterBefore(guestOrderRateLimitFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
package se.bilhalsning.security;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import jakarta.servlet.FilterChain;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import jakarta.servlet.ServletException;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import java.io.IOException;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import java.time.Instant;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import java.util.ArrayDeque;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import java.util.Deque;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import org.springframework.http.MediaType;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import org.springframework.stereotype.Component;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
/**
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* In-memory per-IP rate limiter for public guest-order endpoints.
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
*
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* <p>Uses a sliding-window log algorithm: for each client IP, stores request
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* timestamps in a deque. On each request, timestamps older than the window
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* are pruned. If the remaining count exceeds the limit, the request is
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* rejected with HTTP 429.
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
*
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* <p>This is a Phase 0 interim measure. It is not suitable for multi-instance
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* deployments (state is per-JVM) and resets on restart. For production, use
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* Bucket4j with a Redis backing or a reverse proxy (nginx {@code limit_req}).
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
*
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* <p>Configurable via application properties:
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* <ul>
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* <li>{@code app.rate-limit.guest-create} — POST /api/guest-orders (default 5/min)</li>
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* <li>{@code app.rate-limit.guest-default} — all other /api/guest-orders/** (default 20/min)</li>
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* </ul>
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
*/
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
@Component
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
public class GuestOrderRateLimitFilter extends OncePerRequestFilter {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
@Value("${app.rate-limit.guest-create:5}")
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
private int createLimit;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
@Value("${app.rate-limit.guest-default:20}")
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
private int defaultLimit;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
private static final long WINDOW_SECONDS = 60;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
private final ConcurrentHashMap<String, Deque<Instant>> store = new ConcurrentHashMap<>();
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
@Override
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
protected void doFilterInternal(
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
HttpServletRequest request,
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
HttpServletResponse response,
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
String path = request.getRequestURI();
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
if (!path.startsWith("/api/guest-orders")) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
filterChain.doFilter(request, response);
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
return;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
String ip = extractClientIp(request);
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
String key = ip + ":" + (isCreatePath(path) ? "create" : "default");
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
int limit = isCreatePath(path) ? createLimit : defaultLimit;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
if (isRateLimited(key, limit)) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
response.getWriter().write(
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
"{\"message\":\"För många förfrågningar. Försök igen om en minut.\"}");
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
return;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
filterChain.doFilter(request, response);
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
/**
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* Check and record a request. Returns true if the request should be
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* rejected (rate limit exceeded), false otherwise.
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
*/
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
private boolean isRateLimited(String key, int limit) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
Instant now = Instant.now();
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
Instant cutoff = now.minusSeconds(WINDOW_SECONDS);
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
Deque<Instant> timestamps = store.computeIfAbsent(key, k -> new ArrayDeque<>());
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
synchronized (timestamps) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
while (!timestamps.isEmpty() && timestamps.peekFirst().isBefore(cutoff)) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
timestamps.pollFirst();
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
if (timestamps.size() >= limit) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
return true;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
timestamps.addLast(now);
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
return false;
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
private boolean isCreatePath(String path) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
return path.equals("/api/guest-orders");
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
private String extractClientIp(HttpServletRequest request) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
String forwarded = request.getHeader("X-Forwarded-For");
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
if (forwarded != null && !forwarded.isBlank()) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
return forwarded.split(",")[0].trim();
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
String realIp = request.getHeader("X-Real-IP");
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
if (realIp != null && !realIp.isBlank()) {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
return realIp.trim();
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
return request.getRemoteAddr();
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
/**
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
* Reset the rate limit state. For testing only.
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
*/
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
public void reset() {
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
store.clear();
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
}
|
||||
|
hermes
commented
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine 🟡 **Unbounded map growth.** Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine `maximumSize`).
hermes
commented
💡 Add 💡 **Add `Retry-After` header.** `response.setHeader("Retry-After", "60")` is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.
hermes
commented
💡 Use the existing 💡 **Use the existing `ErrorResponse` DTO.** The codebase has `ErrorResponse(String message)` and SecurityConfig uses `objectMapper.writeValueAsString(new ErrorResponse(message))` for all error responses. Inject `ObjectMapper` and follow the same pattern to avoid hardcoded JSON and keep responses consistent.
hermes
commented
🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like 🟡 **X-Forwarded-For is trusted unconditionally.** If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like `app.rate-limit.trust-forwarded-headers` (default `false`).
|
||||
|
|
@ -23,7 +23,11 @@ import se.bilhalsning.service.UserService;
|
|||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@TestPropertySource(properties = "app.jwt.secret=this-is-a-test-secret-that-is-at-least-32-bytes-long!!")
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
@TestPropertySource(properties = {
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
"app.jwt.secret=this-is-a-test-secret-that-is-at-least-32-bytes-long!!",
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
"app.rate-limit.guest-create=1000",
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
"app.rate-limit.guest-default=1000"
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
})
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
class GuestOrderControllerTest {
|
||||
|
||||
@Autowired
|
||||
|
|
@ -35,6 +39,14 @@ class GuestOrderControllerTest {
|
|||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
@MockitoBean
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
private se.bilhalsning.security.GuestOrderRateLimitFilter rateLimitFilter;
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
@org.junit.jupiter.api.BeforeEach
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
void resetRateLimit() {
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
rateLimitFilter.reset();
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
}
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
|
||||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
// --- POST /api/guest-orders (create) ---
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
hermes
commented
💡 The rate limiter is wired in but never actually tested. No test fires 💡 The rate limiter is wired in but never actually tested. No test fires `createLimit + 1` requests to verify a 429 is returned. For a security control, consider a dedicated `GuestOrderRateLimitFilterTest` with low limits that exercises the actual rejection path.
|
||||
🟡 Unbounded map growth. Stale IP keys (pruned deques) are never removed from the map. With X-Forwarded-For spoofing, an attacker can cause unbounded memory growth by sending unique header values. Consider a scheduled cleanup task or a bounded cache (Caffeine
maximumSize).💡 Add
Retry-Afterheader.response.setHeader("Retry-After", "60")is trivial and helps well-behaved clients back off. RFC 6585 recommends it for 429 responses.💡 Use the existing
ErrorResponseDTO. The codebase hasErrorResponse(String message)and SecurityConfig usesobjectMapper.writeValueAsString(new ErrorResponse(message))for all error responses. InjectObjectMapperand follow the same pattern to avoid hardcoded JSON and keep responses consistent.🟡 X-Forwarded-For is trusted unconditionally. If the app is directly reachable (no stripping reverse proxy), an attacker can rotate this header per request to bypass rate limiting entirely. Consider a config flag like
app.rate-limit.trust-forwarded-headers(defaultfalse).