carlos / platform Public
| Previous finding | Disposition at 29455f24 | |---|---| | R1-1 — Readiness without established database state | Resolved. Unknown pointers block readiness; off and expired pointers require empty mirrors. | | R1-2 — off waits behind publication | Resolved. TryLock returns 409 while publication holds the slot. | | R1-3 — Unbounded console pointer reads | Resolved for reads. Pointer reads are streamed and capped. | | R1-4 — Recovery generation deleted after failed synchronization | Resolved for the reported paths. Installation failures preserve loaded and retained generations. | | R1-5 — Rejected-upload test does not establish zero reads | Resolved at the reservation boundary. The panicking-reader test detects reads before reservation. | | R1-6 — Countries overflow ordering | Resolved. _other remains intact until rendering and sorts last. | | R2-1 — Feed status writes bypass the read cap | Partly resolved; P2 remains. geoipfeed.go:174 still calls Put; release/store.go:408 reads the entire existing object before checking its precondition. An oversized feed.json can still exhaust memory. Apply the stat/streamed-hash checks used by PutFrom. | | R2-2 — Timed-out checks never persist failures | Resolved for download timeouts. Status persistence gets a separate bounded context. | | R2-3 — Unreadable feed status clears an alert | Resolved. Read and parse failures preserve established feed state. | | R2-4 — Unusable directory prevents “not loaded” alert | Resolved. Pointer state is retained before directory preparation. | | R2-5 — Published alert reasons never change while unhealthy | Resolved. Reason changes update Value and emit an event. | | R3-1 — Console follower keeps serving an expired database | Resolved. Loaded-reader expiry is checked independently of local state and candidate loading. | | R3-2 — Transient status-read failure erases feed history | Resolved. Unknown history is not overwritten. | | R4-1 — Unbounded bucket operations block startup or publication | Resolved for the reported bucket operations. Startup cleanup is asynchronous; maintenance and staging reads have deadlines. | | R4-2 — Restart falsely clears a persisted GeoIP alert | Resolved. Unknown inputs cannot establish recovery. | | R4-3 — Email delivery suppresses active reason changes | Resolved. Successful delivery records the last reason per recipient and resets other reason markers. | | R4-4 — Region guesses carry another generation’s attribution | Resolved. Location and source are captured under one reader lock. | | R5-1 — Unknown feed state suppresses confirmed expiry | Resolved. Established unhealthy conditions are evaluated before the unknown-state guard. | | R6-1 — Failed startup deletion leaves a disabled feed alert firing indefinitely | Resolved. Deletion retries with bounded attempts and capped exponential backoff. | | R7-1 — Unbounded feed edition metadata makes control records unreadable | Resolved for the reported input. MaxMind editions must parse as HTTP dates and are normalized; publication rejects oversized serialized pointers. | | R7-2 — Unchanged-edition checks leave the feed reported as “not run yet” | Resolved. Both providers return the confirmed edition, allowing Check to record success and edition history. |
New findings:
- P1 — MMDB verification can indefinitely hold the publish slot despite its deadline. internal/console/geoippublish.go:216, internal/geo/mmdb.go:41:
CommitcallsOpenMMDBsynchronously while holding the publication mutex. The pinnedmaxminddb-golangverifier enumerates every network path without checking a context or limiting traversal work. A compact IPv6 database containing 128 nodes, with both children of each node pointing to the next and the final children pointing to one data record, causes enumeration of \(2^{128}\) paths. It passes the byte caps; verification runs before the country, type and shrink checks.
A hostile feed response—or an operator uploading such a downloaded file—therefore leaves verification consuming CPU, publication and off returning 409, and staging retained beyond the 15-minute deadline. For the feed, Check never returns to persist a failure or schedule another check. Bound verification itself through a cancellable, work-limited verifier or a killable worker process. A timeout around an uncancelled goroutine is insufficient. Add a pathological-tree regression proving timely termination, slot release, staging cleanup and preservation of the previous pointer.
Validation was static, including inspection of the pinned verifier. Targeted Go tests could not start because the work directory is read-only; cross-compilation remains unverified.
Verdict: revise.