GHSA-VXJ7-4XRP-5VR4
Vulnerability from github – Published: 2026-08-27 23:32 – Updated: 2026-08-27 23:32Impact
When a connection is upgraded with STARTTLS, aiosmtplib reads the server's 220 go-ahead reply and immediately performs the TLS handshake without discarding any data still sitting in the receive buffer. Bytes the protocol read off the plaintext socket before the handshake survive across the plaintext→TLS boundary (the asyncio transport is swapped in place, so the protocol object and its buffer are reused), and are then parsed as though they had arrived inside the TLS session.
Who is affected: Any caller that uses STARTTLS by passing start_tls=True or start_tls=None when the server advertises STARTTLS, and whose traffic can be intercepted by an active network attacker on the plaintext leg of the connection.
A man in the middle can send, in a single segment immediately after the client's STARTTLS command, the 220 reply followed by attacker-chosen response lines (e.g. 220 Go ahead\r\n250-mx.evil\r\n250 AUTH LOGIN\r\n). aiosmtplib consumes only the 220, leaves the injected lines buffered, completes the handshake, and then parses the attacker's pre-staged plaintext as the first post-TLS server response. This also desynchronizes every subsequent command/response pair inside the "encrypted" session.
Not affected: Connections using implicit/direct TLS (use_tls=True) have no plaintext phase and are not vulnerable. The attack requires an active man in the middle via network compromise; a passive eavesdropper cannot exploit it.
Patches
A fix is available in aiosmtplib 5.1.2. All earlier versions that support STARTTLS are affected; upgrade to 5.1.2 or later.
The fix treats any data buffered after the 220 STARTTLS reply and before the handshake as a protocol violation, per RFC 3207 §4.2 ("the client MUST discard any knowledge obtained from the server … which was not obtained from the TLS negotiation itself").
Workarounds
If you cannot upgrade immediately:
- Use implicit TLS instead of STARTTLS. Connect with
use_tls=True. This removes the plaintext phase entirely. - If STARTTLS is unavoidable, restrict connections to servers reached over a trusted network path.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.1.1"
},
"package": {
"ecosystem": "PyPI",
"name": "aiosmtplib"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "5.1.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-55558"
],
"database_specific": {
"cwe_ids": [
"CWE-74"
],
"github_reviewed": true,
"github_reviewed_at": "2026-08-27T23:32:22Z",
"nvd_published_at": "2026-08-20T15:17:31Z",
"severity": "MODERATE"
},
"details": "## Impact\n\nWhen a connection is upgraded with STARTTLS, aiosmtplib reads the server\u0027s 220 go-ahead reply and immediately performs the TLS handshake without discarding any data still sitting in the receive buffer. Bytes the protocol read off the plaintext socket before the handshake survive across the plaintext\u2192TLS boundary (the asyncio transport is swapped in place, so the protocol object and its buffer are reused), and are then parsed as though they had arrived inside the TLS session.\n\nWho is affected: Any caller that uses STARTTLS by passing `start_tls=True` or `start_tls=None` when the server advertises STARTTLS, and whose traffic can be intercepted by an active network attacker on the plaintext leg of the connection.\n\nA man in the middle can send, in a single segment immediately after the client\u0027s STARTTLS command, the 220 reply followed by attacker-chosen response lines (e.g. 220 Go ahead\\r\\n250-mx.evil\\r\\n250 AUTH LOGIN\\r\\n). aiosmtplib\n consumes only the 220, leaves the injected lines buffered, completes the handshake, and then parses the attacker\u0027s pre-staged plaintext as the first post-TLS server response. This also desynchronizes every\n subsequent command/response pair inside the \"encrypted\" session.\n\nNot affected: Connections using implicit/direct TLS (`use_tls=True`) have no plaintext phase and are not vulnerable. The attack requires an active man in the middle via network compromise; a passive eavesdropper cannot exploit it.\n\n\n# Patches\n\n A fix is available in aiosmtplib 5.1.2. All earlier versions that support STARTTLS are affected; upgrade to 5.1.2 or\n later.\n\n The fix treats any data buffered after the 220 STARTTLS reply and before the handshake as a protocol violation, per RFC 3207 \u00a74.2 (\"the client MUST discard any knowledge obtained from the server \u2026 which was not\n obtained from the TLS negotiation itself\").\n\n# Workarounds\n\n If you cannot upgrade immediately:\n\n - Use implicit TLS instead of STARTTLS. Connect with `use_tls=True`. This removes the plaintext phase entirely.\n - If STARTTLS is unavoidable, restrict connections to servers reached over a trusted network path.",
"id": "GHSA-vxj7-4xrp-5vr4",
"modified": "2026-08-27T23:32:22Z",
"published": "2026-08-27T23:32:22Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/cole/aiosmtplib/security/advisories/GHSA-vxj7-4xrp-5vr4"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-55558"
},
{
"type": "WEB",
"url": "https://github.com/cole/aiosmtplib/commit/9fab7ba1361dbf7622ede1315a24be805cff09c9"
},
{
"type": "PACKAGE",
"url": "https://github.com/cole/aiosmtplib"
},
{
"type": "WEB",
"url": "https://github.com/cole/aiosmtplib/releases/tag/v5.1.2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "aiosmtplib: STARTTLS response injection"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.