You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
NotifyRequest fields (ref_name, new_sha, old_sha, timestamp, cert_id, pusher_did, owner_did) are free-form strings with no length or format validation (crates/gitlawb-node/src/api/peers.rs:386-409). notify_sync validates only the repo slug (:443-448, the #272 check) and insert_ref_update stores the rest verbatim (crates/gitlawb-node/src/db/mod.rs:3451-3474); its ON CONFLICT(id) DO NOTHING key is a fresh UUID, so no cross-peer dedup fires. The feed collector scans up to max(limit, 2048) complete rows per request (crates/gitlawb-node/src/api/events.rs:70-92) and renders the stored strings; event ordering compares the attacker-controlled timestamp strings lexicographically (events.rs:315-321). The HTTP notify path accepts unsigned callers by default (config.rs:70-77), and the gossipsub path writes the same rows with no HTTP-side brake at all (p2p/mod.rs:302-334).
Impact
Junk rows persist until manually truncated, so a modest number of large-field rows makes every anonymous GET /api/v1/events/ref-updates (and repo events) scan and serialize multi-megabyte content across up to 2,048 rows: durable database and response amplification on a public route, with attacker-chosen timestamps permanently pinning the top of the feed. Distinct from #96/#334 (row-count admission and dedup), EX-002's authenticity gap (#323), and #423 (single-repo scan width): this is per-field size amplification on stored rows.
Remediation
Validate formats and cap lengths at ingest: sha fields as 40-char hex, timestamp as RFC 3339, DIDs bounded, ref_name as a git-checkable ref name.
Enforce the same caps at insert for defense in depth.
Order and paginate on server-generated columns, never attacker-supplied strings.
Activity