NGINX HTTP/2 Frame Injection via Vulnerable Upstream Proxying (CVE-2026-42926)
by ikarolaborda · 2026-07-05
- Severity
- High
- CVE
- CVE-2026-42926
- Category
- web
- Affected product
- NGINX (HTTP/2 upstream proxying)
- Affected versions
- 1.29.4 through 1.30.0 (fixed in 1.30.1+ / 1.31.0+)
- Disclosed
- 2026-07-05
- Patch status
- patched
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-06 |
| Author / Researcher | ikarolaborda |
| CVE / Advisory | CVE-2026-42926 |
| Category | web |
| Severity | High |
| CVSS Score | N/A |
| Status | PoC |
| Tags | nginx, http2, frame-injection, reverse-proxy, request-smuggling, docker-lab |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | NGINX (HTTP/2 upstream proxying) |
| Versions Affected | 1.29.4 through 1.30.0 (fixed in 1.30.1+ / 1.31.0+) |
| Language / Platform | C (NGINX core), PHP/Python lab tooling |
| Authentication Required | No |
| Network Access Required | Yes (HTTP access to the vulnerable proxy location) |
Summary
CVE-2026-42926 is an HTTP/2 frame injection issue in NGINX that occurs when a specific vulnerable proxy configuration is used — proxying to an upstream over HTTP/2 (proxy_http_version 2) while forwarding a client-controlled request body via a variable (proxy_set_body $request_body) with a large client_max_body_size. Under this configuration, attacker-controlled bytes in the client request body can be interpreted as raw HTTP/2 frame data by the upstream connection, allowing frame-level injection into the proxied HTTP/2 stream. The lab in this repository builds NGINX from source (vulnerable and patched versions), runs a controlled raw HTTP/2 “upstream logger” to capture what the upstream actually receives, and provides a PHP validation harness that issues a crafted request and inspects the upstream logs for injected-frame evidence, comparing vulnerable vs. patched behavior.
Vulnerability Details
Root Cause
When NGINX is configured to proxy to an upstream using HTTP/2 (proxy_http_version 2) and to forward the client request body through a variable (proxy_set_body $request_body) rather than the standard request body passthrough, a large (up to client_max_body_size, e.g. 16MB+) attacker-controlled body can contain byte sequences that get placed onto the HTTP/2 connection to the upstream in a way that the upstream can parse as additional/injected HTTP/2 frames, rather than purely as opaque body payload. This breaks the expected isolation between the request body and the framing layer of the proxied connection.
Attack Vector
- Attacker identifies (or is provided, in this lab) a location configured with the vulnerable proxy pattern:
proxy_http_version 2,proxy_set_body $request_body, and a sufficiently largeclient_max_body_size. - Attacker crafts a large request body (up to ~16MB in this lab) containing byte sequences designed to be interpreted as HTTP/2 frame headers/payloads once placed on the upstream HTTP/2 connection by NGINX.
- The request is sent to the vulnerable
/exploitlocation; NGINX proxies it upstream over HTTP/2. - The lab’s controlled
upstream_frame_logger.py(acting as the upstream) parses the raw frames it receives and logs metadata, including any indication that injected/attacker-controlled frame-like data reached it outside the intended body framing. - The PHP driver (
cve_2026_42926_lab.php) checks preconditions (NGINX version, config pattern), sends the crafted request, and correlates the upstream log evidence with the run to return apositive(vulnerable),negative(not vulnerable), orinconclusiveverdict.
Impact
Frame-level injection into HTTP/2 connections between NGINX and its upstream, which can lead to request smuggling-like effects, response confusion, or unauthorized frame injection between the proxy and backend — undermining the isolation assumptions of the reverse-proxy trust boundary.
Environment / Lab Setup
Target: NGINX 1.29.4 (vulnerable) built from source, vs. 1.30.1+ (patched), with the vulnerable proxy_pass/proxy_http_version 2 config
Attacker: bash, python3, php (with cURL extension), or Docker + Docker Compose for the containerized lab
Proof of Concept
PoC Script
See
cve_2026_42926_lab.php,nginx_vulnerable.conf,docker/nginx_vulnerable.docker.conf,nginx_config_verify.sh,upstream_frame_logger.py,run_lab_comparison.sh,Dockerfile, anddocker-compose.ymlin this folder.
| |
Running the comparison harness starts the controlled upstream logger and both NGINX builds against the same vulnerable proxy configuration, sends the same crafted request to each, and writes vulnerable_result.txt / patched_result.txt plus per-run upstream log directories — demonstrating injection evidence present against the vulnerable build and absent against the patched build.
Detection & Indicators of Compromise
Signs of compromise:
- Upstream application/service logs showing HTTP/2 protocol errors, unexpected frame types, or stream state anomalies correlated with proxied requests
- NGINX access logs with unusually large request bodies to proxy locations using HTTP/2 upstream connections
- Backend behavior inconsistent with the request NGINX was expected to forward (evidence of frame confusion/injection)
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade NGINX to 1.30.1+ / 1.31.0+, which fix the HTTP/2 frame injection issue |
| Interim mitigation | Avoid the proxy_http_version 2 + proxy_set_body $request_body combination for untrusted client input; keep client_max_body_size as low as operationally feasible; monitor upstream services for anomalous HTTP/2 frame behavior |
References
Notes
Mirrored from https://github.com/ikarolaborda/CVE2026-42926 on 2026-07-05.
| |