Someone left two price tags on the same item, and the cashier and the shelf stocker each read a different one
CVE-2026-54388 is an HTTP Request Smuggling flaw in Tinyproxy through version 1.11.3. The proxy fails to reject HTTP requests carrying multiple Content-Length headers with differing values. Instead, it reads the *first* value to decide how many body bytes to consume, then dutifully forwards *all* duplicate headers to the backend. If the backend server picks the *second* value, the two parsers desynchronize: the leftover bytes the proxy thought were part of the body become a brand-new, attacker-controlled request in the backend's eyes. This enables cache poisoning, access-control bypass, session hijacking, and exposure of internal endpoints—all without authentication.
The vendor-assigned CVSS 9.1 CRITICAL assumes the worst-case: unauthenticated, no user interaction, high confidentiality and integrity impact. That vector is *technically correct* but ignores two enormous real-world filters. First, the attack only works if the backend server also mishandles the duplicate Content-Length headers rather than rejecting them per RFC 7230 §3.3.2 (many modern stacks—Go net/http, recent Apache, nginx—do reject them). Second, Tinyproxy is a 2 MB lightweight proxy designed for embedded devices, Raspberry Pis, small-office WiFi, and container sidecars—not the proxy of choice for enterprises managing 10,000 hosts. The vendor severity overweights the theoretical attack surface and underweights the narrow blast radius and conditional backend requirement.
4 steps from start to impact.
Identify an exposed Tinyproxy instance
Via header or Server header leak the proxy identity). Censys data from 2024 showed ~90,000 internet-facing instances globally. Shodan dorks like Server: tinyproxy surface targets quickly.- Tinyproxy is network-reachable to the attacker (internet or internal)
- Most enterprise environments use Squid, HAProxy, nginx, or commercial proxies; Tinyproxy is rare in large fleets
- Many Tinyproxy instances are ACL-restricted to trusted subnets via
Allowdirectives
Content-Length headersCraft a request with duplicate Content-Length headers
Content-Length headers with different values. Tinyproxy reads the first value to determine how many bytes of the body to consume, but forwards both headers verbatim to the backend. No authentication or special privileges are required. Tools like smuggler.py (defparam) or http-request-smuggler (Burp extension by James Kettle / PortSwigger) automate this probing.- Network access to the proxy port (default 8888)
- Some upstream load balancers or WAFs normalize or reject duplicate Content-Length headers before they reach Tinyproxy
Backend parser desynchronization
Content-Length values. If it picks the *second* (or last) value, it reads a different number of body bytes than Tinyproxy consumed. The remaining bytes sit in the TCP stream and are parsed as the start of a new, independent HTTP request by the backend.- Backend server must NOT reject duplicate Content-Length headers per RFC 7230
- Backend must pick a *different* Content-Length value than Tinyproxy (first vs. last)
- RFC 7230 §3.3.2 mandates rejection of messages with multiple differing Content-Length values; compliant servers (Go net/http, recent nginx, recent Apache) reject such requests outright
- Backend frameworks that normalize headers to a single value also break the chain
Smuggled request reaches backend
- Backend trusts requests from the proxy IP or forwards them without re-authentication
- A shared cache or multi-tenant backend amplifies impact
- Single-user or single-purpose backends limit blast radius to one application
- Zero-trust architectures that require per-request authentication on the backend neutralize the smuggled request
Host headers, path mismatches, or response poisoning indicatorsThe supporting signals.
| In-the-Wild Exploitation | No confirmed active exploitation as of 2026-08-03. Not listed in CISA KEV. |
|---|---|
| Proof of Concept | No public PoC specific to CVE-2026-54388. Generic HTTP smuggling tools (smuggler.py by defparam, PortSwigger http-request-smuggler) can probe for the condition. Trivial to craft manually with curl or netcat. |
| EPSS | 0.00439 (~top 15% probability of exploitation in 30 days) — low signal, consistent with no observed exploitation. |
| KEV Status | Not listed. No CISA KEV entry as of 2026-08-03. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N — Network/no-auth/no-interaction is accurate; C:H and I:H assume a cooperative backend, which is the main point of contention. |
| Affected Versions | All Tinyproxy releases through 1.11.3. No tagged release yet contains the fix. |
| Fixed Version | Commit 364cdb67e0ea00a8e4a7037e2693e0711e816adb on the main branch. No versioned release cut yet; distro backports pending. |
| Exposure Data | Censys (May 2024): ~90,310 internet-facing Tinyproxy instances globally. US: ~11,946, South Korea: ~3,732. Numbers likely similar or slightly higher in 2026. |
| Disclosure Date | 2026-06-17 |
| Researcher | Tristan Madani (@TristanInSec) |
noisgate verdict.
The single most decisive downgrade factor is the conditional backend dependency: the smuggling chain only completes if the backend server also mishandles duplicate Content-Length headers, which RFC 7230-compliant servers reject outright. This transforms a theoretical unauthenticated-remote-CRITICAL into a real-world HIGH that requires a specific, non-compliant backend pairing to deliver impact.
Why this verdict
- Backend compliance gate: RFC 7230 §3.3.2 requires servers to reject messages with multiple differing Content-Length values. Modern Go, nginx, and Apache stacks comply. This single prerequisite blocks the chain in a large fraction of deployments, removing the AC:L assumption from the vendor score.
- Small enterprise footprint: Tinyproxy is a 2 MB embedded-class proxy. Enterprises managing 10,000+ hosts overwhelmingly use Squid, HAProxy, nginx, or commercial proxies. The affected population in a typical large fleet is near zero.
- No exploitation activity: Zero KEV listing, no confirmed in-the-wild campaigns, EPSS at 0.44%, and no weaponized public PoC. The threat is theoretical today.
- Unauthenticated network vector is real: The AV:N/PR:N/UI:N vector is accurate—no credentials or user clicks needed. This prevents a deeper downgrade below HIGH.
- Role multiplier: Tinyproxy is NOT a canonical high-value-role component. It is not an identity provider, domain controller, hypervisor, PAM vault, backup server, CI/CD system, or network edge appliance. Its canonical deployment roles are (a) embedded device forward proxy, (b) container sidecar proxy, (c) small-office internet gateway. In the rare case it fronts a sensitive multi-tenant API backend with a non-RFC-compliant server, the blast radius could reach tenant-level data exposure, but this is an edge case representing well under 1% of installs. No high-value-role floor is triggered.
Why not higher?
The vendor's CRITICAL/9.1 assumes every backend will cooperatively misparse the smuggled headers. In practice, RFC 7230-compliant backends reject the malformed request outright, collapsing the chain before impact. There is no active exploitation, no PoC, and the EPSS is below 0.5%. The affected component is not a canonical high-value target.
Why not lower?
The vulnerability is unauthenticated and network-reachable with no user interaction—the most dangerous access vector class. HTTP smuggling, when it works, delivers high-impact outcomes (cache poisoning, access-control bypass, session hijacking) that can affect multiple users. Roughly 90,000 instances are internet-exposed. These factors together prevent a drop below HIGH.
What to do — in priority order.
- Block duplicate Content-Length headers at the WAF or load balancer — Configure your WAF (ModSecurity, AWS WAF, Cloudflare) or upstream load balancer to reject any HTTP request containing more than one
Content-Lengthheader. This neutralizes the attack vector entirely. Deploy within 30 days per noisgate mitigation SLA for HIGH. - Restrict Tinyproxy to trusted source IPs via Allow directives — In
tinyproxy.conf, ensureAllowdirectives limit connections to known internal subnets. This reduces the attack surface from internet-wide to internal-only. Deploy within 30 days. - Place an RFC 7230-compliant reverse proxy in front of the backend — If you cannot patch Tinyproxy immediately, ensure the backend or an intermediary proxy (nginx, Envoy) rejects requests with duplicate Content-Length headers. This breaks the smuggling chain at step 3.
- Upgrade Tinyproxy to a build containing commit 364cdb6 — Build from the main branch post-commit
364cdb67e0eaor wait for the next tagged release / distro package update. This is the definitive remediation. Apply within 180 days per noisgate remediation SLA for HIGH.
- TLS/HTTPS termination alone does not help—the smuggling occurs at the HTTP layer regardless of transport encryption.
- Rate limiting does not prevent smuggling; a single crafted request is sufficient to inject a smuggled payload.
- IP reputation blocklists are ineffective because the attack requires only one request from any source IP, and the attacker can use clean IPs.
Crowdsourced verification payload.
Run this on any host where Tinyproxy is installed. Execute as any user with read access to the tinyproxy binary. Example: bash check_cve_2026_54388.sh /usr/sbin/tinyproxy or simply bash check_cve_2026_54388.sh to auto-detect.
#!/usr/bin/env bash
# check_cve_2026_54388.sh - Check if Tinyproxy is vulnerable to CVE-2026-54388
# Usage: bash check_cve_2026_54388.sh [/path/to/tinyproxy]
# Exit codes: 0=VULNERABLE, 1=PATCHED, 2=UNKNOWN
set -euo pipefail
BINARY="${1:-$(command -v tinyproxy 2>/dev/null || echo "")}"
if [ -z "$BINARY" ]; then
echo "UNKNOWN - tinyproxy binary not found. Provide path as argument."
exit 2
fi
if [ ! -x "$BINARY" ]; then
echo "UNKNOWN - $BINARY is not executable."
exit 2
fi
VERSION=$($BINARY -v 2>&1 | grep -oP '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [ -z "$VERSION" ]; then
echo "UNKNOWN - could not determine Tinyproxy version."
exit 2
fi
echo "Detected Tinyproxy version: $VERSION"
# All versions through 1.11.3 are vulnerable
# Compare version: vulnerable if <= 1.11.3
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
if [ "$MAJOR" -lt 1 ]; then
echo "VULNERABLE - Tinyproxy $VERSION is affected by CVE-2026-54388."
exit 0
elif [ "$MAJOR" -eq 1 ] && [ "$MINOR" -lt 11 ]; then
echo "VULNERABLE - Tinyproxy $VERSION is affected by CVE-2026-54388."
exit 0
elif [ "$MAJOR" -eq 1 ] && [ "$MINOR" -eq 11 ] && [ "$PATCH" -le 3 ]; then
echo "VULNERABLE - Tinyproxy $VERSION is affected by CVE-2026-54388."
exit 0
else
echo "PATCHED - Tinyproxy $VERSION is beyond the affected range (<=1.11.3)."
exit 1
fiIf you remember one thing.
Content-Length header block as a compensating control within the noisgate mitigation SLA of 30 days for HIGH. Plan to upgrade Tinyproxy to a build containing commit 364cdb6 (or the next tagged release that includes it) within the noisgate remediation SLA of 180 days. If you do not run Tinyproxy—and most large enterprises do not—verify that assumption with a quick Shodan/Censys check of your perimeter and move on. There is no active exploitation or KEV listing, so this is a scheduled patch, not a fire drill.Sources
- Security Online – Tinyproxy Request Smuggling Flaws
- GHSA-P3H9-73G9-X6M3 – Vulnerability Lookup (CIRCL)
- Censys Advisory – Tinyproxy Exposure Data
- BleepingComputer – 50,000 Tinyproxy Servers Vulnerable
- THREATINT – CVE-2026-54388
- Black Kite TPRM Insights – TinyProxy
- Tinyproxy Official Site
- SANS @Risk Newsletter Vol. XXVI-25
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.