CVE-2026-46428
lettre has TLS hostname verification disabled when using Boring TLS backend
lettre is a a mailer library for Rust. Starting in version 0.10.1 and prior to version 0.11.22, an inverted-boolean bug in lettre's boring-tls integration silently disables TLS hostname verification for callers using the default (strict) configuration. An on-path attacker presenting any chain-valid certificate for any domain can intercept SMTP submission, including PLAIN/LOGIN credentials and message contents, against any lettre user built with the boring-tls feature. Other TLS backends (native-tls, rustls) are unaffected. Version 0.11.22 patches the issue.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
9.1
lettre has TLS hostname verification disabled when using Boring TLS backend
lettre is a a mailer library for Rust. Starting in version 0.10.1 and prior to version 0.11.22, an inverted-boolean bug in lettre's boring-tls integration silently disables TLS hostname verification for callers using the default (strict) configuration. An on-path attacker presenting any chain-valid certificate for any domain can intercept SMTP submission, including PLAIN/LOGIN credentials and message contents, against any lettre user built with the boring-tls feature. Other TLS backends (native-tls, rustls) are unaffected. Version 0.11.22 patches the issue.
- Record
CVE-2026-46428- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N - Weakness
- CWE-295
- Updated
- 2026-11-02
EUVDEUVD-2026-45982
9.1
lettre is a a mailer library for Rust. Starting in version 0.10.1 and prior to version 0.11.22, an inverted-boolean bug in lettre's boring-tls integration silently disables TLS hostname verification for callers using the default (strict) configuration. An on-path attacker presenting any chain-valid certificate for any domain can intercept SMTP submission, including PLAIN/LOGIN credentials and message contents, against any lettre user built with the boring-tls feature. Other TLS backends (native-tls, rustls) are unaffected. Version 0.11.22 patches the issue.
- Record
EUVD-2026-45982- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-4pj9-g833-qx53
9.1
lettre has TLS hostname verification disabled when using Boring TLS backend
Summary
An inverted-boolean bug in lettre's boring-tls integration silently
disables TLS hostname verification for callers using the default (strict)
configuration. An on-path attacker presenting any chain-valid certificate
for any domain can intercept SMTP submission, including PLAIN/LOGIN
credentials and message contents, against any lettre user built with the
boring-tls feature. Other TLS backends (native-tls, rustls) are
unaffected.
Details
boring's SslConnectorBuilder::set_verify_hostname(bool) /
verify_hostname(bool) API takes a verify flag — true means enforce
hostname verification, false means skip it. (Boring docs:
https://docs.rs/boring/latest/boring/ssl/struct.ConnectConfiguration.html#method.set_verify_hostname)
lettre's TlsParametersBuilder exposes the opposite-named flag
accept_invalid_hostnames: bool — true means accept invalid (skip
verification), false means verify. lettre passes this flag directly to
boring at both TLS-upgrade sites, inverting the semantics:
src/transport/smtp/client/net.rs:202 (sync)
.verify_hostname(*accept_invalid_hostnames)
src/transport/smtp/client/async_net.rs:377 (async)
config.set_verify_hostname(accept_invalid_hostnames);
Concrete behaviour under boring-tls:
- accept_invalid_hostnames = false (the strict default) → set_verify_hostname(false) → hostname verification SKIPPED (wrong; the caller asked for strict verification)
- accept_invalid_hostnames = true (explicit opt-in to "dangerous")
→ set_verify_hostname(true) → hostname verification ENFORCED
(wrong; the caller opted into accepting any name)
Boring's own warning on
set_verify_hostname: "If hostname verification is not used, any valid certificate for any site will be trusted for use from any other. This introduces a significant vulnerability to man-in-the-middle attacks."native-tls(src/transport/smtp/client/tls.rs:355) usesdanger_accept_invalid_hostnames(self.accept_invalid_hostnames), whose flag name and semantics match lettre's — unaffected.rustlsuses a separate verifier path — unaffected. The bug was introduced in PR #797 ("Add support for boring TLS"), commit 985fa7e, first released in v0.10.1, and persists unchanged through v0.11.21 (latest). Zero existing tests coveraccept_invalid_hostnamesend-to-end with any backend, which is why the inversion has gone undetected. Fix: negate the flag at both call sites. Two-line patch:- .verify_hostname(*accept_invalid_hostnames)
- .verify_hostname(!*accept_invalid_hostnames)
- config.set_verify_hostname(accept_invalid_hostnames);
- config.set_verify_hostname(!accept_invalid_hostnames); I have the patch ready locally and can push to a private fork if a collaborative fix branch is preferred.
PoC
Setup (any lettre version >= v0.10.1, built with the boring-tls
feature, default-strict configuration):
- Generate a TLS cert for any hostname the attacker controls, e.g.
attacker.example, signed by any CA in the client's trust store (e.g. a Let's Encrypt cert is sufficient). - Stand up an attacker SMTP server on the network path between the
lettre client and the intended MX. Have it present the
attacker.examplecert on STARTTLS or implicit TLS. - Use lettre with default-strict TLS to send to the real MX hostname,
e.g.
mail.example.com: use lettre::transport::smtp::client::{Tls, TlsParameters}; use lettre::{AsyncSmtpTransport, Tokio1Executor, Message}; let tls = TlsParameters::builder("mail.example.com".to_owned()) .build_boring() .unwrap(); let mailer = AsyncSmtpTransport::<Tokio1Executor>::relay( "mail.example.com", )? .tls(Tls::Required(tls)) .build(); mailer.send(message).await?; // succeeds against attacker Expected with hostname verification: handshake fails because the presented leaf cert's…
- Record
GHSA-4pj9-g833-qx53- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N - Weakness
- CWE-295
- Updated
- 2026-11-02
NVD
9.1
lettre is a a mailer library for Rust. Starting in version 0.10.1 and prior to version 0.11.22, an inverted-boolean bug in lettre's boring-tls integration silently disables TLS hostname verification for callers using the default (strict) configuration. An on-path attacker presenting any chain-valid certificate for any domain can intercept SMTP submission, including PLAIN/LOGIN credentials and message contents, against any lettre user built with the boring-tls feature. Other TLS backends (native-tls, rustls) are unaffected. Version 0.11.22 patches the issue.
- Record
CVE-2026-46428- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-295
- Updated
- 2026-11-02
OSV
9.1
lettre has TLS hostname verification disabled when using Boring TLS backend
lettre is a a mailer library for Rust. Starting in version 0.10.1 and prior to version 0.11.22, an inverted-boolean bug in lettre's boring-tls integration silently disables TLS hostname verification for callers using the default (strict) configuration. An on-path attacker presenting any chain-valid certificate for any domain can intercept SMTP submission, including PLAIN/LOGIN credentials and message contents, against any lettre user built with the boring-tls feature. Other TLS backends (native-tls, rustls) are unaffected. Version 0.11.22 patches the issue.
- Record
CVE-2026-46428- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N - Weakness
- CWE-295
- Updated
- 2026-11-02
OSVGHSA-4pj9-g833-qx53
9.1
lettre has TLS hostname verification disabled when using Boring TLS backend
Summary
An inverted-boolean bug in lettre's boring-tls integration silently
disables TLS hostname verification for callers using the default (strict)
configuration. An on-path attacker presenting any chain-valid certificate
for any domain can intercept SMTP submission, including PLAIN/LOGIN
credentials and message contents, against any lettre user built with the
boring-tls feature. Other TLS backends (native-tls, rustls) are
unaffected.
Details
boring's SslConnectorBuilder::set_verify_hostname(bool) /
verify_hostname(bool) API takes a verify flag — true means enforce
hostname verification, false means skip it. (Boring docs:
https://docs.rs/boring/latest/boring/ssl/struct.ConnectConfiguration.html#method.set_verify_hostname)
lettre's TlsParametersBuilder exposes the opposite-named flag
accept_invalid_hostnames: bool — true means accept invalid (skip
verification), false means verify. lettre passes this flag directly to
boring at both TLS-upgrade sites, inverting the semantics:
src/transport/smtp/client/net.rs:202 (sync)
.verify_hostname(*accept_invalid_hostnames)
src/transport/smtp/client/async_net.rs:377 (async)
config.set_verify_hostname(accept_invalid_hostnames);
Concrete behaviour under boring-tls:
- accept_invalid_hostnames = false (the strict default) → set_verify_hostname(false) → hostname verification SKIPPED (wrong; the caller asked for strict verification)
- accept_invalid_hostnames = true (explicit opt-in to "dangerous")
→ set_verify_hostname(true) → hostname verification ENFORCED
(wrong; the caller opted into accepting any name)
Boring's own warning on
set_verify_hostname: "If hostname verification is not used, any valid certificate for any site will be trusted for use from any other. This introduces a significant vulnerability to man-in-the-middle attacks."native-tls(src/transport/smtp/client/tls.rs:355) usesdanger_accept_invalid_hostnames(self.accept_invalid_hostnames), whose flag name and semantics match lettre's — unaffected.rustlsuses a separate verifier path — unaffected. The bug was introduced in PR #797 ("Add support for boring TLS"), commit 985fa7e, first released in v0.10.1, and persists unchanged through v0.11.21 (latest). Zero existing tests coveraccept_invalid_hostnamesend-to-end with any backend, which is why the inversion has gone undetected. Fix: negate the flag at both call sites. Two-line patch:- .verify_hostname(*accept_invalid_hostnames)
- .verify_hostname(!*accept_invalid_hostnames)
- config.set_verify_hostname(accept_invalid_hostnames);
- config.set_verify_hostname(!accept_invalid_hostnames); I have the patch ready locally and can push to a private fork if a collaborative fix branch is preferred.
PoC
Setup (any lettre version >= v0.10.1, built with the boring-tls
feature, default-strict configuration):
- Generate a TLS cert for any hostname the attacker controls, e.g.
attacker.example, signed by any CA in the client's trust store (e.g. a Let's Encrypt cert is sufficient). - Stand up an attacker SMTP server on the network path between the
lettre client and the intended MX. Have it present the
attacker.examplecert on STARTTLS or implicit TLS. - Use lettre with default-strict TLS to send to the real MX hostname,
e.g.
mail.example.com: use lettre::transport::smtp::client::{Tls, TlsParameters}; use lettre::{AsyncSmtpTransport, Tokio1Executor, Message}; let tls = TlsParameters::builder("mail.example.com".to_owned()) .build_boring() .unwrap(); let mailer = AsyncSmtpTransport::<Tokio1Executor>::relay( "mail.example.com", )? .tls(Tls::Required(tls)) .build(); mailer.send(message).await?; // succeeds against attacker Expected with hostname verification: handshake fails because the presented leaf cert's…
- Record
GHSA-4pj9-g833-qx53- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N - Weakness
- CWE-295
- Updated
- 2026-11-02
OSVRUSTSEC-2026-0141
9.1
TLS hostname verification disabled when using Boring TLS backend
An inverted-boolean bug in lettre's boring-tls integration silently
disables TLS hostname verification for callers using the default (strict)
configuration. An on-path attacker presenting any chain-valid certificate
for any domain can intercept SMTP submission, including PLAIN/LOGIN
credentials and message contents, against any lettre user built with the
boring-tls feature. Other TLS backends (native-tls, rustls) are
unaffected.
The bug was introduced in v0.10.1 and persists through v0.11.21 (latest).
- Record
RUSTSEC-2026-0141- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
lettrecrates.io |
0.10.1 up to 0.11.22 | 0.11.22 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-46428 is a critical vulnerability (CVSS 9.1) in Lettre, published May 14, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.32%, the 25th percentile. Fixed in lettre 0.11.22.
References
github.com/lettre/lettre/security/advisories/GHSA-4pj9-g833-qx53
github.com/lettre/lettre/commit/f5efffc88360dbdbfcef80f465e42d5bce68ca35
github.com/lettre/lettre/releases/tag/v0.11.22
rustsec.org/advisories/RUSTSEC-2026-0141.html
nvd.nist.gov/vuln/detail/CVE-2026-46428
github.com/advisories/GHSA-4pj9-g833-qx53
github.com/CVEProject/cvelistV5/tree/main/cves/2026/46xxx/CVE-2026-46428.json
github.com/lettre/lettre
crates.io/crates/lettre
Left out here: the rest of 2 source descriptions. The JSON record has them.