CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-128068

CVE-2026-128068: Regular Expression Denial of Service in rails-html-sanitizer

Alon Barad
Alon Barad
Software Engineer

Nov 13, 2026·9 min read·3 visits

Executive Summary (TL;DR)

A quadratic Regular Expression Denial of Service (ReDoS) vulnerability exists in rails-html-sanitizer (>= 1.0.3, < 1.7.2) when scrubbing SVG href and xlink:href attributes. Applications running on Ruby 3.1 or earlier (or JRuby) that customize their HTML sanitizer allowlist to permit SVG reference tags can suffer worker thread exhaustion when processing crafted multiline whitespace payloads.

CVE-2026-128068 (GHSA-cpgf-5mjf-73p7) is a Regular Expression Denial of Service (ReDoS) vulnerability in the rails-html-sanitizer Ruby gem affecting versions 1.0.3 through 1.7.1. The flaw resides in the Rails::HTML::PermitScrubber#scrub_attribute method, which uses the multiline regular expression /^\s*[^#\s].*/m to enforce local-only URI fragment references on SVG elements. On Ruby runtimes prior to version 3.2 (CRuby <= 3.1 and JRuby), evaluating an attribute value composed of repeated newline and whitespace characters without a hash character triggers quadratic backtracking O(n^2). Applications are only vulnerable if their sanitization allowlist is explicitly configured to permit SVG reference elements such as <use> alongside href or xlink:href attributes.

Vulnerability Overview

The rails-html-sanitizer gem is the standard library responsible for sanitizing HTML fragments in Ruby on Rails applications, powering Action View helpers such as sanitize. Internally, the gem builds upon Loofah and Nokogiri to parse HTML trees and filter elements and attributes against configurable allowlists via scrubber classes, primarily Rails::HTML::PermitScrubber and Rails::HTML::SafeListSanitizer.

CVE-2026-128068 (also tracked as GHSA-cpgf-5mjf-73p7) is an Inefficient Regular Expression Complexity vulnerability (CWE-1333) leading to Uncontrolled Resource Consumption (CWE-400) within Rails::HTML::PermitScrubber#scrub_attribute. The vulnerability is triggered when the scrubber validates href or xlink:href attributes on allowed SVG elements to ensure they only contain local fragment identifiers (values starting with #).

