Lost in Translation: How CVE-2025-7962 Turns Unicode into SMTP Command Injection
Jan 23, 2026·7 min read·13 visits
Executive Summary (TL;DR)
Jakarta Mail (formerly JavaMail) contains a classic CRLF injection vulnerability with a twist: it's triggered by Unicode characters. Because the library naively truncates 16-bit characters to 8-bit bytes during SMTP transmission, characters like '瘍' (U+760D) become a literal Carriage Return (0x0D). This allows attackers to break out of email headers and inject arbitrary SMTP commands, leading to spam relaying, phishing from trusted domains, or session poisoning.
A critical flaw in Jakarta Mail (Eclipse Angus Mail) allows attackers to perform SMTP Command Injection by leveraging improper Unicode-to-ASCII conversion. By using specific multibyte characters, an attacker can smuggle protocol delimiters past input filters.
The Hook: When 'Safe' Characters Aren't Safe
We tend to think of input validation as a binary gatekeeper: either the input contains dangerous characters like < > ' ", or it doesn't. Developers sanitize inputs by stripping out known bad actors, specifically looking for ASCII control characters like \r (Carriage Return) and \n (Line Feed) to prevent protocol injection. But what happens when the library you rely on decides to perform some aggressive reconstructive surgery on your data after you've validated it?
Enter CVE-2025-7962, a vulnerability in Jakarta Mail (specifically the Eclipse Angus Mail implementation) that turns the seemingly harmless act of sending an email into a protocol-level jailbreak. This isn't your standard "forgot to escape the input" bug. It is a fundamental disagreement between how Java represents text (UTF-16) and how SMTP demands text (7-bit ASCII).
The vulnerability lies in the obscure mechanics of character casting. While you might be blocking 0x0D and 0x0A at your application gateway, Jakarta Mail was unknowingly manufacturing them deep inside the transport layer. It turns out that if you squeeze certain Chinese characters hard enough, they bleed protocol delimiters. This allows an attacker to inject entirely new SMTP commands into an active session, turning a simple "Contact Us" form into an open relay for spam or a vehicle for highly convincing phishing campaigns.
The Flaw: The Byte-Chopping Butcher
To understand this flaw, you have to look at the bits. SMTP is an ancient, chatty protocol. It relies on \r\n (CRLF) to mark the end of a command. If I send RCPT TO:<victim@company.com>, the server waits for that CRLF before processing the instruction. If an attacker can insert a CRLF in the middle of that string, they can terminate the command early and start typing their own instructions. This is why we have filters.
However, Jakarta Mail made a fatal assumption in how it converted Java's 16-bit Unicode char types into the byte stream sent over the wire. Instead of properly encoding or rejecting multibyte characters that don't fit into the SMTP standard, the library essentially performed a naive cast or low-order byte extraction. This is the computational equivalent of trying to fit a square peg in a round hole by just sawing off the corners.
Consider the Unicode character '瘍' (U+760D). In binary, that's 01110110 00001101. Notice the last 8 bits: 00001101, which is 0x0D—the Carriage Return. When the vulnerable library processes this character for transmission, it ignores the high byte (0x76) and transmits only the low byte (0x0D). Similarly, the character '瘊' (U+760A) has a low byte of 0x0A—the Line Feed. To the application logic, 瘍 is just a valid UTF-8 character. To the SMTP server receiving the raw bytes, it is the "End of Command" signal. The library inadvertently acts as a smuggler, hiding protocol delimiters inside valid Unicode glyphs.
The Smoking Gun: Anatomy of the Patch
The fix for this vulnerability, delivered in commit 269099b652a0a5c2fa140f1296a18f0fbbea0d44, reveals just how dangerous the raw output stream was. The developers didn't just fix the encoding; they added a final safety net—a "chokepoint"—right before the data hits the wire.
In SMTPTransport.java, the method sendCommand was modified to include a mandatory validation step. This is an admission that upstream sanitation cannot be fully trusted. Here is the critical diff:
// providers/smtp/src/main/java/org/eclipse/angus/mail/smtp/SMTPTransport.java
private void sendCommand(byte[] cmdBytes) throws MessagingException {
try {
// THE FIX: Validate the raw bytes before writing to the socket
validateCommand(cmdBytes);
serverOutput.write(cmdBytes);
serverOutput.write(CRLF);
serverOutput.flush();
} catch ...
}
private void validateCommand(byte[] cmdBytes) throws MessagingException {
final byte CR = '\r';
final byte LF = '\n';
for (byte b : cmdBytes) {
// If any byte in the payload mimics a delimiter, ABORT.
if (b == LF || b == CR) {
throw new IllegalArgumentException(
"Command contains illegal character: " +
String.format("0x%02x", b)
);
}
}
}This code iterates through the final byte array intended for the server. It doesn't care how the bytes got there—whether via UTF-8, ASCII, or a casting error. If it sees a 0x0D or 0x0A inside the command body (which should never happen in a strictly compliant SMTP command argument), it throws an exception. This effectively kills the "low byte" attack vector because the resulting 0x0D from the character 瘍 will be caught by this filter immediately before transmission.
The Exploit: Breaking the Protocol
Let's construct a realistic attack scenario. Imagine a web application that allows users to send feedback. The backend code takes the user's email address and sends a confirmation email. The code looks something like transport.sendMessage(msg, internetAddresses). The developer feels safe because they validate that the email doesn't contain ASCII control characters.
The attacker submits the following string as their email address:
admin瘍瘊DATA瘍瘊Subject: Pwned瘍瘊瘍瘊Bad things happen here.@evil.com
When the vulnerable Jakarta Mail library processes this, it strips the high bytes. The SMTP conversation, which should have been a single RCPT TO command, transforms into this nightmare:
The server interprets the injected DATA command immediately. The original email content intended by the application becomes garbage appended to the attacker's message, or is rejected, but by then the damage is done. The attacker has successfully sent an email masquerading as the application.
The Impact: Digital Ventriloquism
The impact of this vulnerability ranges from annoying to catastrophic, depending on the architecture of the victim system. The primary risk is Email Spoofing and Spam Relaying. Since the injection happens after authentication (if the app is authenticated to the SMTP server), the injected commands run with the full privileges of the trusted application. An attacker can send thousands of spam emails that appear to originate from support@yourbank.com, bypassing SPF and DKIM checks because the email is technically coming from the legitimate server.
Furthermore, this can lead to Internal Scanning. If the SMTP server is internal and restricts commands based on IP, the vulnerable web app (running on a trusted internal IP) can be used as a proxy to send commands that would otherwise be blocked.
There is also a risk of Session Poisoning. By injecting commands, an attacker can desynchronize the state of the SMTP connection. Subsequent emails sent by the application over the same connection (if connection pooling is used) might be mishandled, attached to the wrong recipients, or dropped entirely, leading to a subtle Denial of Service or data leakage.
The Fix: Plugging the Leak
The remediation is straightforward but urgent. You must stop using the library that thinks sawing bytes in half is a valid conversion strategy.
1. Update Dependencies:
Upgrade org.eclipse.angus:angus-mail (or the Jakarta Mail API implementation you are using) to version 2.0.4 or later. If you are using Jenkins, update the "Jakarta Mail API Plugin" to 2.1.3-3.
2. Defensive Coding (The "Belt and Suspenders" Approach):
Even with the patch, you should never trust a library to handle input sanitation for you. Implement strict allow-listing for email addresses. A valid email address generally should not require characters outside the printable ASCII range. If your application supports Internationalized Domain Names (IDN), convert them to Punycode (e.g., xn--...) before passing them to the mail transport layer. This ensures that only safe, 7-bit ASCII characters ever reach the dangerous SMTPTransport class.
3. Monitoring:
Check your SMTP logs for fragmented commands. A RCPT TO followed immediately by a DATA command from the same client IP within milliseconds, or 500 Syntax Error responses triggered by weird garbage data, are strong indicators that someone is probing your mail infrastructure.
Official Patches
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:NAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
Angus Mail Eclipse Foundation | <= 2.0.3 | 2.0.4 |
Jakarta Mail API Plugin Jenkins Project | <= 2.1.3-2 | 2.1.3-3 |
WebSphere Application Server IBM | 8.5.x, 9.0.x | 8.5.5.28, 9.0.5.25 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-147 (Improper Neutralization of Input Terminators) |
| CVSS v3.1 | 7.5 (High) |
| Attack Vector | Network (SMTP Injection) |
| EPSS Score | 0.0001 (0.83%) |
| Exploit Status | PoC Available |
| Impact | Integrity (High) |
| Vector String | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N |
MITRE ATT&CK Mapping
The product does not properly neutralize input terminators (like CRLF), allowing attackers to terminate the current command and inject new commands.
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.