java-topology/whitepaper/outreach/libgit2.md

2.8 KiB
Raw Blame History

libgit2 — CWE-407 Disclosure Brief

2026-03-27 · Patch available — awaiting upstream merge

Finding

One O(n²) defect in libgit2's filesystem reference backend. ref_available() performs an O(R) packed-ref list scan per path segment check — called at 17 sites — causing O(R²) total overhead for repositories with many references. Patch ready for upstream review.

The Defects

libgit2-0001 (PATCHED — HIGH): src/libgit2/refs.c

/* git_refdb_backend_fs.ref_available() — per segment per path check: */
/* Called at 17 sites */
static int ref_available(git_refdb_backend *_backend,
                         const char *refname, ...)
{
    /* O(R) packed-ref list scan per segment */
    git_sortedcache_rlock(backend->refcache);
    size_t i;
    for (i = 0; i < git_sortedcache_entrycount(backend->refcache); i++) {
        struct packref *ref = git_sortedcache_entry(backend->refcache, i);
        if (is_prefix_of(ref->name, refname)) { ... }
    }
    /* O(R²) total across 17 call sites */
}

O(R) packed-ref scan per path segment check, at 17 call sites. O(R²) total. Measured ratio: 17 sites.

Complexity Proof

For R packed references:

  • Per ref_available() call: O(R) scan
  • 17 call sites per ref operation: O(17×R) per operation
  • R operations: O(R²) total
  • Fixed: binary search on sorted refs → O(R × log R)
  • 17 call sites measured.

Impact

All libgit2 users and all software built on libgit2: GitHub's Rugged (Ruby), pygit2 (Python), git2go (Go), NodeGit, libgit2sharp (.NET), and Git GUI clients. Repositories with many references (many branches, many tags — common in large monorepos and CI/CD systems) hit O(R²) during reference creation, renaming, and deletion. libgit2 is the foundation of most non-C Git tooling.

The Fix

Use binary search on the sorted reference cache instead of linear scan:

/* Before */
for (i = 0; i < git_sortedcache_entrycount(backend->refcache); i++) {
    struct packref *ref = git_sortedcache_entry(backend->refcache, i);
    if (is_prefix_of(ref->name, refname)) { ... }
}

/* After */
/* CWE-407 fix: binary search on sorted refcache for O(log R) per check. */
size_t pos;
int error = git_sortedcache_lookup_raw(backend->refcache, &pos, refname);
/* Binary search gives insertion point; check neighbors for prefix overlap */

Patch

defects/libgit2/patch/libgit2-0001-refs-binary-search.patch

What We Ask

  1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
  2. Validate the patch against your reference backend test suite.
  3. Assess CVE eligibility — affects all 17 ref_available call sites in large repositories.
  4. Coordinate a disclosure date — we are targeting 90 days from first contact.

Contact: see cover email. This brief is confidential until coordinated disclosure.