Stalwart does not dynamically limit the memory usage of incoming SMTP messages. As a result, multiple concurrent slow connections can exhaust the server’s available RAM, crashing the mail server via the OS OOM killer.
This behavior can be weaponized to perform a Denial of Service attack against Stalwart instances.
I previously reported this to Stalwart Security, who classified the behavior as a configuration issue rather than a software vulnerability. Because the default configuration leaves instances susceptible to this resource exhaustion, I am sharing the disclosure here for community awareness so other administrators can adjust their setups accordingly.
The email server should spool payloads to disk or limit inbound connection memory usage to prevent exceeding maximum available RAM.
Actual Behavior
The mail server crashes.
Reproduction Steps
Full reproductions steps are available in the Public Full Disclosure.
Stalwart Version
v0.16.x
Installation Method
Docker
Database Backend
SQLite
Blob Storage
SQLite
Search Engine
Internal
Directory Backend
Internal
Additional Context
This was previously reported to [email protected] and classified by the team as a configuration issue that should be handled by adjusting max_message_size and max_connections.
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
I have enough to give a grounded, actionable reply pointing to the relevant mitigations documented for Stalwart.
Thanks for the writeup and for sharing the PoC responsibly. This lines up with how Stalwart’s security team classified it: the server exposes several knobs specifically meant to bound per-connection and server-wide resource consumption, and the defaults are intentionally permissive rather than hardened, so operators are expected to tune them for their exposure.
Relevant settings for mitigating slow-sender/OOM-style abuse:
SystemSettings.maxConnections – server-wide cap on concurrent connections (default 8192), and each NetworkListener can set its own maxConnections to cap a specific SMTP port independently. (docs/server/listener.md)
MtaInboundSession (Settings → MTA → Inbound → Session) exposes maxDuration (max session length, default 10m), timeout (max time to wait for a client command before disconnecting, default 5m), and transferLimit (max bytes transferred per session, default ~250MB). Lowering timeout sharply reduces how long a “slow-sender” can hold a connection open. (docs/ref/object/mta-inbound-session)
MtaStageData.maxMessageSize – caps a single message’s size (default 100MB). (docs/mta/inbound/data.md)
MtaInboundThrottle objects let you rate-limit or cap concurrency per remote IP/subnet for inbound SMTP sessions, which is the direct countermeasure for many slow connections opened from the same source. (docs/mta/outbound/rate-limit.md, “Inbound limits”)
loiterBanRate/loiterBanPeriod under Security auto-ban connections that repeatedly connect without sending meaningful traffic. (docs/server/auto-ban.md)
Tightening timeout/maxDuration on MtaInboundSession, adding a per-IP MtaInboundThrottle limiting concurrent connections, and lowering maxConnections on the SMTP listener together close most of the exposure described in your PoC.