VULNARCHIVE

GCVE-1988-2026-0076

WatsonWebserver v7.1.0 HTTP/1 Chunked Request Processing Bypasses MaxRequestBodySize

Description (en)

WatsonWebserver contains an HTTP/1 request body size-limit bypass when
processing requests using Transfer-Encoding: chunked.

The framework's configured Settings.IO.MaxRequestBodySize limit is enforced
when a request declares its body size using Content-Length. However,
requests using chunked transfer encoding are processed through a separate
body-reading path that accumulates decoded chunks into a MemoryStream
without enforcing the same cumulative request-body limit.

As a result, a remote client can submit an HTTP/1 request whose decoded
body exceeds the administrator-configured MaxRequestBodySize by using
chunked transfer encoding instead of Content-Length.

A proof of concept configured:

MaxRequestBodySize = 16 bytes

and submitted a chunked request containing:

24 bytes

of decoded body data.

WatsonWebserver accepted the complete request, delivered all 24 bytes to
the application, and returned:

HTTP/1.1 200 OK

len=24

This confirms that MaxRequestBodySize is not consistently enforced across
supported HTTP/1 request-framing mechanisms.

Because the chunked body is accumulated in memory without a cumulative
MaxRequestBodySize check, an attacker may also be able to cause excessive
memory and CPU consumption by submitting substantially larger request
bodies. The supplied PoC directly demonstrates the size-limit bypass;
denial of service is a potential consequence rather than a demonstrated
result of the 24-byte test.


Vulnerability Description

WatsonWebserver provides the following configuration setting for
restricting HTTP request body size:

Settings.IO.MaxRequestBodySize

For HTTP/1 requests containing a Content-Length header, WatsonWebserver
parses the declared body size and rejects the request when it exceeds the
configured maximum.

However, HTTP/1 also permits request bodies to be framed using:

Transfer-Encoding: chunked

Chunked requests do not contain a single up-front Content-Length. Instead,
the body is transmitted as a sequence of independently sized chunks.

WatsonWebserver handles these requests through ReadChunkedBodyAsync(),
which repeatedly reads chunks and writes their contents into an in-memory
MemoryStream.

The implementation does not maintain a cumulative decoded-body length and
does not compare the accumulated size against Settings.IO.MaxRequestBodySize
.

Consequently, a client can bypass the configured request body limit simply
by changing the HTTP framing mechanism from Content-Length to
Transfer-Encoding:
chunked.


Technical AnalysisContent-Length Path

When WatsonWebserver encounters a request containing Content-Length, the
parsed length is stored in:

metadata.ContentLength = parsedContentLength;

The framework subsequently enforces MaxRequestBodySize:

if (settings.IO.MaxRequestBodySize > 0 &&
    metadata.ContentLength > settings.IO.MaxRequestBodySize)
{
    throw new IOException(
        "Request body size "
        + metadata.ContentLength
        + " exceeds maximum allowed size "
        + settings.IO.MaxRequestBodySize
        + ".");
}

The configured maximum is therefore enforced for requests whose body
length is known through Content-Length.


Chunked Request Path

Requests using:

Transfer-Encoding: chunked

follow a different body-processing path.

The relevant implementation is:

private async Task<byte[]> ReadChunkedBodyAsync(
    CancellationToken token)
{
    using (MemoryStream memoryStream = new MemoryStream())
    {
        while (true)
        {
            Chunk chunk =
                await ReadChunk(token)
                .ConfigureAwait(false);

            if (chunk.Data != null &&
                chunk.Data.Length > 0)
            {
                memoryStream.Write(
                    chunk.Data,
                    0,
                    chunk.Data.Length);
            }

            if (chunk.IsFinal)
                break;
        }

        _BodyComplete = true;

        return memoryStream.ToArray();
    }
}

Each decoded chunk is appended directly to the MemoryStream:

memoryStream.Write(
    chunk.Data,
    0,
    chunk.Data.Length);

There is no equivalent check against:

Settings.IO.MaxRequestBodySize

before the write.

The loop continues until the terminating chunk is received.


Proof of ConceptServer Configuration

The proof of concept configures WatsonWebserver with:

server.Settings.IO.MaxRequestBodySize = 16;

The maximum accepted request body should therefore be:

16 bytes

Malicious Request

The client submits a valid chunked HTTP/1 request:

POST / HTTP/1.1
Host: 127.0.0.1
Transfer-Encoding: chunked
Connection: close

8
abcdefgh
8
ijklmnop
8
qrstuvwx
0

The request contains three chunks.

Each chunk contains:

8 bytes

giving a cumulative decoded request body of:

8 + 8 + 8 = 24 bytes

The body therefore exceeds the configured limit by:

24 - 16 = 8 bytes

or:

150% of the configured maximum.

Observed HTTP Response

