java-topology/whitepaper/outreach/curl.md

2.7 KiB

curl — CWE-407 Disclosure Brief

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

Finding

One O(n²) defect in curl's cookie engine. replace_existing() in lib/cookie.c performs a linked-list scan over all cookies in a bucket on every cookie insert, causing O(C²) total overhead per bucket during cookie-heavy sessions. Patch ready for upstream review.

The Defects

curl-0001 (PATCHED — HIGH): lib/cookie.c

/* replace_existing() — per cookie bucket insert: */
static struct Cookie *
replace_existing(struct Curl_easy *data, struct CookieInfo *c,
                 const struct Cookie *co)
{
    /* O(C) linked-list scan per insert */
    struct Cookie *clist = c->cookies[hash];
    while (clist) {
        if (strcasecompare(clist->name, co->name) && ...) {
            return clist;  /* found — replace */
        }
        clist = clist->next;
    }
    return NULL;
}
/* O(C²) per bucket when inserting C cookies */

Linked-list scan O(C) per bucket per insert. For C cookies per bucket: O(C²) total. Fix: per-bucket HashMap<name, node>.

Complexity Proof

For C cookies per hash bucket:

  • Per insert: O(C) linked-list walk
  • C inserts: O(C²) per bucket
  • Fixed: HashMap<name, Cookie*> per bucket → O(C) total
  • Scales with cookie jar size; session-heavy applications most affected.

Impact

All curl users making requests to cookie-heavy websites — authentication flows, session management, web scraping, API clients, and browser-like applications. replace_existing() fires on every Set-Cookie header processed. Applications that accumulate large cookie jars (many Set-Cookie headers per session, many domains) hit O(C²) per bucket. curl is used in virtually every software stack as the de-facto HTTP client.

The Fix

Replace the linked-list bucket scan with HashMap<name, Cookie*> per bucket:

/* Before */
struct Cookie *clist = c->cookies[hash];
while (clist) {
    if (strcasecompare(clist->name, co->name)) return clist;
    clist = clist->next;
}

/* After */
/* CWE-407 fix: per-bucket HashMap for O(1) lookup instead of O(C) linked-list scan. */
struct Cookie *existing = Curl_hash_pick(&c->cookie_hash[hash],
                                          co->name, strlen(co->name) + 1);
return existing;

Patch

defects/curl/patch/curl-0001-cookie-replace-hashmap.patch

What We Ask

  1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
  2. Validate the patch against your cookie engine test suite.
  3. Assess CVE eligibility — fires on every Set-Cookie header in cookie-heavy sessions.
  4. Coordinate a disclosure date — we are targeting 90 days from first contact.

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