|
|
@@ -11,7 +11,7 @@
|
|
|
>
|
|
|
> Each finding is referenced as **F<N>** for later citation.
|
|
|
>
|
|
|
-> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (27 fixed, 0 open), 42 sev-1 (38 fixed, 4 open).
|
|
|
+> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (27 fixed, 0 open), 42 sev-1 (39 fixed, 3 open).
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -2273,6 +2273,27 @@
|
|
|
monotonically with no LRU. Admin-creatable, but unbounded. Add a
|
|
|
bounded LRU (e.g. 16 policies cached).
|
|
|
- **Severity: 1**
|
|
|
+- **Status:** Fixed. New `BlocklistCache::MAX_ENTRIES = 16` cap (also
|
|
|
+ configurable via the constructor's new `$maxEntries` argument).
|
|
|
+ Insertion goes through a private `store()` helper that
|
|
|
+ unset-then-assigns the key (which pushes it to the end of PHP's
|
|
|
+ insertion-ordered array) and evicts `array_key_first()` past the
|
|
|
+ cap. Reads through `getOrBuild` / `getRendered` mark the entry as
|
|
|
+ most-recently-used via a private `touch()` helper. Both paths
|
|
|
+ preserve the existing per-policy invalidation contract
|
|
|
+ (`invalidate($policyId)` / `invalidateAll()`). Worst-case memory
|
|
|
+ is now bounded by 16 × the per-policy build cost, regardless of
|
|
|
+ how many policies an admin creates over the worker's lifetime.
|
|
|
+ Two tiny `@internal` accessors — `entryCount()` and
|
|
|
+ `cachedPolicyIds()` — let the regression test inspect cache state
|
|
|
+ without reaching into private fields via reflection. Regression
|
|
|
+ test in `api/tests/Integration/Public/BlocklistControllerTest.php`:
|
|
|
+ `testCacheIsLruBoundedAtSixteenEntries` rebuilds the cache with a
|
|
|
+ 30 s TTL (the test fixture default is 0 s = no caching), creates
|
|
|
+ 18 policies and one consumer per policy, hits `/api/v1/blocklist`
|
|
|
+ for each, then asserts `entryCount() ≤ MAX_ENTRIES`, the two
|
|
|
+ oldest policy IDs are NOT in the cache, and the most-recent one
|
|
|
+ IS. The 10 pre-existing BlocklistController tests still pass.
|
|
|
|
|
|
### F72 — `/ips/{ip:.+}` accepts unbounded path parameter
|
|
|
- **Files:** `api/src/App/AppFactory.php:256`,
|