net-imap rubygem vulnerable to possible DoS by memory exhaustionGHSA-j3g3-5qv5-52mj
Fix: ruby/net-imap#442GHSA-j3g3-5qv5-52mj is a Uncontrolled Resource Consumption vulnerability in net-imap. A fix is available for net-imap — see the affected versions and patch details below.
Exploitation Status
No confirmed exploitation observed yet
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for GHSA-j3g3-5qv5-52mj.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
Real-World Exposure
net-imap💎net-imap💎net-imap💎net-imapReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects RubyGems packages — download data is not available via public APIs for these ecosystems.
Description
Summary
There is a possibility for denial of service by memory exhaustion when net-imap reads server responses. At any time while the client is connected, a malicious server can send can send a "literal" byte count, which is automatically read by the client's receiver thread. The response reader immediately allocates memory for the number of bytes indicated by the server response.
This should not be an issue when securely connecting to trusted IMAP servers that are well-behaved. It can affect insecure connections and buggy, untrusted, or compromised servers (for example, connecting to a user supplied hostname).
Details
The IMAP protocol allows "literal" strings to be sent in responses, prefixed with their size in curly braces (e.g. {1234567890}\r\n). When Net::IMAP receives a response containing a literal string, it calls IO#read with that size. When called with a size, IO#read immediately allocates memory to buffer the entire string before processing continues. The server does not need to send any more data. There is no limit on the size of literals that will be accepted.
Fix
Upgrade
Users should upgrade to net-imap 0.5.7 or later. A configurable max_response_size limit has been added to Net::IMAP's response reader. The max_response_size limit has also been backported to net-imap 0.2.5, 0.3.9, and 0.4.20.
To set a global value for max_response_size, users must upgrade to net-imap ~> 0.4.20, or > 0.5.7.
Configuration
To avoid backward compatibility issues for secure connections to trusted well-behaved servers, the default max_response_size for net-imap 0.5.7 is very high (512MiB), and the default max_response_size for net-imap ~> 0.4.20, ~> 0.3.9, and 0.2.5 is nil (unlimited).
When connecting to untrusted servers or using insecure connections, a much lower max_response_size should be used.
# Set the global max_response_size (only ~> v0.4.20, > 0.5.7)
Net::IMAP.config.max_response_size = 256 << 10 # 256 KiB
# Set when creating the connection
imap = Net::IMAP.new(hostname, ssl: true,
max_response_size: 16 << 10) # 16 KiB
# Set after creating the connection
imap.max_response_size = 256 << 20 # 256 KiB
# flush currently waiting read, to ensure the new setting is loaded
imap.noop
Please Note: max_response_size only limits the size per response. It does not prevent a flood of individual responses and it does not limit how many unhandled responses may be stored on the responses hash. Users are responsible for adding response handlers to prune excessive unhandled responses.
Compatibility with lower max_response_size
A lower max_response_size may cause a few commands which legitimately return very large responses to raise an exception and close the connection. The max_response_size could be temporarily set to a higher value, but paginated or limited versions of commands should be used whenever possible. For example, to fetch message bodies:
imap.max_response_size = 256 << 20 # 256 KiB
imap.noop # flush currently waiting read
# fetch a message in 252KiB chunks
size = imap.uid_fetch(uid, "RFC822.SIZE").first.rfc822_size
limit = 252 << 10
message = ((0..size) % limit).each_with_object("") {|offset, str|
str << imap.uid_fetch(uid, "BODY.PEEK[]<#{offset}.#{limit}>").first.message(offset:)
}
imap.max_response_size = 16 << 20 # 16 KiB
imap.noop # flush currently waiting read
References
- PR to introduce max_response_size: https://github.com/ruby/net-imap/pull/444
- Specific commit: 0ae8576c1 - lib/net/imap/response_reader.rb
- Backport to 0.4: https://github.com/ruby/net-imap/pull/445
- Backport to 0.3: https://github.com/ruby/net-imap/pull/446
- Backport to 0.2: https://github.com/ruby/net-imap/pull/447
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 💎RubyGems | net-imap | ≥ 0.5.0&&< 0.5.7 | 0.5.7bundle update net-imap --conservative |
| 💎RubyGems | net-imap | ≥ 0.4.0&&< 0.4.20 | 0.4.20bundle update net-imap --conservative |
| 💎RubyGems | net-imap | ≥ 0.3.0&&< 0.3.9 | 0.3.9bundle update net-imap --conservative |
| 💎RubyGems | net-imap | all versions | 0.2.5bundle update net-imap --conservative |
Affected Products
net\ruby-langDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for net-imap, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update net-imap to 0.5.7 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-j3g3-5qv5-52mj is resolved across your whole dependency graph.
Workarounds
Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base or stability.Source: Red Hat security advisory for GHSA-j3g3-5qv5-52mj (CC BY 4.0)
Frequently Asked Questions
Is GHSA-j3g3-5qv5-52mj in your dependencies?
Find it across RubyGems, including transitive dependencies.