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-126070

CVE-2026-126070: Cross-Site Scripting in Ruby on Rails Action View strip_tags Helper

Amit Schendel
Amit Schendel
Senior Security Researcher

Nov 13, 2026·10 min read·3 visits

Executive Summary (TL;DR)

Action View's strip_tags helper marks its output as html_safe without encoding quotation marks, allowing attackers to break out of quoted HTML attributes and achieve Cross-Site Scripting (XSS). Upgrade to Ruby on Rails 8.0.5.2 or 8.1.4.1.

CVE-2026-126070 is a Cross-Site Scripting (XSS) vulnerability in the Action View component of Ruby on Rails. Prior to versions 8.0.5.2 and 8.1.4.1, the strip_tags helper returned sanitized output marked as html_safe without encoding single or double quotation marks. When applications render the output of strip_tags inside quoted HTML attributes in ERB templates, attackers can break out of the attribute context and inject arbitrary HTML attributes or JavaScript event handlers.

Vulnerability Overview

Action View is the core Ruby on Rails framework component responsible for handling view template lookup, template rendering, and providing helpers for constructing HTML documents. Among these utilities is the SanitizeHelper module, which exposes methods such as sanitize, strip_links, and strip_tags to process untrusted user input before rendering it within application views.

A Cross-Site Scripting (XSS) vulnerability, tracked as CVE-2026-126070 (and GHSA-rq8q-p985-fjq7), exists in the strip_tags helper method in Ruby on Rails versions prior to 8.0.5.2 and 8.1.4.1. This flaw is classified under CWE-79 (Improper Neutralization of Input During Web Page Generation). The vulnerability stems from a discrepancy between the character encoding performed by the underlying HTML sanitizer and the safety guarantees expected of strings marked as html_safe in Rails.

