Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:libnet-cidr-set-perl
User: [email protected]
Usertags: pu

[ Reason ]
This fixes CVE-2026-49940, CVE-2026-49942 and CVE-2026-49941.
These are minior issues with input sanitizing.

[ Impact ]
Depending on the usage of the library this may be a security issue.

[ Tests ]
salsa-ci passed execpt test-uscan (which isn't a problem for a
trixie-pu).  See
https://salsa.debian.org/perl-team/modules/packages/libnet-cidr-set-perl/-/pipelines/1108672
The two patches both ship their own test cases, which succeed.
(For this I had to add libtest-exception-perl to Build-Depends).

[ Risks ]
Hopefully none...

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable (0.21-1)

[ Changes ]
Fixes for CVE-2026-49940, CVE-2026-49942 and CVE-2026-49941.
Add libtest-exception-perl to Build-Depends to run the added
testsuite.
Switch RELEASE in salsa-ci to trixie.

[ Other info ]
Moritz Mühlenhoff from the security team suggested to fix this via
point release, no need for a DSA.

Greetings
Roland
diff -Nru libnet-cidr-set-perl-0.15/debian/changelog libnet-cidr-set-perl-0.15/debian/changelog
--- libnet-cidr-set-perl-0.15/debian/changelog	2025-05-28 11:51:45.000000000 +0200
+++ libnet-cidr-set-perl-0.15/debian/changelog	2026-06-14 16:13:20.000000000 +0200
@@ -1,3 +1,12 @@
+libnet-cidr-set-perl (0.15-1+deb13u1) trixie; urgency=medium
+
+  * CVE-2026-49940+49942.patch: Only accept ASCII digits for netmasks and
+    IP addresses (Fixes CVE-2026-49940 and CVE-2026-49942).
+  * CVE-2026-49941.patch: Improve strictness of IP address matching
+    (Fixes CVE-2026-49941).
+
+ -- Roland Rosenfeld <[email protected]>  Sun, 14 Jun 2026 16:13:20 +0200
+
 libnet-cidr-set-perl (0.15-1) unstable; urgency=medium
 
   * New upstream version, fixes CVE-2025-40911 (Closes: #1106699).
diff -Nru libnet-cidr-set-perl-0.15/debian/control libnet-cidr-set-perl-0.15/debian/control
--- libnet-cidr-set-perl-0.15/debian/control	2025-05-28 11:51:45.000000000 +0200
+++ libnet-cidr-set-perl-0.15/debian/control	2026-06-14 16:13:20.000000000 +0200
@@ -6,6 +6,7 @@
 Priority: optional
 Build-Depends: debhelper-compat (= 13),
                libmodule-build-perl,
+               libtest-exception-perl <!nocheck>,
                perl:any
 Standards-Version: 4.7.2
 Vcs-Browser: https://salsa.debian.org/perl-team/modules/packages/libnet-cidr-set-perl
diff -Nru libnet-cidr-set-perl-0.15/debian/patches/CVE-2026-49940+49942.patch libnet-cidr-set-perl-0.15/debian/patches/CVE-2026-49940+49942.patch
--- libnet-cidr-set-perl-0.15/debian/patches/CVE-2026-49940+49942.patch	1970-01-01 01:00:00.000000000 +0100
+++ libnet-cidr-set-perl-0.15/debian/patches/CVE-2026-49940+49942.patch	2026-06-14 16:13:20.000000000 +0200
@@ -0,0 +1,69 @@
+From: Robert Rothenberg <[email protected]>
+Date: Mon, 1 Jun 2026 23:12:29 +0100
+Origin: upstream, https://github.com/robrwo/perl-Net-CIDR-Set/commit/875010b
+Forwarded: not-needed
+Subject: Only accept ASCII digits  for netmasks and IP addresses
+ CVE-2026-49940
+ CVE-2026-49942
+
+--- a/lib/Net/CIDR/Set/IPv4.pm
++++ b/lib/Net/CIDR/Set/IPv4.pm
+@@ -22,7 +22,7 @@ sub _pack {
+   my @nums = split /[.]/, shift, -1;
+   return unless @nums == 4;
+   for ( @nums ) {
+-    return unless /^\d{1,3}$/ and !/^0\d{1,2}$/ and $_ < 256;
++    return unless /^[0-9]{1,3}$/ and !/^0[1-9]+/ and $_ < 256;
+   }
+   return pack "CC*", 0, @nums;
+ }
+@@ -59,7 +59,7 @@ sub _encode {
+     return unless my $addr = _pack( $1 );
+     return
+      unless my $bits
+-       = ( $mask =~ /^\d+$/ )
++       = ( $mask =~ /^[0-9]+$/ )
+       ? _width2bits( $mask, 32 )
+       : _ip2bits( _pack( $mask ) );
+     return ( $addr & $bits, Net::CIDR::Set::_inc( $addr | ~$bits ) );
+--- a/lib/Net/CIDR/Set/IPv6.pm
++++ b/lib/Net/CIDR/Set/IPv6.pm
+@@ -22,7 +22,7 @@ sub _pack_ipv4 {
+   my @nums = split /[.]/, shift, -1;
+   return unless @nums == 4;
+   for ( @nums ) {
+-    return unless /^\d{1,3}$/ and !/^0\d{1,2}$/ and $_ < 256;
++    return unless /^[0-9]{1,3}$/ and !/^0[1-9]+/ and $_ < 256;
+   }
+   return pack "CC*", 0, @nums;
+ }
+@@ -43,7 +43,7 @@ sub _pack {
+   my ( $empty, $ipv4, $str ) = ( 0, '', '' );
+   for ( @nums ) {
+     return if $ipv4;
+-    $str .= "0" x ( 4 - length ) . $_, next if /^[a-fA-F\d]{1,4}$/;
++    $str .= "0" x ( 4 - length ) . $_, next if /^[a-fA-F0-9]{1,4}$/;
+     do { return if $empty++ }, $str .= "X", next if $_ eq '';
+     next if $ipv4 = _pack_ipv4( $_ );
+     return;
+--- /dev/null
++++ b/t/validation.t
+@@ -0,0 +1,18 @@
++#!perl
++
++use strict;
++use warnings;
++
++use Test::More;
++use Test::Exception;
++
++use Net::CIDR::Set;
++
++
++my $set = Net::CIDR::Set->new;
++
++throws_ok {
++    $set->add("\x{0661}0.0.0.0/8");
++} qr{^Can't decode \x{0661}0.0.0.0/8 as an IPv4 or IPv6 address};
++
++done_testing;
diff -Nru libnet-cidr-set-perl-0.15/debian/patches/CVE-2026-49941.patch libnet-cidr-set-perl-0.15/debian/patches/CVE-2026-49941.patch
--- libnet-cidr-set-perl-0.15/debian/patches/CVE-2026-49941.patch	1970-01-01 01:00:00.000000000 +0100
+++ libnet-cidr-set-perl-0.15/debian/patches/CVE-2026-49941.patch	2026-06-14 16:13:20.000000000 +0200
@@ -0,0 +1,183 @@
+From: Robert Rothenberg <[email protected]>
+Date: Tue, 2 Jun 2026 14:28:27 +0100
+Origin: upstream, https://github.com/robrwo/perl-Net-CIDR-Set/commit/3a40b4c
+Forwarded: not-needed
+Subject: Improve strictness of IP address matching
+ This prevents bad characters causing infinite loops in the matching algorithm.
+ CVE-2026-49941
+
+--- a/lib/Net/CIDR/Set/IPv4.pm
++++ b/lib/Net/CIDR/Set/IPv4.pm
+@@ -18,11 +18,14 @@ our $VERSION = '0.15';
+ 
+ sub new { bless \my $x, shift }
+ 
++my $DEC = "(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})";
++my $IP  = "(?:${DEC}\.){3}${DEC}";
++
+ sub _pack {
+   my @nums = split /[.]/, shift, -1;
+   return unless @nums == 4;
+   for ( @nums ) {
+-    return unless /^[0-9]{1,3}$/ and !/^0[1-9]+/ and $_ < 256;
++    return unless /\A${DEC}\z/ and !/\A0[1-9]+/;
+   }
+   return pack "CC*", 0, @nums;
+ }
+@@ -39,7 +42,7 @@ sub _ip2bits {
+   my $ip = shift or return;
+   vec( $ip, 0, 8 ) = 255;
+   my $bits = unpack 'B*', $ip;
+-  return unless $bits =~ /^1*0*$/;    # Valid mask?
++  return unless $bits =~ /\A1*0*\z/;    # Valid mask?
+   return $ip;
+ }
+ 
+@@ -48,30 +51,33 @@ sub _is_cidr {
+   my $mask = ~( $lo ^ $hi );
+   my $bits = unpack 'B*', $mask;
+   return unless $hi eq ($lo | $hi);
+-  return unless $bits =~ /^(1*)0*$/;
++  return unless $bits =~ /\A(1*)0*\z/;
+   return length( $1 ) - 8;
+ }
+ 
+ sub _encode {
+   my ( $self, $ip ) = @_;
+-  if ( $ip =~ m{^(.+?)/(.+)$} ) {
++  if ( $ip =~ m{\A(${IP})/((?:3[0-2]|[12]?[0-9])|${IP})\z} ) {
+     my $mask = $2;
+     return unless my $addr = _pack( $1 );
+     return
+      unless my $bits
+-       = ( $mask =~ /^[0-9]+$/ )
++       = ( $mask =~ /\A[0-9]+\z/ )
+       ? _width2bits( $mask, 32 )
+       : _ip2bits( _pack( $mask ) );
+     return ( $addr & $bits, Net::CIDR::Set::_inc( $addr | ~$bits ) );
+   }
+-  elsif ( $ip =~ m{^(.+?)-(.+)$} ) {
++  elsif ( $ip =~ m{\A(${IP})-(${IP})\z} ) {
+     return unless my $lo = _pack( $1 );
+     return unless my $hi = _pack( $2 );
+     return ( $lo, Net::CIDR::Set::_inc( $hi ) );
+   }
+-  else {
++  elsif ( $ip =~ m{\A${IP}\z} ) {
+     return $self->_encode( "$ip/32" );
+   }
++  else {
++    return;
++  }
+ }
+ 
+ sub encode {
+--- a/lib/Net/CIDR/Set/IPv6.pm
++++ b/lib/Net/CIDR/Set/IPv6.pm
+@@ -18,11 +18,13 @@ our $VERSION = '0.15';
+ 
+ sub new { bless \my $x, shift }
+ 
++my $DEC = "(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})";
++
+ sub _pack_ipv4 {
+   my @nums = split /[.]/, shift, -1;
+   return unless @nums == 4;
+   for ( @nums ) {
+-    return unless /^[0-9]{1,3}$/ and !/^0[1-9]+/ and $_ < 256;
++    return unless /\A${DEC}\z/ and !/\A0[1-9]+/;
+   }
+   return pack "CC*", 0, @nums;
+ }
+@@ -36,14 +38,14 @@ sub _426 {
+ sub _pack {
+   my $ip = shift;
+   return pack( 'H*', '0' x 33 ) if $ip eq '::';
+-  return if $ip =~ /^:/ and $ip !~ s/^::/:/;
+-  return if $ip =~ /:$/ and $ip !~ s/::$/:/;
++  return if $ip =~ /\A:/ and $ip !~ s/\A::/:/;
++  return if $ip =~ /:\z/ and $ip !~ s/::\z/:/;
+   my @nums = split /:/, $ip, -1;
+   return unless @nums <= 8;
+   my ( $empty, $ipv4, $str ) = ( 0, '', '' );
+   for ( @nums ) {
+     return if $ipv4;
+-    $str .= "0" x ( 4 - length ) . $_, next if /^[a-fA-F0-9]{1,4}$/;
++    $str .= "0" x ( 4 - length ) . $_, next if /\A[A-Fa-f0-9]{1,4}\z/;
+     do { return if $empty++ }, $str .= "X", next if $_ eq '';
+     next if $ipv4 = _pack_ipv4( $_ );
+     return;
+@@ -61,7 +63,7 @@ sub _unpack {
+ # Replace longest run of null blocks with a double colon
+ sub _compress_ipv6 {
+   my $ip = shift;
+-  if ( my @runs = $ip =~ /((?:(?:^|:)(?:0000))+:?)/g ) {
++  if ( my @runs = $ip =~ /((?:(?:\A|:)(?:0000))+:?)/g ) {
+     my $max = $runs[0];
+     for ( @runs[ 1 .. $#runs ] ) {
+       $max = $_ if length( $max ) < length;
+@@ -83,27 +85,30 @@ sub _is_cidr {
+   my $mask = ~( $lo ^ $hi );
+   my $bits = unpack 'B*', $mask;
+   return unless $hi eq ($lo | $hi);
+-  return unless $bits =~ /^(1*)0*$/;
++  return unless $bits =~ /\A(1*)0*\z/;
+   return length( $1 ) - 8;
+ }
+ 
+ sub _encode {
+   my ( $self, $ip ) = @_;
+-  if ( $ip =~ m{^(.+?)/(.+)$} ) {
++  if ( $ip =~ m{\A([0-9A-Fa-f:]+)/(0|[1-9][0-9]*)\z} ) {
+     my $mask = $2;
+     return unless my $addr = _pack( $1 );
+     return unless my $bits = _width2bits( $mask, 128 );
+     return ( $addr & $bits, Net::CIDR::Set::_inc( $addr | ~$bits ) );
+   }
+-  elsif ( $ip =~ m{^(.+?)-(.+)$} ) {
++  elsif ( $ip =~ m{\A([0-9A-Fa-f:]+)-([0-9A-Fa-f:]+)\z} ) {
+     my ( $from, $to ) = ( $1, $2 );
+     return unless my $lo = _pack( $from );
+     return unless my $hi = _pack( $to );
+     return ( $lo, Net::CIDR::Set::_inc( $hi ) );
+   }
+-  else {
++  elsif ( $ip =~ m{\A[0-9A-Fa-f:]+\z} ) {
+     return $self->_encode( "$ip/128" );
+   }
++  else {
++    return;
++  }
+ }
+ 
+ sub encode {
+--- a/t/validation.t
++++ b/t/validation.t
+@@ -13,6 +13,26 @@ my $set = Net::CIDR::Set->new;
+ 
+ throws_ok {
+     $set->add("\x{0661}0.0.0.0/8");
+-} qr{^Can't decode \x{0661}0.0.0.0/8 as an IPv4 or IPv6 address};
++} qr{^Can't decode \x{0661}0\.0\.0\.0/8 as an IPv4 or IPv6 address};
++
++$set->add("10.0.0.0/8");
++
++throws_ok {
++    $set->add("1.1.1.1/09");
++} qr{^Can't decode 1\.1\.1\.1/09 as an IPv4 (or IPv6 )?address};
++
++throws_ok {
++    $set->contains("10\n.0.0.0");
++} qr{^Can't decode 10\n\.0\.0\.0 as an IPv4 or IPv6 address}s;
++
++throws_ok {
++    Net::CIDR::Set->new->add("::1/foo");
++} qr{^Can't decode ::1/foo as an IPv4 or IPv6 address};
++
++
++throws_ok {
++    Net::CIDR::Set->new->add("::1/02");
++} qr{^Can't decode ::1/02 as an IPv4 or IPv6 address};
++
+ 
+ done_testing;
diff -Nru libnet-cidr-set-perl-0.15/debian/patches/series libnet-cidr-set-perl-0.15/debian/patches/series
--- libnet-cidr-set-perl-0.15/debian/patches/series	1970-01-01 01:00:00.000000000 +0100
+++ libnet-cidr-set-perl-0.15/debian/patches/series	2026-06-14 16:13:20.000000000 +0200
@@ -0,0 +1,2 @@
+CVE-2026-49940+49942.patch
+CVE-2026-49941.patch
diff -Nru libnet-cidr-set-perl-0.15/debian/salsa-ci.yml libnet-cidr-set-perl-0.15/debian/salsa-ci.yml
--- libnet-cidr-set-perl-0.15/debian/salsa-ci.yml	2025-05-28 11:51:45.000000000 +0200
+++ libnet-cidr-set-perl-0.15/debian/salsa-ci.yml	2026-06-14 16:13:20.000000000 +0200
@@ -1,3 +1,6 @@
 include:
  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
+
+variables:
+  RELEASE: 'trixie'

Attachment: signature.asc
Description: PGP signature

Reply via email to