Because the validation logic uses a line-anchored regular expression (/^\s*[^#\s].*/m), an attacker can supply an attribute value consisting of thousands of newline characters (\n) without a # character. On Ruby runtimes lacking linear-time regular expression memoization—specifically CRuby 3.1 and earlier, as well as JRuby—the regular expression engine repeatedly rescans the trailing whitespace sequence from every newline boundary, resulting in quadratic $\mathcal{O}(n^2)$ CPU consumption.

> [!NOTE] > Default configurations of rails-html-sanitizer and Rails Action View are not affected. Exploitation requires the application to override the default tag and attribute allowlists to permit both an SVG reference element (such as <use>) and URI reference attributes (href or xlink:href).

Root Cause Analysis

To prevent SVG elements from loading external resources—which can introduce Cross-Site Scripting (XSS) or Server-Side Request Forgery (SSRF) vectors—Rails::HTML::PermitScrubber#scrub_attribute checks whether an element is listed in Loofah::HTML5::SafeList::SVG_ALLOW_LOCAL_HREF and whether the attribute is in Loofah::HTML5::SafeList::SVG_HREF_ATTRIBUTES. If both conditions hold, the scrubber tests the attribute value against the regular expression /^\s*[^#\s].*/m. If the pattern matches, the attribute is considered a non-local reference and is removed from the DOM node.

The root cause of the algorithmic complexity flaw lies in how Ruby's regular expression engine (Onigmo) interprets anchors and character classes in multiline mode:

  1. Line Anchor (^) vs. String Anchor (\A): In Ruby regular expressions, the caret ^ matches the beginning of any line (immediately following any \n character) by default, whereas \A matches exclusively at the beginning of the string.
  2. Overlapping Whitespace Matching (\s): The character class shorthand \s matches spaces, tabs, and newline characters ([ \t\r\n\f\v]).
  3. Failed Terminal Requirement ([^#\s]): After ^\s* consumes all contiguous whitespace and newlines to the end of the string, the engine attempts to match [^#\s] (any character that is neither # nor whitespace).

When the input string consists exclusively of $n$ newline characters (or whitespace interspersed with newlines) and contains no non-whitespace characters, the initial attempt starting at index $0$ consumes all $n$ bytes via \s* and fails at [^#\s]. Because \s* is greedy, the engine backtracks one character at a time down to index $0$, testing each position against [^#\s] (which fails because every character is whitespace).

Once backtracking at index $0$ is exhausted, the engine does not terminate. Because the pattern begins with ^ rather than \A, the engine advances to the next line boundary (index $1$, following the first \n) and repeats the entire scan across the remaining $n - 1$ characters. Across $n$ newline characters, the total number of character comparisons scales quadratically:

$$\sum_{i=1}^{n} (n - i) = \frac{n(n - 1)}{2} = \mathcal{O}(n^2)$$

In CRuby 3.2 and later, the Onigmo engine incorporates a memoization optimization for non-backreferencing regular expressions, bounding execution to $\mathcal{O}(n)$ linear time. However, CRuby 3.1 and earlier, as well as JRuby, execute the full backtracking and line-rescanning loop.

Code Analysis

Prior to version 1.7.2, lib/rails/html/scrubbers.rb maintained its own attribute-scrubbing logic inside PermitScrubber#scrub_attribute, duplicating functionality that also existed upstream in Loofah. The vulnerable implementation checked URI attributes, SVG reference attributes, and SVG local href attributes sequentially:

# Vulnerable code in lib/rails/html/scrubbers.rb (< 1.7.2)
def scrub_attribute(node, attr_node)
  attr_name = if attr_node.namespace
    "#{attr_node.namespace.prefix}:#{attr_node.node_name}"
  else
    attr_node.node_name
  end
 
  return if Loofah::HTML5::SafeList::ATTR_VAL_IS_URI.include?(attr_name) &&
            Loofah::HTML5::Scrub.scrub_uri_attribute(attr_node)
 
  if Loofah::HTML5::SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
    Loofah::HTML5::Scrub.scrub_attribute_that_allows_local_ref(attr_node)
  end
 
  # VULNERABLE CHECK: ^ anchors to every line start, causing O(n^2) rescanning
  if Loofah::HTML5::SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) &&
     Loofah::HTML5::SafeList::SVG_HREF_ATTRIBUTES.include?(attr_name) &&
     attr_node.value =~ /^\s*[^#\s].*/m
    attr_node.remove
  end
 
  node.remove_attribute(attr_node.name) if attr_name == "src" && attr_node.value !~ /[^[:space:]]/
 
  Loofah::HTML5::Scrub.force_correct_attribute_escaping!(node)
end

In commit f776f963b9d9346271aade9cb903e793fd38e865, the maintainers resolved the vulnerability by removing the custom regular expression and delegating attribute value validation to Loofah::HTML5::Scrub.scrub_attribute_value, coupled with bumping the minimum required loofah dependency to >= 2.25.3 (which Fixed the equivalent regex in Loofah):

# Patched code in lib/rails/html/scrubbers.rb (1.7.2)
def scrub_attribute(node, attr_node)
  # Extract normalized attribute name including namespace prefix via Loofah
  attr_name = Loofah::HTML5::Scrub.prefixed_attribute_name(attr_node)
 
  # Delegate URI and SVG local-reference scrubbing to Loofah >= 2.25.3
  # Returns true only if the attribute was completely removed by URI scrubbing
  return if Loofah::HTML5::Scrub.scrub_attribute_value(node, attr_node, attr_name)
 
  node.remove_attribute(attr_node.name) if attr_name == "src" && attr_node.value !~ /[^[:space:]]/
 
  Loofah::HTML5::Scrub.force_correct_attribute_escaping!(node)
end

Fix Completeness Assessment

The patch in rails-html-sanitizer 1.7.2 completely eliminates the vulnerable /^\s*[^#\s].*/m regular expression from the gem's codebase and consolidates sanitization rules into upstream Loofah (>= 2.25.3). In addition, the patch adds unit tests verifying edge cases where a local reference is followed by a newline and an external URL (e.g., href="#p\nhttp://bad.com/x"), ensuring that removing the ^ line-anchor trick does not reintroduce a bypass allowing multiline external references.

Furthermore, in commit c5252d798b283f29bf0a590ee1a63e9cb16bafa2 (also included in the 1.7.2 release), the gem updated spec.required_ruby_version = ">= 3.2.0", ensuring that future installations of rails-html-sanitizer run on Ruby versions with built-in linear-time regular expression matching.

Exploitation

Prerequisites

Exploiting CVE-2026-128068 requires three distinct conditions to be satisfied simultaneously:

  1. Custom Sanitizer Allowlist: The target application must explicitly permit at least one tag listed in Loofah::HTML5::SafeList::SVG_ALLOW_LOCAL_HREF (such as <use>, <animate>, <feImage>, <filter>, <linearGradient>, <mpath>, <pattern>, <radialGradient>, <set>, or <textPath>) and at least one attribute in Loofah::HTML5::SafeList::SVG_HREF_ATTRIBUTES (href or xlink:href).
  2. Unpatched Dependency: The application must use rails-html-sanitizer versions >= 1.0.3 and < 1.7.2.
  3. Non-Memoized Regex Runtime: The application must execute on CRuby 3.1 or earlier, or JRuby.

Attack Methodology & Proof of Concept

When a Rails controller or view passes user-controlled HTML to sanitize or Rails::HTML::SafeListSanitizer with SVG elements enabled, an unauthenticated attacker can submit an HTTP request containing an <svg><use href="..."></use></svg> fragment filled with newline characters (0x0A or HTML entity &#10;). Note that Nokogiri decodes numerical character references inside attribute values prior to invoking the scrubber's scrub_attribute method.

require "rails-html-sanitizer"
require "benchmark"
 
sanitizer = Rails::HTML::SafeListSanitizer.new
 
# Generate a 20 KB payload of newline characters without a '#' character
payload_size = 20_000
malicious_input = "<svg><use href=\"#{"\n" * payload_size}\"></use></svg>"
 
time = Benchmark.realtime do
  sanitizer.sanitize(
    malicious_input,
    tags: %w[svg use],
    attributes: %w[href xlink:href]
  )
end
 
puts "Sanitization took #{time.round(3)} seconds"

On CRuby 3.1.7, a 20 KB attribute payload consumes approximately 3.4 seconds of CPU time on a single thread. Because quadratic complexity scales by $4\times$ for every $2\times$ increase in payload size:

  • 20 KB payload $\approx 3.4$ seconds
  • 40 KB payload $\approx 13.6$ seconds
  • 80 KB payload $\approx 54.4$ seconds

Because Ruby's regular expression engine holds the Global VM Lock (GVL) during C-level regex evaluation on CRuby 3.1, a single request processing an 80 KB payload blocks all other Ruby threads within the same OS process for nearly a minute. In typical multi-process web servers like Puma or Unicorn, an attacker sending a small burst of concurrent requests can saturate all available worker processes, causing request queuing and HTTP 502/504 gateway timeouts across the entire application.

Impact Assessment

The security impact of CVE-2026-128068 is restricted to Availability. There is no mechanism through this vulnerability to bypass HTML sanitization rules, inject arbitrary scripts, read application memory, or modify server data.

CVSS v3.1 Breakdown

The vulnerability is rated 5.3 (Medium) with vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L:

  • Attack Vector (AV:N): Exploitable remotely via standard HTTP/HTTPS requests containing HTML payloads.
  • Attack Complexity (AC:L): Although non-default configuration is required, triggering the algorithmic slowdown on a vulnerable endpoint requires no race conditions or dynamic state preparation.
  • Privileges Required (PR:N): Publicly accessible forms, comment fields, or rich-text editors can be targeted without authentication.
  • User Interaction (UI:N): Sanitization frequently happens synchronously during request processing or background job execution without requiring another user to view the payload.
  • Confidentiality & Integrity (C:N / I:N): No data disclosure or unauthorized modification occurs.
  • Availability (A:L): Rated Low because the vulnerability requires specific non-default configuration and is mitigated by default on modern Ruby runtimes (CRuby 3.2+).

Threat Landscape

As of disclosure, CVE-2026-128068 is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and no active exploitation in the wild or ransomware integration has been observed.

Remediation

Primary Remediation: Upgrade Gem and Dependencies

Upgrade rails-html-sanitizer to version 1.7.2 or later, which automatically pulls in loofah >= 2.25.3 and removes the vulnerable regular expression:

bundle update rails-html-sanitizer loofah

Note that rails-html-sanitizer 1.7.2 requires Ruby >= 3.2.0. If your application is locked to Ruby 3.1 or earlier and cannot upgrade rails-html-sanitizer to 1.7.2, apply the runtime or configuration mitigations below.

Alternative Remediation: Upgrade Ruby Runtime

Upgrading the Ruby interpreter to CRuby 3.2.0 or newer resolves the quadratic backtracking behavior at the language engine level. Ruby 3.2's memoized regular expression matcher evaluates /^\s*[^#\s].*/m in $\mathcal{O}(n)$ linear time even if rails-html-sanitizer remains on a pre-1.7.2 release.

Workarounds for Legacy Environments

If neither the gem nor the Ruby runtime can be immediately upgraded, apply one or more of the following workarounds:

  1. Restrict Allowed SVG Tags and Attributes: Remove SVG reference tags (use, animate, feImage, filter, linearGradient, mpath, pattern, radialGradient, set, textPath) or remove href and xlink:href from custom sanitizer allowlists (config.action_view.sanitized_allowed_tags and config.action_view.sanitized_allowed_attributes).
  2. Custom Scrubber Pre-Filtering: Before passing untrusted HTML to PermitScrubber, strip or truncate attribute values containing excessive whitespace runs, or override scrub_attribute in a subclass to replace /^\s*[^#\s].*/m with an anchored check (!attr_node.value.strip.start_with?('#')).

Official Patches

RailsPatch commit removing the quadratic regex and delegating attribute scrubbing to Loofah >= 2.25.3
RailsOfficial release v1.7.2 of rails-html-sanitizer
GitHubGitHub Security Advisory GHSA-cpgf-5mjf-73p7

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

Affected Systems

rails-html-sanitizer RubyGem (>= 1.0.3, < 1.7.2)Ruby on Rails applications on CRuby <= 3.1 or JRuby with custom SVG sanitizer allowlists

Affected Versions Detail

Product
Affected Versions
Fixed Version
rails-html-sanitizer
Rails
>= 1.0.3, < 1.7.21.7.2
loofah
flavorjones
< 2.25.32.25.3
AttributeDetail
CVE IDCVE-2026-128068 (GHSA-cpgf-5mjf-73p7)
Weakness ClassCWE-1333 (Inefficient Regular Expression Complexity) / CWE-400
CVSS v3.1 Score5.3 Medium (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L)
Affected ComponentRails::HTML::PermitScrubber#scrub_attribute (rails-html-sanitizer >= 1.0.3, < 1.7.2)
Affected RuntimesCRuby <= 3.1 and JRuby (CRuby >= 3.2 is unaffected)
ImpactQuadratic O(n^2) CPU exhaustion / Worker Thread Denial of Service
Exploit StatusPoC / Algorithmic Complexity (Not in CISA KEV)
Patched Versionrails-html-sanitizer 1.7.2 (with loofah >= 2.25.3)

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-1333
Inefficient Regular Expression Complexity

The software uses a regular expression with an inefficient, possibly exponential or quadratic worst-case computational complexity that allows an attacker to cause a denial of service by crafting input that triggers excessive backtracking.

Vulnerability Timeline

Upstream fix authored by Mike Dalessio in commit f776f963b9d9346271aade9cb903e793fd38e865.
2026-09-13
Security fixes merged into release PR #243 and rails-html-sanitizer v1.7.2 prepared.
2026-11-02
GitHub Security Advisory GHSA-cpgf-5mjf-73p7 published and CVE-2026-128068 assigned.
2026-11-13
Advisory synchronized to the Ruby Advisory Database and CVE.org.
2026-11-13

References & Sources

  • [1]CVE-2026-128068 Official CVE Record
  • [2]GitHub Security Advisory GHSA-cpgf-5mjf-73p7
  • [3]Patch Commit f776f963b9d9346271aade9cb903e793fd38e865
  • [4]rails-html-sanitizer v1.7.2 Release Notes
  • [5]Ruby Advisory Database Entry for GHSA-cpgf-5mjf-73p7
  • [6]rails-html-sanitizer GitHub Repository

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 2 hours ago•CVE-2026-126360
5.3

CVE-2026-126360: Regular Expression Denial of Service in OpenTelemetry Python opentelemetry-api

CVE-2026-126360 (GHSA-mf5v-w3w3-f6cg) is an algorithmic complexity vulnerability (Regular Expression Denial of Service) in the trace context propagation logic of the opentelemetry-api package within the OpenTelemetry Python ecosystem. In versions prior to 1.45.2, the TraceContextTextMapPropagator.extract() method utilizes a regular expression susceptible to quadratic-time backtracking when parsing malformed W3C traceparent headers containing long sequences of whitespace followed by an embedded newline character. In Python applications—particularly those using single-threaded asynchronous event loops—an unauthenticated remote attacker transmitting payloads over newline-preserving carriers can monopolize CPU execution and induce application-level Denial of Service.

Alon Barad
Alon Barad
3 views•10 min read
•about 3 hours ago•CVE-2026-126359
3.4

CVE-2026-126359: Cross-Site Scripting via Split Closing Style Tag in Hono CSS Helper

CVE-2026-126359 (GHSA-3gg2-335m-rxc6) is an improper input neutralization vulnerability (CWE-79) in the Hono web framework (`honojs/hono`). Versions from 3.12.0 prior to 4.13.16 evaluate and escape interpolated strings in the `hono/css` helper individually before concatenating template chunks and stripping CSS comments. When a `<` character and a `/style>` sequence are split across template boundaries, adjacent interpolations, or separated by a CSS comment, the sanitizer fails to escape the closing tag sequence. During Server-Side Rendering (SSR), the `<Style />` component outputs an unescaped `</style>` delimiter, permitting an attacker to break out of the CSS raw text context and execute arbitrary HTML and JavaScript in the victim's browser.

Alon Barad
Alon Barad
4 views•10 min read
•about 4 hours ago•CVE-2026-126358
5.3

CVE-2026-126358: Authorization Bypass via Wildcard Middleware Omission in Hono RegExpRouter

An incorrect authorization vulnerability (CWE-863) exists in the Hono web application framework (npm package `hono`) from version 4.1.4 prior to 4.13.16. Flaws in the registration-time coverage calculation and regular expression compilation within `RegExpRouter` cause wildcard middleware to be omitted under three specific routing conditions: parameter pattern equivalence mismatches, wildcard boundary collisions, and request paths containing percent-encoded line terminators. Because Hono's default `SmartRouter` selects `RegExpRouter` for most standard web applications, unauthenticated remote clients can bypass authentication, authorization, or security middleware registered on wildcard paths to directly access protected route handlers or the application's not-found handler.

Alon Barad
Alon Barad
5 views•13 min read
•about 5 hours ago•CVE-2026-126357
5.3

CVE-2026-126357: Authentication Bypass via Mount Path Transformation in Hono

CVE-2026-126357 (GHSA-4m76-xfj5-7975) is an authentication bypass vulnerability in the Hono web application framework prior to version 4.13.16. The flaw resides in the prefix-stripping and URL reconstruction logic of `app.mount()` and the `mount()` middleware. Two distinct path transformation errors—static route-pattern length slicing on dynamic prefixes and URL normalization of decoded pathnames—create a routing discrepancy between the outer Hono router and the mounted sub-application. An unauthenticated attacker can exploit these discrepancies to bypass outer authentication or authorization middleware and access protected inner routes directly.

Amit Schendel
Amit Schendel
5 views•9 min read
•about 6 hours ago•CVE-2026-126356
5.3

CVE-2026-126356: Multipart Form Validation Bypass in Hono Web Framework

A parser differential vulnerability exists in the Hono web application framework versions 4.5.1 prior to 4.13.16. The built-in form validation middleware (`validator('form')`) utilizes an overly restrictive regular expression to evaluate the HTTP `Content-Type` header for `multipart/form-data` payloads. When a client supplies additional valid MIME parameters (such as `charset=utf-8`) or multiple whitespace characters following a semicolon delimiter, the regular expression fails to match. Consequently, the validator passes an empty object to the validation callback instead of the parsed form fields. If the validation logic permits empty objects or only checks for disallowed values on optional properties, the request passes validation, allowing downstream route handlers calling `c.req.parseBody()` or `c.req.formData()` to process unvalidated user input.

Amit Schendel
Amit Schendel
5 views•10 min read
•about 7 hours ago•CVE-2026-126355
5.3

CVE-2026-126355: Cross-Site Request Forgery Protection Bypass via Hyperlink Auditing in Hono

CVE-2026-126355 (GHSA-46wx-v44x-9hh2) is a Cross-Site Request Forgery (CSRF) validation bypass in Hono, a web application framework for JavaScript runtimes. Prior to version 4.13.16, Hono's built-in csrf() middleware only evaluated origin headers for requests matching standard HTML form MIME types (application/x-www-form-urlencoded, multipart/form-data, and text/plain). By leveraging the HTML anchor ping attribute in Chromium-based browsers, an attacker can initiate an unprompted, credentialed cross-origin HTTP POST request with Content-Type: text/ping without triggering a CORS preflight request. Because text/ping was omitted from the middleware regular expression, requests bypassed Origin and Sec-Fetch-Site verification, allowing unauthorized state-changing operations.

Amit Schendel
Amit Schendel
5 views•9 min read