When strip_tags processes a string, it removes HTML elements and encodes ampersands (&), less-than signs (<), and greater-than signs (>). However, it leaves single quotes (') and double quotes (") unencoded while marking the returned string as html_safe. Because the Rails ERB template engine bypasses automatic entity escaping for html_safe strings, interpolating the output of strip_tags directly inside a quoted HTML attribute allows untrusted input to prematurely close the attribute delimiter.

An attacker who controls input passed through strip_tags and rendered inside an HTML attribute (such as <meta content="...">, <input value="...">, or <div title="...">) can inject arbitrary HTML attributes, including inline JavaScript event handlers like onfocus or onmouseover. When triggered in a victim's browser, this results in arbitrary JavaScript execution within the context of the vulnerable application's origin.

Root Cause Analysis

To understand the root cause of CVE-2026-126070, it is necessary to examine how Ruby on Rails manages output safety during template compilation. Rails utilizes the ActiveSupport::SafeBuffer class (instantiated by calling .html_safe on a standard Ruby String) to distinguish between raw untrusted strings and strings that have already been sanitized or escaped. When an ERB template evaluates an expression using <%= ... %>, Rails inspects the return value: standard strings undergo full HTML entity escaping via ERB::Util.html_escape, whereas SafeBuffer instances are concatenated directly into the output buffer without further modification.

In Rails convention, any string marked as html_safe that is intended for general text interpolation must neutralize all five HTML-significant characters: &, <, >, ", and '. Neutralizing < and > prevents tag injection in element body contexts, while neutralizing " and ' prevents attribute breakout when the string is interpolated inside single- or double-quoted HTML attribute values.

Prior to the patch, ActionView::Helpers::SanitizeHelper#strip_tags delegated sanitization to rails-html-sanitizer via self.class.full_sanitizer.sanitize(html) and immediately invoked &.html_safe on the result. The full_sanitizer (backed by Loofah and Nokogiri) parses the input as an HTML fragment, strips all element nodes, and serializes the remaining text nodes. During text node serialization, Nokogiri/Loofah encodes &, <, and > into &amp;, &lt;, and &gt; respectively, as required by the HTML specification for element content. Because quotation marks are completely valid inside HTML text nodes, the serializer leaves " and ' as literal characters.

By unconditionally appending .html_safe to the output of full_sanitizer.sanitize, strip_tags promoted a string that was only safe for element content into a SafeBuffer that ERB treated as safe for all HTML contexts, including quoted attribute values. When a developer wrote <div title="<%= strip_tags(untrusted_input) %>">, ERB observed the SafeBuffer flag, skipped attribute escaping, and emitted the unescaped quotation marks directly into the rendered HTML document.

Code Analysis

The vulnerability resides in actionview/lib/action_view/helpers/sanitize_helper.rb. In vulnerable versions of Rails, strip_tags was implemented as a single-line method that called full_sanitizer.sanitize and marked any non-nil return value as html_safe.

# Vulnerable implementation in actionview/lib/action_view/helpers/sanitize_helper.rb
def strip_tags(html)
  self.class.full_sanitizer.sanitize(html)&.html_safe
end

In commits 568b19cb860322885593e308a7f27aceb779e9d7 and c3772a10f405f9644125cbb484adfd2aa7a25a59, the Rails core team modified strip_tags to pass the sanitized string through ERB::Util.html_escape_once rather than calling .html_safe directly.

diff --git a/actionview/lib/action_view/helpers/sanitize_helper.rb b/actionview/lib/action_view/helpers/sanitize_helper.rb
--- a/actionview/lib/action_view/helpers/sanitize_helper.rb
+++ b/actionview/lib/action_view/helpers/sanitize_helper.rb
@@ -1,5 +1,6 @@
 # frozen_string_literal: true
 
+require "active_support/core_ext/string/output_safety"
 require "rails-html-sanitizer"
 
 module ActionView
@@ -33,6 +34,9 @@ module SanitizeHelper
       # Please note that sanitizing user-provided text does not guarantee that the
       # resulting markup is valid or even well-formed.
       #
+      # The output is markup, which is safe only as element content. Do not use it in an attribute
+      # value; use +strip_tags+ or a tag helper such as <tt>tag.a(title: ...)</tt> instead.
+      #
       # ==== Options
       #
       # [+:tags+]
@@ -137,7 +141,8 @@ def sanitize_css(style)
       #   strip_tags("> A quote from Smith & Wesson")
       #   # => &gt; A quote from Smith &amp; Wesson
       def strip_tags(html)
-        self.class.full_sanitizer.sanitize(html)&.html_safe
+        stripped = self.class.full_sanitizer.sanitize(html)
+        ERB::Util.html_escape_once(stripped) if stripped
       end

The replacement of &.html_safe with ERB::Util.html_escape_once(stripped) resolves the issue through two specific mechanisms:

  1. Complete Character Encoding: html_escape_once converts " to &quot; and ' to &#39; while also ensuring &, <, and > are encoded. Because full_sanitizer.sanitize already converts &, <, and > into &amp;, &lt;, and &gt;, using html_escape_once (instead of standard html_escape) prevents double-encoding existing HTML entities (e.g., avoiding &amp;amp;).
  2. SafeBuffer Return Type: ERB::Util.html_escape_once returns an ActiveSupport::SafeBuffer instance, preserving backward compatibility with callers that expect strip_tags to return an html_safe string.

Fix Completeness and Variant Analysis: The patch also updates the documentation for the sibling sanitize helper to explicitly warn developers that sanitize returns markup intended strictly for element content and must not be placed inside HTML attributes. Because sanitize intentionally allows HTML tags and attributes through an allowlist, encoding quotes across its entire return string would break allowed HTML tag attributes. Furthermore, strip_tags remains unsafe if placed inside an unquoted HTML attribute (e.g., <div title=<%= strip_tags(input) %>>), as whitespace characters are sufficient to break out of unquoted attributes. However, unquoted dynamic attributes violate standard HTML authoring practices regardless of the escaping function used.

Exploitation

Exploiting CVE-2026-126070 requires an application to accept untrusted input, pass that input through strip_tags, and interpolate the result directly inside a quoted HTML attribute within an ERB template. Common real-world patterns where developers use strip_tags inside attributes include populating SEO <meta> tags, tooltip title attributes, data-* attributes, or form <input value="..."> fields from user-generated rich text or Markdown summaries.

Consider a vulnerable Rails ERB template that renders user-supplied profile data or article summaries inside a <meta> tag and an <input> field:

<!-- Vulnerable ERB Template -->
<meta name="description" content="<%= strip_tags(@user.bio) %>">
<input type="text" name="headline" value="<%= strip_tags(@user.headline) %>">

Because the attacker cannot use < or > to close the enclosing tag or inject a <script> block (as full_sanitizer.sanitize strips tags and encodes angle brackets), exploitation relies on attribute injection. If the target element is an interactive form control such as <input>, the attacker can supply the following payload for @user.headline:

x" onfocus="alert(document.domain)" autofocus="

When strip_tags executes on this payload, full_sanitizer detects no HTML tags or angle brackets and returns the string unmodified, marked as html_safe. ERB inserts the string directly into the value attribute:

<input type="text" name="headline" value="x" onfocus="alert(document.domain)" autofocus="">

When the page loads in the victim's browser, the autofocus attribute immediately directs browser focus to the <input> element, firing the onfocus event handler and executing the attacker's JavaScript without requiring direct user clicks.

If the target element is non-interactive by default (such as a <div> with a title attribute) or a hidden element that can be styled to become visible and interactive, the attacker can combine inline style attributes with mouse event handlers:

x" onmouseover="alert(document.domain)" style="position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999;" x="

When rendered inside <div title="<%= strip_tags(input) %>">, this payload breaks out of the title attribute, overlays the element across the entire browser viewport using fixed CSS positioning, and executes the onmouseover payload as soon as the user moves their cursor anywhere on the page.

Impact Assessment

CVE-2026-126070 is rated as Medium severity with a CVSS v3.1 base score of 6.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N). The attack vector is Network (AV:N) with Low attack complexity (AC:L) and requires no privileges (PR:N) in scenarios where unauthenticated input (such as search queries, public comments, or URL parameters) is reflected or stored. User Interaction is Required (UI:R), as a victim must view the rendered page or interact with the injected element. The Scope is Changed (S:C) because the vulnerability resides in the server-side web framework but executes within the security context of the client browser.

