What's Changed
🔒 Security Fix
Fixes CVE-2025-25186 (GHSA-7fc5-f82f-cx69): A malicious server can exhaust client memory by sending APPENDUID
or COPYUID
responses with very large uid-set
ranges. Net::IMAP::UIDPlusData
expands these ranges into arrays of integers.
Fix with minor API changes
Set config.parser_use_deprecated_uidplus_data
to false
to replace UIDPlusData
with AppendUIDData
and CopyUIDData
. These classes store their UIDs as Net::IMAP::SequenceSet
objects (not expanded into arrays of integers). Code that does not handle APPENDUID
or COPYUID
responses should not see any difference. Code that does handle these responses may need to be updated.
For v0.3.8, this option is not available
For v0.4.19, the default value is true
.
For v0.5.6, the default value is :up_to_max_size
.
For v0.6.0, the only allowed value will be false
(UIDPlusData
will be removed from v0.6).
Mitigate with backward compatible API
Adjust config.parser_max_deprecated_uidplus_data_size
to limit the maximum UIDPlusData
UID set size.
When config.parser_use_deprecated_uidplus_data == true
, larger sets will crash.
When config.parser_use_deprecated_uidplus_data == :up_to_max_size
, larger sets will use AppendUIDData
or CopyUIDData
.
For v0.3,8, this limit is hard-coded to 10,000.
For v0.4.19, this limit defaults to 1000.
For v0.5.6, this limit defaults to 100.
For v0.6.0, the only allowed value will be 0
(UIDPlusData
will be removed from v0.6).
Please Note: unhandled responses
If the client does not add response handlers to prune unhandled responses, a malicious server can still eventually exhaust all client memory, by repeatedly sending malicious responses. However, net-imap
has always retained unhandled responses, and it has always been necessary for long-lived connections to prune these responses. This is not significantly different from connecting to a trusted server with a long-lived connection. To limit the maximum number of retained responses, a simple handler might look something like the following:
limit = 1000
imap.add_response_handler do |resp|
next unless resp.respond_to?(:name) && resp.respond_to?(:data)
name = resp.name
code = resp.data.code&.name if resp.data.is_a?(Net::IMAP::ResponseText)
imap.responses(name) { _1.slice!(0...-limit) }
imap.responses(code) { _1.slice!(0...-limit) }
end
Added
- 🔧 Ensure ResponseParser config is mutable and non-global by @nevans in #381
- ✨ Add SequenceSet methods for querying about duplicates by @nevans in #384
- ✨ Add
SequenceSet#each_ordered_number
by @nevans in #386 - ✨ Add
SequenceSet#find_ordered_index
by @nevans in #396 - ✨ Add
SequenceSet#ordered_at
by @nevans in #397 - ✨ Add AppendUIDData and CopyUIDData classes by @nevans in #400
- 🔧 Add parser config for
APPENDUID
/COPYUID
, 🗑️ Deprecate UIDPlusData by @nevans in #401
Fixed
- 🐛 Fix
SequenceSet#append
when its@string
is nil by @nevans in #376 - 🐛 Fix SequenceSet merging in another SequenceSet by @nevans in #377
- 🐛 Fix SequenceSet count dups with multiple "*" by @nevans in #387
- 🥅 Re-raise
#starttls
error from receiver thread by @nevans in #395
Documentation
- 📚 Fix
SequenceSet#cover?
documentation by @nevans in #379 - 📚 Document COPYUID in tagged vs untagged responses by @nevans in #398
Other Changes
- 🚚 Move UIDPlusData to its own file by @nevans in #391
- ♻️ Parse
uid-set
assequence-set
without*
by @nevans in #393
Miscellaneous
- ⬆️ Bump step-security/harden-runner from 2.10.2 to 2.10.3 by @dependabot in #375
- ⬆️ Bump step-security/harden-runner from 2.10.3 to 2.10.4 by @dependabot in #380
- ✅ Improve test coverage for SequenceSet enums by @nevans in #383
- ♻️✅ Refactor SequenceSet enumerator tests by @nevans in #385
- ➕ Add "irb" to Gemfile to silence warning by @nevans in #388
- Omit flaky test with macOS platform by @hsbt in #389
- ✅ Improve UIDPlusData test coverage by @nevans in #392
- 🚚 Rename UIDPLUS test file for consistency by @nevans in #399
Full Changelog: v0.5.5...v0.5.6