WatsonWebserver accepts the request and returns:
HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 6 Date: Thu, 06
Aug 2026 01:16:34 GMT Connection: close Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: OPTIONS, HEAD, GET, PUT, POST, DELETE, PATCH
Access-Control-Allow-Headers: * Access-Control-Expose-Headers: Accept: */*
Accept-Language: en-US, en Accept-Charset: ISO-8859-1, utf-8 Cache-Control:
no-cache Host: 127.0.0.1:44009 len=24

The application reports:
len=24

confirming that the complete decoded body reached the application despite:
MaxRequestBodySize = 16

Security ImpactConfirmed Impact

The PoC directly demonstrates that a remote HTTP client can bypass the
configured:

Settings.IO.MaxRequestBodySize

restriction when using chunked transfer encoding.

The confirmed impact is therefore:

   - bypass of the configured HTTP request-body size restriction;
   - acceptance of request bodies larger than the administrator-defined
   maximum; and
   - in-memory processing of data that should have been rejected by the
   configured limit.

Resource Consumption

The affected chunked path accumulates the decoded body in a MemoryStream:

memoryStream.Write(
    chunk.Data,
    0,
    chunk.Data.Length);

and ultimately performs:

return memoryStream.ToArray();

Because there is no cumulative MaxRequestBodySize check in this path,
substantially larger request bodies can potentially consume increasing
amounts of process memory and processing time.

Depending on deployment configuration, available resources, concurrency,
reverse proxies, transport timeouts, and application-specific controls,
this may contribute to:

   - excessive memory consumption;
   - increased CPU utilization;
   - request-processing degradation; and
   - denial of service.

The supplied 24-byte PoC demonstrates the *security-control bypass*, not
resource exhaustion itself.

Ron Edgerson
Vulnerability Researcher & Exploit Developer

CVE Research | Binary Exploitation | Application & Systems Security
Responsible Disclosure โ€ข Proof-of-Concept Development

๐ŸŒ https://github.com/ob1sec
๐Ÿ”— https://www.linkedin.com/in/ronedgerson1
<https://linkedin.com/in/yourhandle>
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/

References

Raw JSON
{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Watsonwebserver",
          "vendor": "Watsonwebserver Project",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "WatsonWebserver contains an HTTP/1 request body size-limit bypass when\nprocessing requests using Transfer-Encoding: chunked.\n\nThe framework's configured Settings.IO.MaxRequestBodySize limit is enforced\nwhen a request declares its body size using Content-Length. However,\nrequests using chunked transfer encoding are processed through a separate\nbody-reading path that accumulates decoded chunks into a MemoryStream\nwithout enforcing the same cumulative request-body limit.\n\nAs a result, a remote client can submit an HTTP/1 request whose decoded\nbody exceeds the administrator-configured MaxRequestBodySize by using\nchunked transfer encoding instead of Content-Length.\n\nA proof of concept configured:\n\nMaxRequestBodySize = 16 bytes\n\nand submitted a chunked request containing:\n\n24 bytes\n\nof decoded body data.\n\nWatsonWebserver accepted the complete request, delivered all 24 bytes to\nthe application, and returned:\n\nHTTP/1.1 200 OK\n\nlen=24\n\nThis confirms that MaxRequestBodySize is not consistently enforced across\nsupported HTTP/1 request-framing mechanisms.\n\nBecause the chunked body is accumulated in memory without a cumulative\nMaxRequestBodySize check, an attacker may also be able to cause excessive\nmemory and CPU consumption by submitting substantially larger request\nbodies. The supplied PoC directly demonstrates the size-limit bypass;\ndenial of service is a potential consequence rather than a demonstrated\nresult of the 24-byte test.\n\n\nVulnerability Description\n\nWatsonWebserver provides the following configuration setting for\nrestricting HTTP request body size:\n\nSettings.IO.MaxRequestBodySize\n\nFor HTTP/1 requests containing a Content-Length header, WatsonWebserver\nparses the declared body size and rejects the request when it exceeds the\nconfigured maximum.\n\nHowever, HTTP/1 also permits request bodies to be framed using:\n\nTransfer-Encoding: chunked\n\nChunked requests do not contain a single up-front Content-Length. Instead,\nthe body is transmitted as a sequence of independently sized chunks.\n\nWatsonWebserver handles these requests through ReadChunkedBodyAsync(),\nwhich repeatedly reads chunks and writes their contents into an in-memory\nMemoryStream.\n\nThe implementation does not maintain a cumulative decoded-body length and\ndoes not compare the accumulated size against Settings.IO.MaxRequestBodySize\n.\n\nConsequently, a client can bypass the configured request body limit simply\nby changing the HTTP framing mechanism from Content-Length to\nTransfer-Encoding:\nchunked.\n\n\nTechnical AnalysisContent-Length Path\n\nWhen WatsonWebserver encounters a request containing Content-Length, the\nparsed length is stored in:\n\nmetadata.ContentLength = parsedContentLength;\n\nThe framework subsequently enforces MaxRequestBodySize:\n\nif (settings.IO.MaxRequestBodySize > 0 &&\n    metadata.ContentLength > settings.IO.MaxRequestBodySize)\n{\n    throw new IOException(\n        \"Request body size \"\n        + metadata.ContentLength\n        + \" exceeds maximum allowed size \"\n        + settings.IO.MaxRequestBodySize\n        + \".\");\n}\n\nThe configured maximum is therefore enforced for requests whose body\nlength is known through Content-Length.\n\n\nChunked Request Path\n\nRequests using:\n\nTransfer-Encoding: chunked\n\nfollow a different body-processing path.\n\nThe relevant implementation is:\n\nprivate async Task<byte[]> ReadChunkedBodyAsync(\n    CancellationToken token)\n{\n    using (MemoryStream memoryStream = new MemoryStream())\n    {\n        while (true)\n        {\n            Chunk chunk =\n                await ReadChunk(token)\n                .ConfigureAwait(false);\n\n            if (chunk.Data != null &&\n                chunk.Data.Length > 0)\n            {\n                memoryStream.Write(\n                    chunk.Data,\n                    0,\n                    chunk.Data.Length);\n            }\n\n            if (chunk.IsFinal)\n                break;\n        }\n\n        _BodyComplete = true;\n\n        return memoryStream.ToArray();\n    }\n}\n\nEach decoded chunk is appended directly to the MemoryStream:\n\nmemoryStream.Write(\n    chunk.Data,\n    0,\n    chunk.Data.Length);\n\nThere is no equivalent check against:\n\nSettings.IO.MaxRequestBodySize\n\nbefore the write.\n\nThe loop continues until the terminating chunk is received.\n\n\nProof of ConceptServer Configuration\n\nThe proof of concept configures WatsonWebserver with:\n\nserver.Settings.IO.MaxRequestBodySize = 16;\n\nThe maximum accepted request body should therefore be:\n\n16 bytes\n\nMalicious Request\n\nThe client submits a valid chunked HTTP/1 request:\n\nPOST / HTTP/1.1\nHost: 127.0.0.1\nTransfer-Encoding: chunked\nConnection: close\n\n8\nabcdefgh\n8\nijklmnop\n8\nqrstuvwx\n0\n\nThe request contains three chunks.\n\nEach chunk contains:\n\n8 bytes\n\ngiving a cumulative decoded request body of:\n\n8 + 8 + 8 = 24 bytes\n\nThe body therefore exceeds the configured limit by:\n\n24 - 16 = 8 bytes\n\nor:\n\n150% of the configured maximum.\n\nObserved HTTP Response\n\nWatsonWebserver accepts the request and returns:\nHTTP/1.1 200 OK Content-Type: text/plain Content-Length: 6 Date: Thu, 06\nAug 2026 01:16:34 GMT Connection: close Access-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: OPTIONS, HEAD, GET, PUT, POST, DELETE, PATCH\nAccess-Control-Allow-Headers: * Access-Control-Expose-Headers: Accept: */*\nAccept-Language: en-US, en Accept-Charset: ISO-8859-1, utf-8 Cache-Control:\nno-cache Host: 127.0.0.1:44009 len=24\n\nThe application reports:\nlen=24\n\nconfirming that the complete decoded body reached the application despite:\nMaxRequestBodySize = 16\n\nSecurity ImpactConfirmed Impact\n\nThe PoC directly demonstrates that a remote HTTP client can bypass the\nconfigured:\n\nSettings.IO.MaxRequestBodySize\n\nrestriction when using chunked transfer encoding.\n\nThe confirmed impact is therefore:\n\n   - bypass of the configured HTTP request-body size restriction;\n   - acceptance of request bodies larger than the administrator-defined\n   maximum; and\n   - in-memory processing of data that should have been rejected by the\n   configured limit.\n\nResource Consumption\n\nThe affected chunked path accumulates the decoded body in a MemoryStream:\n\nmemoryStream.Write(\n    chunk.Data,\n    0,\n    chunk.Data.Length);\n\nand ultimately performs:\n\nreturn memoryStream.ToArray();\n\nBecause there is no cumulative MaxRequestBodySize check in this path,\nsubstantially larger request bodies can potentially consume increasing\namounts of process memory and processing time.\n\nDepending on deployment configuration, available resources, concurrency,\nreverse proxies, transport timeouts, and application-specific controls,\nthis may contribute to:\n\n   - excessive memory consumption;\n   - increased CPU utilization;\n   - request-processing degradation; and\n   - denial of service.\n\nThe supplied 24-byte PoC demonstrates the *security-control bypass*, not\nresource exhaustion itself.\n\nRon Edgerson\nVulnerability Researcher & Exploit Developer\n\nCVE Research | Binary Exploitation | Application & Systems Security\nResponsible Disclosure โ€ข Proof-of-Concept Development\n\n๐ŸŒ https://github.com/ob1sec\n๐Ÿ”— https://www.linkedin.com/in/ronedgerson1\n<https://linkedin.com/in/yourhandle>\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives & RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-11T11:53:58Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/104"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Aug/104"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Aug/104"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "WatsonWebserver v7.1.0 HTTP/1 Chunked Request Processing Bypasses MaxRequestBodySize",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0076",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/104",
            "automated": true,
            "contentSha256": "38816a813b8254c012b7c96eff0335ea6f0b2235d94514fcdf34162ca1e1d896",
            "evidenceScore": 7,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Aug/104",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-22T12:43:02Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T13:20:21Z",
    "dateUpdated": "2026-09-11T11:53:58Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0076"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}