Successful exploitation grants the attacker arbitrary JavaScript execution in the victim's browser session within the origin of the vulnerable Rails application. Depending on the application's architecture and session management configuration, an attacker can:

  • Perform unauthorized actions on behalf of the authenticated user by issuing forged fetch or XMLHttpRequest calls, bypassing Cross-Site Request Forgery (CSRF) protections by reading the <meta name="csrf-token"> directly from the DOM.
  • Exfiltrate sensitive data rendered within the DOM or accessible via authenticated API endpoints.
  • Steal session identifiers or authentication tokens if they are stored in localStorage, sessionStorage, or cookies lacking the HttpOnly flag.

Applications that only render strip_tags output as standard HTML element content (e.g., <p><%= strip_tags(user_input) %></p>) are not affected, because < and > were already properly encoded into &lt; and &gt; by the sanitizer. Furthermore, applications that pass strip_tags output into Rails tag builder helpers (such as tag.div(title: strip_tags(input)) or content_tag) are confirmably unaffected or have reduced exposure depending on how attribute hashes are escaped.

According to threat intelligence data, CVE-2026-126070 has an EPSS score of 0.00269 (19.25th percentile), indicating a low probability of widespread automated exploitation within 30 days. The vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and no weaponized exploits or mass-scanning templates have been observed in the wild.

Remediation

To remediate CVE-2026-126070, upgrade Ruby on Rails (rails / actionview gems) to a patched release that encodes quotation marks in strip_tags output:

  • For Rails 8.0.x, upgrade to 8.0.5.2 or later.
  • For Rails 8.1.x, upgrade to 8.1.4.1 or later.

Update the Gemfile to specify the patched version and run bundle update rails:

# Gemfile
gem "rails", "~> 8.1.4", ">= 8.1.4.1"
# or for the 8.0 branch:
gem "rails", "~> 8.0.5", ">= 8.0.5.2"

