Nextcloud · Report #3913007
SMTP header injection via C-escape `\r` in the recipient display name
How it was found
Vulnerability Summary
Roundcube strips CR/LF from address input in rcmail_sendmail::email_input_format()
(program/include/rcmail_sendmail.php:760) and then, twenty-five lines later,
calls stripcslashes() on the recipient's display name at
program/include/rcmail_sendmail.php:790. An authenticated user who submits the
two-character sequence \r inside a quoted display name passes the strip
regexp untouched — there is no control character in the input yet — and
stripcslashes() converts it into a real 0x0D after the sanitizer has run.
Nothing downstream removes it. format_email_recipient()
(program/lib/Roundcube/bootstrap.php:329-333) escapes only ".
Mail_mimePart::encodeHeader() folds only /\r?\n[\s\t]*/, so a lone CR is
never matched, and its non-ASCII test preg_match('#([^\s\x21-\x7E]){1}#')
classifies CR as whitespace, so no RFC2047 encoding is applied either. Finally
Net_SMTP::quotedata() (vendor/pear/net_smtp/Net/SMTP.php:1489) normalises
every lone CR into a full CRLF, turning the injected text into real header
lines on the wire.
Steps to Reproduce
- Log in to Roundcube as any user.
- Send
POST /?_task=mail&_action=sendwith a valid_tokenand the body parameter — note\ris backslash followed by the letterr, not a control character:_to="x\rBcc: [email protected]\rSender: [email protected]\rX-Pad: p" <[email protected]> program/include/rcmail_sendmail.php:112reads the raw value; the CRLF strip atprogram/include/rcmail_sendmail.php:760matches nothing.program/include/rcmail_sendmail.php:790—$name = stripcslashes($name);materialises three real 0x0D bytes inside the display name.program/include/rcmail_sendmail.php:202assigns the result to$headers['To'];:384hands it toMail_mime;program/lib/Roundcube/rcube.php:1802serialises the headers, which leaves the lone CR intact.program/lib/Roundcube/rcube_smtp.php:321callsNet_SMTP::data(), whosequotedata()promotes each CR to CRLF.- Run the executable proof, which exercises the real repository and vendor
code end to end:
Result: PASS. On-the-wire output:php roundcubemail-master_VULNHUNT_RESULTS_2026-08-03-095945/exploit_tests/test_vuln_001_smtp_header_injection_recipient.phpTo: "x\r\n Bcc: [email protected]\r\n Sender: [email protected]\r\n X-Pad: p"\r\n <[email protected]>\r\nBcc: [email protected]andSender: [email protected]are asserted to be standalone CRLF-delimited header lines.
Impact
Any authenticated user gains arbitrary RFC-822 header emission on messages
relayed with the server's own SMTP submission credentials — a capability the
compose form deliberately does not expose (rcmail_sendmail.php:198-269 builds
the header array from a fixed key set). Concretely they can:
- forge
From:/Sender:/Reply-To:, bypassing the server-side identity lookup atrcmail_sendmail.php:147-175and theidentities_levelpinning enforced atprogram/actions/settings/identity_save.php:64-79— sender spoofing from a domain whose SPF/DKIM the mail server legitimately satisfies; - add covert
Bcc:recipients; - forge trust-signal headers (
Received:,Authentication-Results:,X-Spam-Status:) that downstream MTAs and spam filters consume; - inject an empty line to terminate the header block early and control the raw message body the MTA parses.