← firefox
bugzilla #2081101
Quadratic address-group accumulation in JSMime causes mail-triggered UI denial of service
firefox
low
denial of service
RESOLVED / FIXED
description
Summary
Thunderbird's JSMime address parser repeatedly replaces the accumulated result array with results.concat(addrlist) while recovering from malformed address-group separators. Each call copies every address accumulated so far. A compact header such as To: a,:a,:a,:... therefore causes O(n²) element copying.
Address headers are parsed synchronously on the main thread while Thunderbird renders a message. An attacker who can deliver a crafted message can make the Thunderbird UI unresponsive when the victim previews or opens it. The attached 451,846-byte EML stalled the tested official Daily build for approximately 15 seconds. Larger headers extend the stall further.
The sample contains no RFC 2047 encoded-word markers. This is a separate root cause from Bug 2081099: the issue is repeated immutable array concatenation, and it also reproduces when RFC 2047 decoding is disabled.
Security impact
- Remote attacker-controlled input: an ordinary folded To, Cc, From, or other address header.
- Required user action: preview or open the crafted message.
- Result: main-thread CPU and allocation pressure causing a temporary application-wide UI denial of service.
- Confidentiality/integrity impact: none observed.
- Suggested CWE: CWE-407 (Inefficient Algorithmic Complexity); secondary CWE-400 (Uncontrolled Resource Consumption).
- Final security rating is left to Mozilla's triage team, as requested by the Client Bug Bounty reporting guidance.
Affected code
Current comm-central revision tested: 4d8f5f89a54280d9e7df4fa692dc29e59add9b73.
1. mailnews/mime/jsmime/jsmime.mjs:888-1130
parseAddressingHeader() builds a temporary addrlist and a top-level results array.
2. mailnews/mime/jsmime/jsmime.mjs:982-991
On each colon, pending entries are appended with:
if (addrlist.length > 0) {
results = results.concat(addrlist);
}
addrlist = [];
The three-byte pattern a,: first adds one entry to addrlist, then takes this branch. For n repetitions, the parser copies result arrays of lengths 1, 2, ..., n, for n(n+1)/2 total element copies.
3. mailnews/mime/jsmime/jsmime.mjs:1060-1076
The malformed-semicolon recovery path contains the same pattern. Repeating a,; triggers equivalent quadratic behavior.
4. mailnews/mime/src/MimeJSComponents.sys.mjs:262-268
MailServices.headerParser.parseEncodedHeaderW() invokes the affected address parser.
5. mail/base/content/msgHdrView.js:1595-1603
outputEmailAddresses() calls parseEncodedHeaderW() synchronously while rendering message headers.
Supported versions checked
The two vulnerable results.concat(addrlist) sites and the UI call path are present in the official source tags for:
- Thunderbird 157.0.1 release (THUNDERBIRD_157_0_1_RELEASE, commit ac1c50734e8df36f2ca56cd4dbe96558ec469b15)
- Thunderbird 153.4.0 ESR (THUNDERBIRD_153_4_0esr_RELEASE, commit 39e4af053e7a49fb2feb892ea77810f6280e5341)
- Thunderbird 140.17.0 ESR build 2 (THUNDERBIRD_140_17_0esr_BUILD2, commit 060fdd85f49aa9a992a0a6023aa883afe1d92177)
- Thunderbird Daily 160.0a1 build 20261012100649, dynamically reproduced
Reproduction
1. Use a disposable Thunderbird profile.
2. Open poc-452kb.eml using File > Open > Saved Message. The same rendering path is used when previewing a message in a folder.
3. Observe that Thunderbird's main UI is unresponsive for roughly 15 seconds while the To header is parsed and rendered.
4. Open the same-size control-452kb.eml. It completes substantially faster.
The PoC is inert text. It does not use scripts, external resources, credentials, or network requests. generate_poc.mjs regenerates both samples.
Measurements
Environment:
- Windows 11 Pro 64-bit, version 10.0.26200
- Official Thunderbird Daily 160.0a1, build ID 20261012100649
- Isolated test profile
End-to-end EML open time:
| Input | EML size | Open time |
|---|---:|---:|
| Candidate, 20,000 repetitions | 60,545 B | 439.5 ms |
| Candidate, 40,000 repetitions | 120,746 B | 1,381.4 ms |
| Candidate, 80,000 repetitions | 241,145 B | 4,067.1 ms |
| Same-size linear control, 100,000 repetitions | 301,344 B | 627.1 ms |
| Candidate, 100,000 repetitions | 301,348 B | 6,475.3 ms |
| Candidate, 150,000 repetitions | 451,846 B | 15,005.4 ms |
Direct timing of MailServices.headerParser.parseEncodedHeaderW():
| Header bytes | Control | Candidate |
|---:|---:|---:|
| 24,000 | 14.0 ms | 48.1 ms |
| 48,000 | 28.8 ms | 177.3 ms |
| 96,000 | 56.5 ms | 604.3 ms |
| 192,000 | 174.0 ms | 1,349.7 ms |
| 300,000 | 199.2 ms | 2,908.1 ms |
The same-size 300 KB parser inputs produce the same 100,000 result entries, but the candidate is approximately 14.6 times slower. End-to-end, the 301 KB candidate is approximately 10.3 times slower than the same-size control.
Root cause and suggested fix
Append the temporary entries without replacing and copying the full result array. A loop avoids both quadratic copies and the argument-count limits of a large spread call:
for (const item of addrlist) {
results.push(item);
}
Both results.concat(addrlist) sites should be changed. A regression test can parse many short malformed groups and verify that the result is correct without repeatedly replacing the result array.
Public duplicate search
- Bug 1411720 / CVE-2018-5161 concerned exponential escaping of repeated @ characters and was fixed for Thunderbird 60. This input does not exercise that encoding path.
- Bug 1055077 concerns general quick-filter performance across many messages, not repeated copying within one address header.
- Bug 1059988 concerns compatibility with semicolon-separated addresses, not algorithmic complexity or UI denial of service.
- Bug 2081099 is my pending report about unanchored RFC 2047 regular-expression searches in the tokenizer. This report contains no =? markers and exercises different lines and a different fix.
I did not find a public report for the current results.concat(addrlist) quadratic path.
PoC integrity
- poc-452kb.eml SHA-256: D4778C041876B302F7431AA3DF00B6B407765F23065DD6BE38B3AEF8D1C245FC
- control-452kb.eml SHA-256: 222F092CC7B962ED085A5B26104BB91AFE488EEC3451FDF5FFAA669C034B0314