TinyWeb Integer Overflow in _Val (HTTP Request Smuggling)
Security Advisory. Published: March 3, 2026. Fixed in TinyWeb v2.03 (February 28, 2026).
Summary
An integer overflow vulnerability in the string-to-integer conversion routine (_Val)
in xBase.pas allows an unauthenticated remote attacker to bypass
Content-Length restrictions and perform HTTP Request Smuggling. By sending a crafted
Content-Length value that overflows a 32-bit integer, the server reads only a small
fraction of the declared body, leaving residual data in the socket buffer that is subsequently
interpreted as a new request. This can lead to unauthorized access, security filter bypass, and
potential web cache poisoning. The impact is most severe for servers using persistent
(Keep-Alive) connections.
Severity: High (CVSS 4.0 Base Score: 8.7)
Vulnerability Details
| CVE ID | CVE-2026-28497 |
|---|---|
| Vulnerability Type | Integer Overflow (CWE-190), HTTP Request Smuggling (CWE-444) |
| Attack Type | Remote |
| Attack Vector | Network (unauthenticated HTTP request) |
| Vendor/Maintainer | Maxim Masiutin |
| Product | TinyWeb HTTP Server |
| Affected Versions | All versions prior to v2.03 |
| Fixed Version | 2.03 (February 28, 2026) |
| Impact | HTTP Request Smuggling, Security Filter Bypass, Cache Poisoning |
CVSS Score
| CVSS Version | Score | Severity | Vector String |
|---|---|---|---|
| CVSS 4.0 | 8.7 | High | AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N |
Technical Details
Root Cause
The vulnerability resides in SRC/xBase.pas within the _Val function
(lines 2961-2979), which is used by StoI to parse the Content-Length
HTTP header value in SrvMain.pas. The implementation accumulates decimal digits
into a 32-bit signed integer without checking for overflow. When the accumulated value exceeds
the maximum representable range (2,147,483,647), the result wraps to a small positive number.
Mechanism
For example, the value 4294967306 (2^32 + 10) overflows a signed 32-bit integer
and produces the result 10. While a frontend proxy forwards the full declared
payload, TinyWeb reads only 10 bytes as the request body. The remaining data stays in the
socket receive buffer and TinyWeb processes it as the beginning of a subsequent HTTP request
on the same Keep-Alive connection.
Proof of Concept
Send a crafted POST request with an overflowing Content-Length:
POST /index.html HTTP/1.1 Host: localhost Content-Length: 4294967306 Connection: keep-alive [10 bytes of body][Smuggled HTTP request follows here...]
TinyWeb parses 4294967306 as 10, reads only the first 10 bytes as the
POST body, and then processes the smuggled data as a new independent request.
Attack Scenarios
- Security Filter Bypass: An attacker smuggles a request to a restricted
path (e.g.,
POST /admin/delete) inside a harmless outer request. Frontend security filters inspect only the outer request and allow it through, while TinyWeb processes the inner smuggled request against the protected resource. - Web Cache Poisoning: The smuggled inner request causes TinyWeb to return a malicious response for a popular resource. A caching frontend may store and serve this response to subsequent users.
- CL.0 Smuggling: The backend treats the overflowing
Content-Lengthas a small value while the frontend honors the large declared length, producing desynchronization between the two sides of the connection. - Credential Theft via Request Hijacking: The smuggled request is crafted to append itself to the next legitimate user's request. When that user sends their request (including session cookies), it is appended to the attacker's smuggled request payload, potentially leaking the user's credentials or session data.
RFC Compliance
According to RFC 9110 (Section 8.6) and RFC 9112 (Section 6.3),
a server MUST NOT forward or accept a message with a malformed Content-Length
header. The ABNF for Content-Length is strictly 1*DIGIT and any
value exceeding the server's representable integer range must be treated as a protocol error,
resulting in a 400 Bad Request response with the connection closed.
Fix Applied in Version 2.03
The problem has been patched in version 2.03. The updated _Val
routine implements strict overflow detection during digit accumulation. Any
Content-Length value that would exceed the 32-bit signed integer range now
causes the server to reject the request with a 400 Bad Request response and
close the connection.
- Fix commit: d2edd03
in
xBase.pas
Workarounds
If upgrading to v2.03 is not immediately possible, consider the following mitigations:
- Place the server behind a robust reverse proxy or Web Application Firewall (WAF) such
as nginx, HAProxy, or Cloudflare configured to normalize and validate
Content-Lengthvalues before forwarding requests to TinyWeb. - Disable persistent (Keep-Alive) connections if feasible. Without connection reuse, the smuggled data cannot be interpreted as a new request.
- Ensure the frontend proxy strips or rejects requests that contain ambiguous or
out-of-range
Content-Lengthvalues per RFC 9112 Section 6.3.
References
- TinyWeb GitHub Repository
- Fix Commit d2edd03
- CWE-190: Integer Overflow or Wraparound
- CWE-444: Inconsistent Interpretation of HTTP Requests (HTTP Request Smuggling)
- RFC 9110 Section 8.6 - Content-Length
- RFC 9112 Section 6.3 - Message Body Length
- CVE-2019-18277: HAProxy HTTP Request Smuggling via Integer Overflow
- CVE-2020-11724: OpenResty HTTP Request Smuggling