Summary
GET /api/v1/stats (crates/gitlawb-node/src/server.rs:546-579, on meta_routes with no auth layer or limiter) calls list_all_repos_deduped() (no LIMIT, db/mod.rs:1525) and then list_visibility_rules_for_repos(&ids) (db/mod.rs:4121) on every request, JSON-parsing every reader_dids list to produce one integer. A byte-budgeted variant built for anonymously reachable surfaces, list_visibility_rules_for_repos_bounded (db/mod.rs:4183), exists but is not used here.
Impact
Every anonymous request performs a full inventory transfer and allocation (repos plus all visibility rules, the latter owner-inflatable via rule flooding), multiplied by parallel callers. Cost grows with total inventory, so the endpoint gets slower and heavier for its entire life with no cache, limit, or admission.
Remediation
- Use the bounded rules variant (or a count-only query) for this endpoint.
- Cache the count briefly or admit the route.
Proposed labels: kind:security, crate:node, subsystem:api.
Summary
GET /api/v1/stats(crates/gitlawb-node/src/server.rs:546-579, onmeta_routeswith no auth layer or limiter) callslist_all_repos_deduped()(no LIMIT,db/mod.rs:1525) and thenlist_visibility_rules_for_repos(&ids)(db/mod.rs:4121) on every request, JSON-parsing everyreader_didslist to produce one integer. A byte-budgeted variant built for anonymously reachable surfaces,list_visibility_rules_for_repos_bounded(db/mod.rs:4183), exists but is not used here.Impact
Every anonymous request performs a full inventory transfer and allocation (repos plus all visibility rules, the latter owner-inflatable via rule flooding), multiplied by parallel callers. Cost grows with total inventory, so the endpoint gets slower and heavier for its entire life with no cache, limit, or admission.
Remediation
Proposed labels: kind:security, crate:node, subsystem:api.