Skip to main content
Vulnerability Database/CVE-2026-74766

CVE-2026-74766: Perl Net::IDN::Punycode Use-After-Free Flaw

CVE-2026-74766 is a heap use-after-free vulnerability in Net::IDN::Punycode for Perl that allows attackers to exploit freed heap memory during punycode decoding. This article covers technical details, affected versions, security impact, and mitigation strategies.

Published:

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.

text
// 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:

text
 #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
bash
# 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.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.