Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-loofah for openSUSE:Factory 
checked in at 2026-09-10 11:48:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-loofah (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-loofah.new.1265 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-loofah"

Thu Sep 10 11:48:05 2026 rev:29 rq:1376640 version:2.25.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-loofah/rubygem-loofah.changes    
2026-03-29 20:01:36.007676176 +0200
+++ /work/SRC/openSUSE:Factory/.rubygem-loofah.new.1265/rubygem-loofah.changes  
2026-09-10 11:51:11.464086746 +0200
@@ -1,0 +2,26 @@
+Wed Sep  9 06:54:59 UTC 2026 - Johannes Segitz <[email protected]>
+
+- update to 2.25.2
+  * Ensure Loofah::HTML5::Scrub.allowed_uri? recognizes numeric character
+    references without semicolons (e.g. javascript&#58alert(1)), which browsers
+    decode and execute, and rejects schemes split by them. See
+    GHSA-5qhf-9phg-95m2. @flavorjones
+  * Ensure Loofah::HTML5::Scrub.allowed_uri? recognizes the named character
+    references &Tab; and &NewLine;, which CGI.unescapeHTML does not decode and
+    browsers strip from URIs, and rejects schemes split by them (e.g.
+    java&Tab;script:alert(1)). See GHSA-8whx-365g-h9vv. @flavorjones
+  * Ensure that both href and xlink:href attributes on SVG elements like use
+    are restricted to local (same-document) references. Previously only
+    xlink:href was restricted, allowing the SVG 2 href attribute to reference
+    external documents. See GHSA-9wjq-cp2p-hrgf. @flavorjones
+  * Harden data: URI mediatype parsing in Loofah::HTML5::Scrub.allowed_uri?.
+    The mediatype is now parsed following the WHATWG data: URL spec and RFC
+    2397 instead of simply being split on a colon. A data: URI with an omitted
+    or malformed mediatype is now treated as text/plain and allowed, and one
+    without the required comma is now rejected. #305 @flavorjones
+  * Remove feed from the default set of allowed protocols
+  * Ensure Loofah::HTML5::Scrub.allowed_uri? recognizes unescaped whitespace
+    entities and rejects schemas containing them. See GHSA-46fp-8f5p-pf2m. #302
+    @flavorjones
+
+-------------------------------------------------------------------

Old:
----
  loofah-2.25.0.gem

New:
----
  loofah-2.25.2.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-loofah.spec ++++++
--- /var/tmp/diff_new_pack.4Gx4I7/_old  2026-09-10 11:51:12.206117866 +0200
+++ /var/tmp/diff_new_pack.4Gx4I7/_new  2026-09-10 11:51:12.208117950 +0200
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-loofah
-Version:        2.25.0
+Version:        2.25.2
 Release:        0
 %define mod_name loofah
 %define mod_full_name %{mod_name}-%{version}

++++++ loofah-2.25.0.gem -> loofah-2.25.2.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md
--- old/CHANGELOG.md    1980-01-02 01:00:00.000000000 +0100
+++ new/CHANGELOG.md    1980-01-02 01:00:00.000000000 +0100
@@ -1,5 +1,24 @@
 # Changelog
 
+## 2.25.2 / 2026-07-15
+
+### Security
+
+* Ensure `Loofah::HTML5::Scrub.allowed_uri?` recognizes numeric character 
references without semicolons (e.g. `javascript&#58alert(1)`), which browsers 
decode and execute, and rejects schemes split by them. See 
[GHSA-5qhf-9phg-95m2](https://github.com/flavorjones/loofah/security/advisories/GHSA-5qhf-9phg-95m2).
 @flavorjones
+* Ensure `Loofah::HTML5::Scrub.allowed_uri?` recognizes the named character 
references `&Tab;` and `&NewLine;`, which `CGI.unescapeHTML` does not decode 
and browsers strip from URIs, and rejects schemes split by them (e.g. 
`java&Tab;script:alert(1)`). See 
[GHSA-8whx-365g-h9vv](https://github.com/flavorjones/loofah/security/advisories/GHSA-8whx-365g-h9vv).
 @flavorjones
+* Ensure that both `href` and `xlink:href` attributes on SVG elements like 
`use` are restricted to local (same-document) references. Previously only 
`xlink:href` was restricted, allowing the SVG 2 `href` attribute to reference 
external documents. See 
[GHSA-9wjq-cp2p-hrgf](https://github.com/flavorjones/loofah/security/advisories/GHSA-9wjq-cp2p-hrgf).
 @flavorjones
+
+### Improved
+
+* Harden `data:` URI mediatype parsing in `Loofah::HTML5::Scrub.allowed_uri?`. 
The mediatype is now parsed following the [WHATWG data: URL 
spec](https://fetch.spec.whatwg.org/#data-urls) and [RFC 
2397](https://www.rfc-editor.org/rfc/rfc2397) instead of simply being split on 
a colon. A `data:` URI with an omitted or malformed mediatype is now treated as 
`text/plain` and allowed, and one without the required comma is now rejected. 
#305 @flavorjones
+* Remove `feed` from the default set of allowed protocols. The [feed URI 
scheme](https://en.wikipedia.org/wiki/Feed_URI_scheme) was never accepted as a 
standard protocol, and no major browser supports it. Removing it reduces the 
attack surface particularly for non-browser contexts. #304 @flavorjones
+* Remove a vestigial `&#x70` alternative from 
`Loofah::HTML5::SafeList::PROTOCOL_SEPARATOR`. This appears to be an ancient 
typo dating back to pre-extraction Rails circa 2007. #305 @flavorjones
+
+
+## 2.25.1 / 2026-03-17
+
+* Ensure `Loofah::HTML5::Scrub.allowed_uri?` recognizes unescaped whitespace 
entities and rejects schemas containing them. See 
[GHSA-46fp-8f5p-pf2m](https://github.com/flavorjones/loofah/security/advisories/GHSA-46fp-8f5p-pf2m).
 #302 @flavorjones
+
 ## 2.25.0 / 2025-12-15
 
 * Extract `Loofah::HTML5::Scrub.allowed_uri?` which operates on a string. 
Previously this logic was coupled to the parsed tree in `.scrub_uri_attribute`. 
#300 @flavorjones
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SECURITY.md new/SECURITY.md
--- old/SECURITY.md     1980-01-02 01:00:00.000000000 +0100
+++ new/SECURITY.md     1980-01-02 01:00:00.000000000 +0100
@@ -2,7 +2,7 @@
 
 The Loofah core contributors take security very seriously and investigate all 
reported vulnerabilities.
 
-If you would like to report a vulnerablity or have a security concern 
regarding Loofah, please [report it via 
HackerOne](https://hackerone.com/loofah/reports/new).
+If you would like to report a vulnerablity or have a security concern 
regarding Loofah, please [report it via 
Github](https://github.com/flavorjones/loofah/security).
 
 Your report will be acknowledged within 24 hours, and you'll receive a more 
detailed response within 72 hours indicating next steps in handling your report.
 
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/loofah/html5/safelist.rb 
new/lib/loofah/html5/safelist.rb
--- old/lib/loofah/html5/safelist.rb    1980-01-02 01:00:00.000000000 +0100
+++ new/lib/loofah/html5/safelist.rb    1980-01-02 01:00:00.000000000 +0100
@@ -605,6 +605,11 @@
         "stroke",
       ])
 
+      SVG_HREF_ATTRIBUTES = Set.new([
+        "xlink:href",
+        "href",
+      ])
+
       SVG_ALLOW_LOCAL_HREF = Set.new([
         "altGlyph",
         "animate",
@@ -978,7 +983,7 @@
         "stroke-opacity",
       ])
 
-      PROTOCOL_SEPARATOR = /:|(&#0*58)|(&#x70)|(&#x0*3a)|(%|&#37;)3A/i
+      PROTOCOL_SEPARATOR = /:|(&#0*58)|(&#x0*3a)|(%|&#37;)3A/i
 
       ACCEPTABLE_PROTOCOLS = Set.new([
         "afs",
@@ -987,7 +992,6 @@
         "data",
         "ed2k",
         "fax",
-        "feed",
         "ftp",
         "gopher",
         "http",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/loofah/html5/scrub.rb 
new/lib/loofah/html5/scrub.rb
--- old/lib/loofah/html5/scrub.rb       1980-01-02 01:00:00.000000000 +0100
+++ new/lib/loofah/html5/scrub.rb       1980-01-02 01:00:00.000000000 +0100
@@ -14,7 +14,43 @@
       CSS_WHITESPACE = " "
       CSS_PROPERTY_STRING_WITHOUT_EMBEDDED_QUOTES = /\A(["'])?[^"']+\1\z/
       DATA_ATTRIBUTE_NAME = /\Adata-[\w-]+\z/
-      URI_PROTOCOL_REGEX = /\A[a-z][a-z0-9+\-.]*:/ # RFC 3986
+
+      # Decimal (`&#58`) or hexadecimal (`&#x3a`) form, with or without the 
trailing semicolon that
+      # CGI.unescapeHTML requires but browsers do not.
+      NUMERIC_CHARACTER_REFERENCE = /&#(x[0-9a-f]+|[0-9]+);?/i
+
+      # A scheme (RFC 3986) followed by a protocol separator. The separator 
must recognize the same
+      # encoded-colon forms as PROTOCOL_SEPARATOR, otherwise a scheme split by 
an encoded colon (for
+      # example "javascript&#58alert(1)") would not be recognized as having a 
scheme and would skip
+      # protocol validation.
+      URI_PROTOCOL_REGEX = 
/\A[a-z][a-z0-9+\-.]*#{SafeList::PROTOCOL_SEPARATOR}/
+
+      # Matches a valid MIME type "essence" (type "/" subtype, no parameters), 
used to
+      # decide whether a data: URI mediatype is well-formed; a non-match is 
not a valid
+      # MIME type, which the data: URL processor treats as text/plain. Specs:
+      #
+      #   https://mimesniff.spec.whatwg.org/#valid-mime-type
+      #   https://mimesniff.spec.whatwg.org/#mime-type-essence
+      #   https://mimesniff.spec.whatwg.org/#http-token-code-point
+      #
+      # The character class below is the HTTP token set (tchar) from RFC 9110 
section
+      # 5.6.2, https://www.rfc-editor.org/rfc/rfc9110#name-tokens :
+      #
+      #   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / 
"^"
+      #         / "_" / "`" / "|" / "~" / DIGIT / ALPHA
+      #
+      # ALPHA is written a-z, not a-zA-Z, because allowed_uri? downcases the 
input first.
+      DATA_URI_MEDIATYPE = %r{
+        \A
+        [a-z0-9!\#$%&'*+\-.^_`|~]+   # type:    1*tchar
+        /                            # "/" is not a tchar, so it is the sole 
delimiter
+        [a-z0-9!\#$%&'*+\-.^_`|~]+   # subtype: 1*tchar
+        \z
+      }x
+
+      # HTML5 named character references for whitespace that browsers strip 
from
+      # URIs. CGI.unescapeHTML does not decode these, so they are handled 
explicitly.
+      WHITESPACE_CHARACTER_REFERENCES = /&(Tab|NewLine);/
 
       class << self
         def allowed_element?(element_name)
@@ -48,7 +84,7 @@
             end
 
             next unless SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) &&
-              attr_name == "xlink:href" &&
+              SafeList::SVG_HREF_ATTRIBUTES.include?(attr_name) &&
               attr_node.value =~ /^\s*[^#\s].*/m
 
             attr_node.remove
@@ -141,26 +177,52 @@
           attr_node.value = values.join(" ")
         end
 
-        # Returns true if the given URI string is safe, false otherwise.
-        # This method can be used to validate URI attribute values without
-        # requiring a Nokogiri DOM node.
+        # Returns true if the given URI string is safe, false otherwise. This 
method can be used to
+        # validate URI attribute values without requiring a Nokogiri DOM node.
         def allowed_uri?(uri_string)
-          # this logic lifted nearly verbatim from HTML5 sanitization
-          val_unescaped = CGI.unescapeHTML(uri_string.gsub(CONTROL_CHARACTERS, 
"")).gsub("&colon;", ":").downcase
-          if URI_PROTOCOL_REGEX.match?(val_unescaped)
-            protocol = val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0]
+          # CGI.unescapeHTML decodes numeric references only when they carry a 
trailing semicolon, so
+          # also decode the semicolon-less ones, which browsers still decode 
and execute. Normalizing
+          # more aggressively than a browser only rejects more, which is safe. 
Control characters are
+          # stripped both before and after decoding, since decoding can 
produce them. That strip must
+          # precede WHITESPACE_CHARACTER_REFERENCES: removing a control 
character can reveal a named
+          # whitespace reference.
+          uri_string = 
decode_numeric_character_references(CGI.unescapeHTML(uri_string.gsub(CONTROL_CHARACTERS,
 "")))
+          uri_string.gsub!(CONTROL_CHARACTERS, "")
+          uri_string.gsub!(WHITESPACE_CHARACTER_REFERENCES, "")
+          uri_string.gsub!("&colon;", ":")
+          uri_string.downcase!
+          if URI_PROTOCOL_REGEX.match?(uri_string)
+            protocol = uri_string.split(SafeList::PROTOCOL_SEPARATOR)[0]
             return false unless SafeList::ALLOWED_PROTOCOLS.include?(protocol)
 
             if protocol == "data"
               # permit only allowed data mediatypes
-              mediatype = val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[1]
-              mediatype, _ = mediatype.split(/[;,]/)[0..1] if mediatype
-              return false if mediatype && 
!SafeList::ALLOWED_URI_DATA_MEDIATYPES.include?(mediatype)
+              return false unless 
SafeList::ALLOWED_URI_DATA_MEDIATYPES.include?(data_uri_mediatype(uri_string))
             end
           end
           true
         end
 
+        def decode_numeric_character_references(string)
+          string.gsub(NUMERIC_CHARACTER_REFERENCE) do |reference|
+            digits = ::Regexp.last_match(1)
+            hexadecimal = digits.start_with?("x", "X")
+            digits = digits[1..-1] if hexadecimal
+            significant_digits = digits.sub(/\A0+/, "")
+
+            # The largest code point is U+10FFFF: 7 decimal or 6 hexadecimal 
significant digits.
+            # Anything longer is out of range; skip it without building a 
large integer from it.
+            next reference if significant_digits.length > (hexadecimal ? 6 : 7)
+
+            codepoint = significant_digits.to_i(hexadecimal ? 16 : 10)
+            begin
+              codepoint.chr(Encoding::UTF_8)
+            rescue RangeError
+              reference
+            end
+          end
+        end
+
         def scrub_uri_attribute(attr_node)
           if allowed_uri?(attr_node.value)
             false
@@ -235,6 +297,20 @@
             string
           end
         end
+
+        private
+
+        # Returns the mediatype of a data: URI per RFC 2397, or nil when the
+        # required comma is absent. allowed_uri? entity-decodes, downcases, and
+        # strips control characters before calling this. An omitted or 
malformed
+        # mediatype resolves to "text/plain", matching the WHATWG data: URL 
processor.
+        def data_uri_mediatype(uri_string)
+          metadata, comma, _data = 
uri_string.delete_prefix("data:").partition(",")
+          return nil if comma.empty?
+
+          mediatype = metadata.delete_suffix(";base64").split(";", 
2).first.to_s.strip
+          mediatype.match?(DATA_URI_MEDIATYPE) ? mediatype : "text/plain"
+        end
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/loofah/version.rb new/lib/loofah/version.rb
--- old/lib/loofah/version.rb   1980-01-02 01:00:00.000000000 +0100
+++ new/lib/loofah/version.rb   1980-01-02 01:00:00.000000000 +0100
@@ -2,5 +2,5 @@
 
 module Loofah
   # The version of Loofah you are using
-  VERSION = "2.25.0"
+  VERSION = "2.25.2"
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        1980-01-02 01:00:00.000000000 +0100
+++ new/metadata        1980-01-02 01:00:00.000000000 +0100
@@ -1,7 +1,7 @@
 --- !ruby/object:Gem::Specification
 name: loofah
 version: !ruby/object:Gem::Version
-  version: 2.25.0
+  version: 2.25.2
 platform: ruby
 authors:
 - Mike Dalessio
@@ -96,7 +96,7 @@
     - !ruby/object:Gem::Version
       version: '0'
 requirements: []
-rubygems_version: 3.6.9
+rubygems_version: 4.0.10
 specification_version: 4
 summary: Loofah is a general library for manipulating and transforming 
HTML/XML documents
   and fragments, built on top of Nokogiri.

Reply via email to