> [!NOTE] > Behavioral Change in Non-HTML Contexts: Because strip_tags now encodes " and ' as &quot; and &#39;, applications that use strip_tags to clean strings for non-HTML outputs—such as plain-text emails, JSON API payloads, or CSV exports—will now see HTML entity strings where literal quotation marks previously appeared. If plain text is required after stripping tags, wrap the call in CGI.unescapeHTML(strip_tags(input)) and ensure the resulting plain string is not marked html_safe.

If an immediate framework upgrade is not feasible, apply one of the following code-level mitigations in ERB templates:

  1. Explicitly call html_escape_once when interpolating inside HTML attributes:

    <meta name="description" content="<%= html_escape_once(strip_tags(user_input)) %>">
    <div title="<%= html_escape_once(strip_tags(user_input)) %>">Content</div>
  2. Use Rails tag helpers instead of raw HTML attribute interpolation:

    <%= tag.meta(name: "description", content: html_escape_once(strip_tags(user_input))) %>
  3. Audit for unquoted attributes and improper sanitize usage: Ensure all HTML attributes containing dynamic content are enclosed in single or double quotes, and verify that the output of sanitize(...) (which permits HTML markup) is never interpolated inside an HTML attribute value.

Official Patches

Ruby on RailsGitHub Security Advisory GHSA-rq8q-p985-fjq7
Ruby on RailsRuby on Rails v8.0.5.2 Release
Ruby on RailsRuby on Rails v8.1.4.1 Release

Fix Analysis (2)

Technical Appendix

CVSS Score
6.1/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
EPSS Probability
0.27%
Top 81% most exploited

Affected Systems

Ruby on Rails (Action View)

Affected Versions Detail

