CVE-2026-74766 Overview
CVE-2026-74766 is a heap use-after-free vulnerability [CWE-416] in the Net::IDN::Punycode Perl module, affecting versions from 2.301 before 2.590. The flaw resides in the XS backend of decode_punycode, where an attacker-supplied punycode label containing code points above U+FFFF triggers a buffer reallocation. The insertion pointer is computed before the reallocation, causing subsequent memory operations to read and write freed heap memory. Only the XS backend is affected; the pure-Perl backend is not. The defect was introduced by the fix for CVE-2016-15059 in version 2.301.
Critical Impact
Decoding an attacker-controlled punycode label corrupts heap memory in the Perl process, enabling potential code execution or process crashes in any application that decodes untrusted internationalized domain names.
Affected Products
- Net::IDN::Punycode for Perl, versions 2.301 through 2.589
- Net::IDN::Encode distribution shipping the affected XS backend
- Perl applications using Net::IDN::Encode to decode internationalized domain names
Discovery Timeline
- 2026-09-22 - CVE-2026-74766 published to NVD
- 2026-09-22 - Last updated in NVD database
Technical Details for CVE-2026-74766
Vulnerability Analysis
The vulnerability exists in the decode_punycode function within lib/Net/IDN/Punycode.xs. The XS backend inserts each decoded Unicode code point into the string buffer of the scalar it returns. The routine computes the insertion pointer skip_p by walking the existing UTF-8 buffer, and only afterward calls grow_string to enlarge the buffer when the new code point does not fit.
The growth operation reallocates the underlying heap buffer and updates the tracked pointers re_s, re_p, and re_e, but the previously computed skip_p is not refreshed. The subsequent Move of trailing bytes and the write of the new code point both dereference the stale skip_p, reading and writing freed heap memory.
Root Cause
The output buffer starts at twice the label length. Decoded code points above U+FFFF require four bytes in UTF-8, so a label composed of such code points quickly outgrows the initial allocation and forces reallocation. The pointer ordering bug was introduced in version 2.301 when the maintainer patched CVE-2016-15059.
Attack Vector
An attacker supplies a crafted punycode label containing high Unicode code points. Any Perl application that passes untrusted input to decode_punycode from the XS backend triggers the use-after-free. The CVSS vector indicates a local attack surface, but exposure extends to any process that decodes attacker-influenced IDN labels, including email processors, URL parsers, and DNS tooling.
// Patch: grow the decode buffer BEFORE taking the insertion pointer
u8 = UNISKIP(n); /* how many bytes we need */
+ grow_string(RETVAL, &re_s, &re_p, &re_e, u8);
+
j = i;
for(skip_p = re_s; j > 0; j--) /* find position in UTF-8 */
skip_p+=UTF8SKIP(skip_p);
- grow_string(RETVAL, &re_s, &re_p, &re_e, u8);
if(skip_p < re_p) /* move succeeding chars */
Move(skip_p, skip_p + u8, re_p - skip_p, char);
re_p += u8;
Source: GitHub Patch Commit 259e74c
A companion patch also rejects decoded code points above U+10FFFF, closing a related class of invalid inputs:
#define DAMP 700
#define INITIAL_BIAS 72
#define INITIAL_N 128
+#define UNICODE_MAX 0x10FFFF
Source: GitHub Patch Commit 2fbc71e4
Detection Methods for CVE-2026-74766
Indicators of Compromise
- Unexpected Perl process crashes or SIGSEGV in workflows that decode IDN or punycode input
- Heap corruption reports from AddressSanitizer or Valgrind runs of Perl binaries linked against affected Net::IDN::Encode XS objects
- Punycode labels containing repeated high code points (for example, sequences that decode to characters at or near U+10FFFF)
Detection Strategies
- Inventory installed CPAN modules and flag any Net::IDN::Encode installation with a version between 2.301 and 2.589
- Audit application code paths that call decode_punycode, domain_to_unicode, or email_to_unicode on untrusted input
- Run fuzz tests against decode entry points using punycode strings that expand to four-byte UTF-8 sequences
Monitoring Recommendations
- Alert on abnormal termination of long-running Perl services that process email, URLs, or DNS names
- Capture core dumps from affected services to identify heap corruption signatures tied to Punycode.xs
- Track CPAN and OS package repositories for the Net-IDN-Encode 2.590 upgrade rollout across hosts
How to Mitigate CVE-2026-74766
Immediate Actions Required
- Upgrade Net::IDN::Encode to version 2.590 or later on every host running affected Perl applications
- Rebuild or reinstall any packaged distributions that vendor Net::IDN::Encode as a dependency
- Restrict or sanitize untrusted IDN input at application boundaries until patching completes
Patch Information
The fix is delivered in Net-IDN-Encode-2.590-TRIAL and later. Two commits address the issue: commit 259e74c reorders the grow_string call so the buffer is enlarged before the insertion pointer is computed, and commit 2fbc71e rejects decoded code points above U+10FFFF. Refer to the MetaCPAN Release Changes and the upstream patches at GitHub Patch Commit 259e74c and GitHub Patch Commit 2fbc71e4.
Workarounds
- Force applications to use the pure-Perl backend by setting $Net::IDN::Punycode::_NO_XS = 1 before loading the module, which avoids the vulnerable XS code path
- Reject punycode labels that decode to code points above U+FFFF at the input validation layer
- Isolate services that decode untrusted IDN input into least-privilege sandboxes to limit blast radius
# Upgrade Net::IDN::Encode via cpanm to the fixed release
cpanm --force Net::IDN::Encode@2.590
# Verify the installed version
perl -MNet::IDN::Encode -E 'say $Net::IDN::Encode::VERSION'
# Optional: disable the XS backend as a temporary mitigation
PERL5OPT='-MNet::IDN::Punycode=_NO_XS' perl your_app.pl
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.