
Dead.Letter CVE-2026-45185 EXIM Vulnerability Detection Script
A shell script for detecting whether a Linux system is vulnerable to CVE-2026-45185, a use-after-free in the Exim mail transfer agent that can lead to remote code execution.
Designed for use in CI/CD pipelines, configuration management tooling, and ad-hoc system audits. Produces both human-readable and machine-readable (JSON) output.
CVE-2026-45185 (alias: Dead.Letter) is a use-after-free bug in Exim's BDAT (binary data) message body parsing, triggered when TLS is handled by GnuTLS.
During TLS shutdown, Exim frees its TLS transfer buffer — but a nested BDAT
receive wrapper can still process incoming bytes and call ungetc(), writing
a single \n byte into the freed region. That one-byte write corrupts heap
allocator metadata, from which an attacker can gain further memory primitives
and achieve remote code execution.
| Property | Detail |
|---|---|
| CVE | CVE-2026-45185 |
| Alias | Dead.Letter |
| Type | Use-After-Free (CWE-416) |
| Component | Exim BDAT/CHUNKING handler (GnuTLS builds only) |
| Attack vector | Network — unauthenticated, requires only a TLS connection and CHUNKING extension |
| Affected versions | Exim 4.97 – 4.99.2, GnuTLS builds only |
| Fixed in | Exim 4.99.3 |
| Discovered by | Federico Kirschbaum, XBOW Security Lab (reported 1 May 2026) |
OpenSSL builds are not affected. The vulnerability is specific to Exim compiled with
USE_GNUTLS=yes. If your Exim links against OpenSSL, you are not vulnerable regardless of version.
The script works through a decision tree, stopping and marking the system not vulnerable as soon as a definitive safe condition is confirmed:
Check 1 — Exim presence
Searches $PATH and common install locations (/usr/sbin/exim,
/usr/sbin/exim4, /usr/local/sbin/exim). If Exim is not found, the system
is not vulnerable and the script exits immediately.
Check 2 — Exim version
Parses exim -bV output and compares against the affected range
(4.97 – 4.99.2). Versions ≥ 4.99.3 are treated as patched. Versions outside
the known range are marked not vulnerable (with a note if they are
unrecognised).
Check 3 — TLS library (the critical gate) Uses three detection methods in sequence:
exim -bV build information (most reliable — Exim reports its own compile-time features, e.g. Support for: GnuTLS)ldd shared library linkagestrings binary scan (fallback)If OpenSSL is detected → verdict flips to not vulnerable regardless of version. If GnuTLS is detected → the attack surface is confirmed present. If neither can be determined → result is inconclusive.
Check 4 — CHUNKING/BDAT config (workaround check)
Only runs if the system is still marked vulnerable at this point. Checks
whether chunking_advertise_hosts has been explicitly set to an empty value
in the Exim config, which disables BDAT advertisement and blocks the attack
vector. Handles both single-file configs and Debian's split-config layout
(/etc/exim4/conf.d/ fragments).
Note: if
chunking_advertise_hostsis absent from the config (the default), Exim advertises CHUNKING to all hosts (*). The option must be explicitly set to an empty value to disable it.
Check 5 — Informational system mitigations Does not change the verdict, but reports on factors that affect exploitability:
/proc/sys/kernel/randomize_va_space) — should be 2checksec output for the Exim binary (PIE, RELRO, stack canaries) if checksec is installedMemoryDenyWriteExecute, NoNewPrivileges, SystemCallFilter/proc filesystem (for ASLR check)grep, awk, ldd, headchecksec (optional — for binary hardening analysis)systemctl (optional — for systemd unit inspection)Debian-exim group on Debian/Ubuntu)No external dependencies are required for the core vulnerability checks.
chmod +x check_cve_2026_45185.sh
./check_cve_2026_45185.sh
| Flag | Description |
|---|---|
| Code | Meaning |
|---|---|
0 | Not vulnerable (or a definitive safe condition was found) |
1 | Vulnerable |
CVE-2026-45185 (Dead.Letter) — Exim Vulnerability Assessment
============================================================
[CHECK] Checking for Exim installation...
[WARN] Exim binary found: /usr/sbin/exim4
[CHECK] Checking Exim version...
Detected version: 4.99.1
[FAIL] Exim 4.99.1 is in the vulnerable range (4.97 – 4.99.2).
[CHECK] Checking TLS library linkage (GnuTLS vs OpenSSL)...
[FAIL] Exim is linked against GnuTLS — this build IS affected.
[CHECK] Checking CHUNKING (BDAT) advertisement config...
Config file: /etc/exim4/exim4.conf
[WARN] chunking_advertise_hosts is not disabled — BDAT is active (default advertises to all hosts).
Tip: add 'chunking_advertise_hosts =' (empty value) to your main config to disable BDAT as a workaround.
[CHECK] Checking system-level exploit mitigations (informational)...
[PASS] ASLR: full randomisation (randomize_va_space=2)
glibc version: 2.35 (2.32+ has stronger heap metadata checks)
[WARN] systemd: MemoryDenyWriteExecute not set — recommend adding to unit
[WARN] systemd: NoNewPrivileges not set
------------------------------------------------------------
VERDICT
------------------------------------------------------------
VULNERABLE — CVE-2026-45185
Reason: Exim version 4.99.1 is in vulnerable range 4.97–4.99.2
Recommended actions:
1. Upgrade Exim to 4.99.3 or later (primary fix)
2. As a workaround, set 'chunking_advertise_hosts =' (empty) in exim config
3. Add MemoryDenyWriteExecute=yes and NoNewPrivileges=yes to the systemd unit
4. Ensure ASLR is set to 2: echo 2 > /proc/sys/kernel/randomize_va_space
------------------------------------------------------------
--json){
"cve": "CVE-2026-45185",
"alias": "Dead.Letter",
"host": "mailserver-01",
"timestamp": "2026-05-12T17:00:00Z",
"verdict": "vulnerable",
"reason": "Exim version 4.99.1 is in vulnerable range 4.97–4.99.2",
"exit_code": 1,
"findings": {
"exim_binary": "/usr/sbin/exim4",
"exim_version": "4.99.1",
"exim_version_vulnerable": "true",
"tls_library": "gnutls",
"tls_library_detected": "gnutls",
"exim_config": "/etc/exim4/exim4.conf",
"chunking_advertised": "true",
"aslr_level": "2",
"glibc_version": "2.35"
},
"mitigations": [
"aslr=full"
]
}
- name: Check for CVE-2026-45185
run: |
chmod +x check_cve_2026_45185.sh
./check_cve_2026_45185.sh --json | tee vuln-report.json
exit $(jq '.exit_code' vuln-report.json)
- name: Upload vulnerability report
if: always()
uses: actions/upload-artifact@v4
with:
name: cve-2026-45185-report
path: vuln-report.json
check-exim-vuln:
stage: security
script:
- chmod +x check_cve_2026_45185.sh
- ./check_cve_2026_45185.sh --json > vuln-report.json
artifacts:
when: always
paths:
- vuln-report.json
allow_failure: false
- name: Run CVE-2026-45185 check
script: check_cve_2026_45185.sh --json
register: vuln_check
failed_when: vuln_check.rc == 1
changed_when: false
- name: Show vulnerability report
debug:
msg: "{{ vuln_check.stdout | from_json }}"
# Get just the verdict
./check_cve_2026_45185.sh --json | jq -r '.verdict'
# Check if a specific mitigation was found
./check_cve_2026_45185.sh --json | jq '.mitigations | contains(["aslr=full"])'
# Run across multiple hosts and collect results
for host in mail1 mail2 mail3; do
ssh "$host" 'bash -s' < check_cve_2026_45185.sh --json
done | jq -s '.'
# Debian / Ubuntu
apt-get update && apt-get install --only-upgrade exim4
# RHEL / CentOS / Fedora
dnf upgrade exim
# From source
# Download 4.99.3 from https://ftp.exim.org/pub/exim/exim4/
# and rebuild with your existing Local/Makefile settings
Verify after upgrade:
exim -bV | head -1
# Expected: Exim version 4.99.3 ...
If you cannot upgrade immediately, adding the following line to the main configuration section of your Exim config disables BDAT advertisement entirely, blocking the attack vector:
chunking_advertise_hosts =
The empty value means "no hosts" — Exim will no longer advertise the
CHUNKING extension in EHLO responses. Restart Exim after making this
change:
# Debian / Ubuntu
systemctl restart exim4
# Other systemd systems
systemctl restart exim
Verify CHUNKING is no longer advertised:
# Connect and check the EHLO response — CHUNKING should not appear
echo QUIT | openssl s_client -connect localhost:25 -starttls smtp 2>/dev/null \
| grep -i chunking
# No output = CHUNKING is disabled
This is a workaround, not a fix. Some sending mail servers use BDAT for large message delivery. Disabling it may cause compatibility issues with those senders. Upgrade to 4.99.3 as soon as possible.
Even on a patched system, adding these directives to the Exim systemd unit reduces the impact of any future memory corruption vulnerability:
# /etc/systemd/system/exim4.service.d/hardening.conf
[Service]
NoNewPrivileges=yes
MemoryDenyWriteExecute=yes
ProtectSystem=strict
PrivateTmp=yes
RestrictAddressFamilies=AF_INET AF_INET6
SystemCallFilter=@system-service
systemctl daemon-reload && systemctl restart exim4
ldd and
strings, which may be less reliable.--json |
| Output results as a JSON object (see below) |
--quiet | Suppress all output; only the exit code is set |
--no-color | Disable ANSI colour codes (useful for log files) |
--help / -h | Print usage information |
2 | Inconclusive — could not determine one or more required facts; treat as potentially vulnerable |
3 | Script error or unsupported environment |