{"vulnerability": "cve-2024-6874", "sightings": [{"uuid": "375a165e-f0c4-4d27-82b3-2b62cf2b763a", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2024-6874", "type": "seen", "source": "https://www.cisa.gov/news-events/ics-advisories/icsa-26-043-06", "content": "", "creation_timestamp": "2026-02-12T11:00:00.000000Z"}, {"uuid": "0dbf92d6-f1f8-469d-a65a-6d5f4a7881fe", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2024-6874", "type": "seen", "source": "https://t.me/cvedetector/1548", "content": "{\n  \"Source\": \"CVE FEED\",\n  \"Title\": \"CVE-2024-6874 - Libcurl Punycode Buffer Overflow\", \n  \"Content\": \"CVE ID : CVE-2024-6874 \nPublished : July 24, 2024, 8:15 a.m. | 27\u00a0minutes ago \nDescription : libcurl's URL API function  \n[curl_url_get()]() offers punycode  \nconversions, to and from IDN. Asking to convert a name that is exactly 256  \nbytes, libcurl ends up reading outside of a stack based buffer when built to  \nuse the *macidn* IDN backend. The conversion function then fills up the  \nprovided buffer exactly - but does not null terminate the string.  \n  \nThis flaw can lead to stack contents accidently getting returned as part of  \nthe converted string. \nSeverity: 0.0 | NA \nVisit the link for more details, such as CVSS details, affected products, timeline, and more...\",\n  \"Detection Date\": \"24 Jul 2024\",\n  \"Type\": \"Vulnerability\"\n}\n\ud83d\udd39 t.me/cvedetector \ud83d\udd39", "creation_timestamp": "2024-07-24T10:47:44.000000Z"}, {"uuid": "0848c967-6f45-4527-83e5-facf55f77b2c", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2024-6874", "type": "seen", "source": "https://gist.github.com/Caixa-git/b651dc90f3055319340ba3e6976fb35e", "content": "# Vulnerability Report: curl/libcurl PUSH_PROMISE Heap Buffer Over-read\n\n## Summary\n\nA heap buffer over-read vulnerability exists in curl's HTTP/2 implementation (`lib/http2.c` line 1489). When processing PUSH_PROMISE frames, the `on_header` callback uses `curl_maprintf(\"%s:%s\", ...)` to store header name:value pairs, but the `name` and `value` pointers provided by the nghttp2 library are **not guaranteed to be null-terminated**. The `%s` format specifier reads past the intended buffer boundary until a null byte is found, causing an out-of-bounds heap read.\n\n## Vulnerability Details\n\n### Bug Location\n\n**File:** `lib/http2.c` \u2014 line 1489  \n**Function:** `on_header()` (callback invoked by nghttp2 for each HTTP/2 header)  \n**Trigger:** PUSH_PROMISE frame processing\n\n### Vulnerable Code\n\n```c\n// line 1489 \u2014 BUG: name/value are NOT null-terminated\nh = curl_maprintf(\"%s:%s\", name, value);\n```\n\n### Root Cause\n\nThe `on_header` callback receives `name` and `value` as `const uint8_t *` pointers into nghttp2's internal HPACK decoding buffer. The nghttp2 API documentation explicitly documents length-limited parameters:\n\n```\ntypedef int (*nghttp2_on_header_callback)(\n    nghttp2_session *session,\n    const nghttp2_frame *frame,\n    const uint8_t *name,   // NOT null-terminated\n    size_t namelen,         // length provided separately\n    const uint8_t *value,  // NOT null-terminated\n    size_t valuelen,        // length provided separately\n    uint8_t flags,\n    void *userp\n);\n```\n\nUsing `%s` with a non-null-terminated buffer causes:\n1. **Heap memory leak** \u2014 contiguous heap data following the intended value is read into the header string\n2. **Potential crash** \u2014 reading across a memory page boundary into unmapped memory causes SIGSEGV\n3. **Information disclosure** \u2014 the over-read data is stored in `push_headers[]` and passed to the application's `CURLOPT_PUSHFUNCTION` callback\n\n### Correct Pattern (exists in same file)\n\nThe same function correctly handles non-null-terminated data in the trailer processing path (line 1500):\n\n```c\n// line 1500 \u2014 CORRECT: uses %.*s with explicit length\nCURL_TRC_CF(data_s, cf, \"[%d] trailer: %.*s: %.*s\",\n            stream-&gt;id, (int)namelen, name, (int)valuelen, value);\n```\n\nAnd in the non-PUSH header path (line 1502):\n\n```c\n// line 1502 \u2014 CORRECT: uses explicit length\nresult = Curl_dynhds_add(&amp;stream-&gt;resp_trailers,\n                         (const char *)name, namelen,\n                         (const char *)value, valuelen);\n```\n\n### Fix\n\nReplace line 1489 with:\n\n```c\nh = curl_maprintf(\"%.*s:%.*s\", (int)namelen, name, (int)valuelen, value);\n```\n\n## Impact\n\n| Impact | Description |\n|--------|-------------|\n| **Information Disclosure** | Heap contents adjacent to the header value buffer are read and returned to the application through `curl_pushheader_bynum()` / `curl_pushheader_byname()` in the PUSH callback. This can leak sensitive heap data (session keys, TLS buffers, other connection data) to the application. |\n| **Denial of Service** | If the over-read crosses a page boundary into unmapped memory, the process crashes with SIGSEGV. |\n| **Data Corruption** | A malformed string may cause incorrect parsing of pushed headers by the application. |\n\n**Attack Vector:** A malicious or compromised HTTP/2 server sends a crafted PUSH_PROMISE frame. The attacker needs to be in control of the HTTP/2 server or have MITM capability (TLS interception).\n\n**CWE Classification:** CWE-125: Out-of-bounds Read  \n**C Mistake Category:** OVERREAD\n\n## Affected Versions\n\n- **Affected:** All versions of curl built with HTTP/2 support (nghttp2) that include PUSH_PROMISE handling\n- **First vulnerable:** commit introducing PUSH_PROMISE support in `on_header` callback\n- **Last vulnerable:** latest released version (the bug remains unpatched at time of report)\n\nThe vulnerability requires `CURLOPT_PUSHFUNCTION` to be set by the application for the heap data to be leaked to the caller. However, the buffer over-read itself occurs regardless \u2014 the heap data is read into `push_headers[]` memory regardless of whether the application registers a push callback.\n\n## Steps to Reproduce\n\n### Method 1: Code Analysis (Static)\n\nExamine `lib/http2.c` lines 1489 and 1500-1504 side by side:\n\n```\nLine 1489:   h = curl_maprintf(\"%s:%s\", name, value);                    \u2190 BUG\nLine 1500:   ... \"%.*s: %.*s\", (int)namelen, name, (int)valuelen, value  \u2190 CORRECT\nLine 1502-3: Curl_dynhds_add(..., name, namelen, value, valuelen);      \u2190 CORRECT\n```\n\nThe same function uses three different patterns for the same data. Only the PUSH_PROMISE path uses the unsafe `%s`.\n\n### Method 2: AddressSanitizer (Dynamic)\n\n1. Build curl with AddressSanitizer:\n   ```bash\n   mkdir build-asan &amp;&amp; cd build-asan\n   cmake .. -DCMAKE_BUILD_TYPE=Debug \\\n            -DCMAKE_C_FLAGS=\"-fsanitize=address -fno-omit-frame-pointer\" \\\n            -DCMAKE_EXE_LINKER_FLAGS=\"-fsanitize=address\"\n   make -j$(nproc)\n   ```\n\n2. Run the PoC malicious HTTP/2 server (Python, see attached):\n   ```bash\n   python3 poc_server.py\n   ```\n\n3. Connect with curl setting a PUSH callback:\n   ```bash\n   curl --http2-prior-knowledge -k https://localhost:8443/push-test\n   ```\n\n4. ASAN will report a heap-buffer-overflow on the `curl_maprintf` call.\n\n### Method 3: Manual Trigger\n\nWrite a minimal C program using `curl_multi` with `CURLMOPT_PUSHFUNCTION`:\n```c\nstatic int push_cb(CURL *parent, CURL *child,\n                   size_t num_headers,\n                   struct curl_pushheaders *headers,\n                   void *userp) {\n    for (size_t i = 0; i &lt; num_headers; i++) {\n        char *h = curl_pushheader_bynum(headers, i);\n        // h may contain heap data beyond the intended header value\n        printf(\"[%zu] %s\\n\", i, h);\n    }\n    return CURL_PUSH_DENY;\n}\n```\n\n## Supporting Material\n\nAttached:\n1. `poc_server.py` \u2014 Malicious HTTP/2 server that sends crafted PUSH_PROMISE\n2. `test_poc.py` \u2014 Automated test harness with ASAN build\n3. Code diff showing the bug and its fix\n\n## Timeline\n\n- **Discovery:** 2026-05-08\n- **Reported:** [Date of HackerOne submission]\n- **curl advisory:** Pending\n\n## Reporter\n\n- **Name:** [Your Name]\n- **HackerOne:** [Your HackerOne handle]\n\n---\n\n## Appendix A: Fix Commit Preview\n\n```diff\n--- a/lib/http2.c\n+++ b/lib/http2.c\n@@ -1486,7 +1486,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,\n       stream-&gt;push_headers = headp;\n     }\n-    h = curl_maprintf(\"%s:%s\", name, value);\n+    h = curl_maprintf(\"%.*s:%.*s\", (int)namelen, name, (int)valuelen, value);\n     if(!h) {\n       free_push_headers(stream);\n       return NGHTTP2_ERR_CALLBACK_FAILURE;\n```\n\n## Appendix B: CWE Reference\n\nCWE-125: Out-of-bounds Read  \nThe product reads data past the end, or before the beginning, of the intended buffer.\n\n## Appendix C: Related CVEs (same pattern in curl)\n\n| CVE | Description | Severity | Bounty |\n|-----|-------------|----------|--------|\n| CVE-2025-9086 | Out of bounds read for cookie path | Low | $505 |\n| CVE-2024-7264 | ASN.1 date parser overread | Low | $540 |\n| CVE-2024-6874 | macidn punycode buffer overread | Low | $540 |\n", "creation_timestamp": "2026-05-11T12:23:09.000000Z"}]}