CVE-2025-66570 in cpp-httplib – Critical Header Shadowing Vulnerability Explained
A critical vulnerability (CVE-2025-66570, GHSA-xm2j-vfr9-mg9m) has been identified in cpp-httplib, a popular single-header C++ HTTP/HTTPS library used in many lightweight services, internal tools, and embedded applications. Prior to version 0.27.0, cpp-httplib incorrectly accepts and processes certain reserved header names directly from client requests, including: REMOTE_ADDR,REMOTE_PORT,LOCAL_ADDR,LOCAL_PORT.
Because these values are parsed before httplib injects the server’s own connection metadata, an attacker can override what the server believes to be the client’s IP, port, or local connection details. Any application logic that relies on these fields for authorization, logging, audit trails, or network trust decisions can be misled.
This issue effectively turns internal metadata into attacker-controlled input.
What is cpp-httplib?
cpp-httplib is a lightweight, header-only HTTP/HTTPS library implemented in modern C++. Its simplicity and ease of integration make it common across a wide range of environments, including microservices, internal admin tools, agent-based systems, embedded devices, automation workflows, and local development servers. Because the library is distributed as a single header file, it is frequently embedded transitively within other projects, often without developers being fully aware that it is present.
What versions are affected?
This vulnerability affects:
- cpp-httplib versions
≤ 0.26.0
The issue is resolved in:
- cpp-httplib
0.27.0
How to Identify If You’re Affected by CVE-2025-66570 in cpp-httplib
Search your codebase or dependency tree for a direct or vendored copy of httplib.h.
Common signs of vulnerability:
1. You are using cpp-httplib ≤ 0.26.0
Check build scripts, Bazel rules, Docker images, embedded libraries, or vendor folders for:
httplib.hCopied
2. Your application relies on values retrieved through:
req.get_header_value("REMOTE_ADDR")
req.get_header_value("REMOTE_PORT")
req.get_header_value("LOCAL_ADDR")
req.get_header_value("LOCAL_PORT")Copied
These header lookups returned attacker-controlled values before version 0.27.0.
3. You use these values for trust or decision-making, such as:
- IP-based allowlists
- admin-only route restrictions
- determining “internal vs external” access
- audit logging or SOC telemetry
- deriving client identity or trust level
Any of these patterns increases risk.
Vulnerable Code Implementation
The vulnerability is triggered through normal request handling. The cpp-httplib code:
- Parses all client headers into a multimap.
- Later inserts its own connection metadata using the same header names.
- Returns the first header value when an application calls
get_header_value().
This allows client-supplied headers to override internal ones.
Vulnerable Code
cpp-httplib inserts connection metadata into the request using header names that attackers can also supply:
// Server::process_request (pre-0.27.0)
req.remote_addr = remote_addr;
req.remote_port = remote_port;
req.set_header("REMOTE_ADDR", req.remote_addr);
req.set_header("REMOTE_PORT", std::to_string(req.remote_port));
req.local_addr = local_addr;
req.local_port = local_port;
req.set_header("LOCAL_ADDR", req.local_addr);
req.set_header("LOCAL_PORT", std::to_string(req.local_port));Copied
Applications commonly retrieve these values through header lookups:
auto ip = req.get_header_value("REMOTE_ADDR");Copied
Internally, cpp-httplib returns the first header value for a key, making attacker-supplied entries take precedence over server-supplied metadata:
auto rng = headers.equal_range(key);
auto it = rng.first; // attacker-controlled header appears firstCopied
This first-value-wins behavior is what enabled header shadowing, allowing malicious clients to override metadata such as REMOTE_ADDR and influence authorization, logging, and auditing logic.
How to Protect against CVE-2025-66570
The most effective fix is to upgrade, but several defensive measures can help reduce exposure until the patch is applied.
- Upgrade to cpp-httplib 0.27.0 – This release blocks the use of reserved header names and prevents clients from injecting
REMOTE_*orLOCAL_*values.
- Stop using
get_header_value()for connection metadata: Instead of relying on header lookups, applications should use the dedicated metadata fields:
req.remote_addr
req.remote_port
req.local_addr
req.local_portCopied
These values are not influenced by client input.
- Sanitize or remove incoming headers that overlap with internal metadata. Reject or strip any client-supplied headers that begin with:
REMOTE_*LOCAL_*
- Validate proxy boundaries – Only honor X-Forwarded-For or similar headers when they originate from a trusted proxy. Unvalidated forwarding headers allow attackers to bypass IP-based logic.
- Separate internal metadata from user-controlled headers. Applications should avoid using user-visible header maps as a source of truth for sensitive information such as client IPs, identity, or network classification.
Securing Your Application with Upwind
Upgrading to cpp-httplib 0.27.0 is the most important step, but protecting your environment requires visibility into where the vulnerable library is running and whether attackers are attempting to exploit it.
Upwind provides that coverage by:
- Mapping vulnerable versions of httplib.h across your workloads
- Monitoring runtime behavior for spoofed or inconsistent metadata
- Detecting suspicious headers that may indicate an attempt to override REMOTE_ADDR or related fields
- Our behavioral monitoring flags anomalies such as unexpected internal-IP impersonation or log patterns inconsistent with real network paths.
Together, these capabilities help ensure that applications relying on cpp-httplib remain protected even in environments where legacy code or embedded dependencies are difficult to update immediately.
For assistance in identifying vulnerable components or to learn more about our runtime protections, reach out to [email protected].