Product
Affected Versions
Fixed Version
rails (actionview)
Ruby on Rails
< 8.0.5.28.0.5.2
rails (actionview)
Ruby on Rails
>= 8.1.0, < 8.1.4.18.1.4.1
AttributeDetail
CVE IDCVE-2026-126070 (GHSA-rq8q-p985-fjq7)
Vulnerability ClassCWE-79: Cross-Site Scripting (XSS)
Affected ComponentAction View (ActionView::Helpers::SanitizeHelper#strip_tags)
CVSS v3.1 Score6.1 Medium (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)
EPSS Score0.27% (19.25th Percentile)
Exploit StatusPoC Confirmed in Unit Tests (Not in CISA KEV)
Patched VersionsRails 8.0.5.2, Rails 8.1.4.1

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.

Vulnerability Timeline

Initial patch developed and committed to the Rails repository
2026-03-23
Rails release preparation for versions 8.1.4.1 and 8.0.5.2
2026-11-03
Security Advisory GHSA-rq8q-p985-fjq7 and CVE-2026-126070 published by GitHub CNA and NVD
2026-11-10
EPSS score registered at 0.00269 (19.25th percentile)
2026-11-12

References & Sources

  • [1]GitHub Security Advisory: GHSA-rq8q-p985-fjq7
  • [2]Fix Commit 568b19cb860322885593e308a7f27aceb779e9d7
  • [3]Backport Commit c3772a10f405f9644125cbb484adfd2aa7a25a59
  • [4]Ruby on Rails Release v8.0.5.2
  • [5]Ruby on Rails Release v8.1.4.1
  • [6]NVD - CVE-2026-126070
  • [7]CVE.org Record - CVE-2026-126070

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-126078
6.1

CVE-2026-126078: Cross-Site Scripting in Ruby on Rails Action View highlight Helper

CVE-2026-126078 is a Cross-Site Scripting (XSS) vulnerability classified under CWE-79 affecting the Action View component of Ruby on Rails in versions prior to 8.0.5.2 and 8.1.4.1. The vulnerability resides in the ActionView::Helpers::TextHelper#highlight method when invoked with a custom :highlighter template that places capture group placeholders inside HTML attribute values. Because matched substrings are substituted without HTML escaping after initial sanitization preserves literal quotation marks, an attacker controlling the input text or target search phrase can break out of the surrounding attribute delimiter and inject arbitrary HTML attributes or JavaScript event handlers.

Amit Schendel
Amit Schendel
2 views•9 min read
•about 3 hours ago•CVE-2026-126077
6.8

CVE-2026-126077: Session Information Leak in Ruby on Rails Action Pack and Active Storage Proxy Mode

An information exposure vulnerability in Ruby on Rails Action Pack allows sensitive session cookies to be attached to public, cacheable responses served by Active Storage proxy controllers. When cookie secret rotation or a hybrid cookie serializer migration is enabled, reading a legacy-format cookie triggers an automatic cookie rewrite that ignores the session-skipping directive. If an intermediate shared cache or CDN caches the resulting response along with its Set-Cookie header, subsequent users requesting the same URL receive the leaked session token.

Amit Schendel
Amit Schendel
3 views•11 min read
•about 4 hours ago•CVE-2026-126072
5.9

CVE-2026-126072: Thread Deadlock and Denial of Service in Ruby on Rails ActionController::Live

CVE-2026-126072 (GHSA-rwvh-fw6r-pwvp) is a concurrency deadlock vulnerability in the Ruby on Rails Action Pack framework affecting applications that utilize ActionController::Live response streaming. The defect occurs due to improper synchronization within ActionController::Live::Buffer when handling full bounded queues during stream closure and connection abortion. An unauthenticated remote attacker can trigger this condition by stalling TCP socket reads on streaming endpoints—including Active Storage proxy mode—resulting in permanent worker thread exhaustion and application-wide denial of service.

Amit Schendel
Amit Schendel
3 views•10 min read
•about 5 hours ago•CVE-2026-126192
6.3

CVE-2026-126192: Quadratic Algorithmic Complexity Denial of Service in Soup Sieve CSS Selector Engine

CVE-2026-126192 is an algorithmic complexity vulnerability in Soup Sieve (soupsieve), the default CSS selector engine for Beautiful Soup 4 in Python. Evaluating a CSS selector that contains a general sibling combinator (~) nested inside a :has() relational pseudo-class against attacker-controlled HTML markup triggers O(n^2) quadratic evaluation complexity when the right-hand sibling target is absent. An unauthenticated attacker can supply small HTML documents containing thousands of sibling elements to exhaust CPU resources and stall application worker threads.

Alon Barad
Alon Barad
2 views•10 min read
•about 6 hours ago•CVE-2026-126190
7.5

CVE-2026-126190: Polynomial-Time Denial of Service in Soup Sieve CSS Descendant Combinator

CVE-2026-126190 (GHSA-mmhr-3c5m-f64f) is an inefficient algorithmic complexity vulnerability (CWE-407) in Soup Sieve, the default CSS selector library integrated into Beautiful Soup 4. In versions prior to 4.0, evaluating CSS selectors that contain descendant combinators (whitespace between compound selectors) executes an unmemoized upward traversal of the document tree. When evaluated against deeply nested HTML or XML documents, the time complexity scales polynomially at O(n^(k+1)), where n is the tree depth and k is the number of descendant combinators. Remote attackers can supply compact, deeply nested markup (1 KB to 4 KB) to trigger prolonged CPU starvation and denial of service in Python applications.

Amit Schendel
Amit Schendel
3 views•9 min read
•about 7 hours ago•CVE-2026-122006
9.8

CVE-2026-122006: Unauthenticated Arbitrary File Read and Write in Ruby on Rails Active Storage via ImageMagick

CVE-2026-122006 is a critical vulnerability in the Ruby on Rails Active Storage framework affecting versions prior to 8.0.5.2 and 8.1.4.1. When an application processes uploaded file attachments using the ImageMagick variant processor (:mini_magick), the framework invokes ImageMagick's metadata analyzer without applying a restrictive security policy. An unauthenticated attacker can upload a crafted file containing directives for unrestricted ImageMagick coders, such as Magick Scripting Language (MSL), resulting in arbitrary server-side file read and write operations. In deployments using the Disk storage service, attackers can exfiltrate sensitive application configuration files, including secret_key_base and master encryption keys, which enables remote code execution via signed payload forgery.

Alon Barad
Alon Barad
3 views•10 min read