Source: ruby3.3
Version: 3.3.8-2
X-Debbugs-CC: [email protected]
Severity: grave
Tags: security upstream
Control: fixed -1 3.3.13-0+deb13u1
Hi,
The following vulnerabilities were published for ruby3.3.
CVE-2026-80212[0]:
| An issue was discovered in the resolv gem before 0.7.2 for Ruby.
| Resolv::DNS::Resource.get_class,
| Resolv::DNS::Resource::Generic.create, and
| Resolv::DNS::SvcParam::Generic.create generate a new class for each
| unknown DNS resource record (type, class) pair, or each unknown
| SvcParamKey, encountered while decoding a response. Each generated
| class was permanently registered both as a constant on Resource (or
| SvcParam::Generic) and as an entry in a class-lookup hash
| (ClassHash), and thus the class remained reachable through that
| constant after the response was discarded. Type and class are each
| 16-bit values, and thus an attacker controlling DNS responses (a
| spoofed response, or a malicious or hijacked upstream DNS server)
| has roughly 2^32 distinct (type, class) pairs to choose from. A
| single response of a few hundred kilobytes carrying tens of
| thousands of distinct unknown types permanently grows process memory
| by tens of megabytes; repeated responses accumulate without bound
| and are never reclaimed by garbage collection, because the constant
| keeps each class alive. Any code path that calls
| Resolv::DNS::Message.decode on attacker-influenced DNS responses is
| affected. resolv is a default gem, and thus this is reachable from a
| plain Ruby installation without any additional dependency.
CVE-2026-80213[1]:
| An issue was discovered in the resolv gem before 0.7.2 for Ruby.
| Resolv::DNS::MessageEncoder wrote a DNS label's length into a single
| octet without checking its range. A label longer than 255 octets had
| its length stored modulo 256 but the label data was written
| unchanged, and thus the bytes on the wire described a different name
| than the one the application asked to encode. RFC 1035 section 2.3.4
| limits a label to 63 octets, and the two high bits of the length
| octet are reserved for compression pointers. put_string packed the
| length with put_pack("C", d.length) and put_label used it for
| labels, and thus any value from 0 to 255 could end up as a label
| length octet, including the reserved 0x40-0xBF range and the
| 0xC0-0xFF pointer range. Resolv::DNS::Name.create did not check per-
| label or total name length either, and thus an attacker-controlled
| hostname reached the encoder unchanged. An application that resolves
| an attacker-controlled hostname sends a query whose wire bytes name
| a domain the attacker chose. A hostname suffix that the application
| validates against an allowlist becomes padding that never appears on
| the wire, and thus allowlist and egress checks can be bypassed. The
| recursive resolver caches the response under the attacker's name,
| and DNS logs record that name rather than the one the application
| asked for. A label length whose low octet lands in the 0xC0-0xFF
| range produces a length octet that conforming parsers read as the
| start of a compression pointer, with the following attacker-
| controlled byte as the offset.
If you fix the vulnerabilities please also make sure to include the
CVE (Common Vulnerabilities & Exposures) ids in your changelog entry.
For further information see:
[0] https://security-tracker.debian.org/tracker/CVE-2026-80212
https://www.cve.org/CVERecord?id=CVE-2026-80212
[1] https://security-tracker.debian.org/tracker/CVE-2026-80213
https://www.cve.org/CVERecord?id=CVE-2026-80213
Regards,
Salvatore