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

CVE-2026-33170: Cross-Site Scripting (XSS) via SafeBuffer State Loss in Rails Active Support

Amit Schendel
Amit Schendel
Senior Security Researcher

Mar 24, 2026·5 min read·40 visits

Executive Summary (TL;DR)

A state-tracking failure in Rails Active Support's `SafeBuffer#%` method permits Cross-Site Scripting (XSS). Destructively mutated strings lose their unsafe flag upon formatting, bypassing ERB auto-escaping and rendering malicious payloads.

CVE-2026-33170 is a Cross-Site Scripting (XSS) vulnerability within the Active Support component of Ruby on Rails. The flaw resides in the `SafeBuffer#%` formatting operator, which fails to correctly propagate internal state regarding HTML safety when creating new string instances. This oversight allows maliciously crafted, destructively mutated strings to bypass Rails' ERB auto-escaping mechanisms, potentially leading to arbitrary JavaScript execution in the context of the user's session.

Vulnerability Overview

Ruby on Rails utilizes the ActiveSupport::SafeBuffer class to differentiate between raw strings and strings that have been sanitized for HTML output. When the Rails ERB templating engine encounters a SafeBuffer object marked as safe, it bypasses the standard HTML auto-escaping process to prevent double-encoding.

The SafeBuffer class achieves this by overriding standard Ruby String methods to track whether the contents have been altered by untrusted data. When an application renders templates, the framework calls html_safe? on the output variables. If the object returns true, the framework writes the bytes directly to the response stream without applying HTML entity encoding.

This mechanism relies on strict internal state tracking to ensure that any unsafe mutation to a previously safe string properly flags the object as unsafe. Destructive string methods, such as gsub! or sub!, explicitly toggle an internal @html_unsafe boolean to prevent tainted data from rendering without escaping.

CVE-2026-33170 emerges from a failure to maintain this state during string formatting operations. The SafeBuffer#% method creates a new buffer but fails to inherit the @html_unsafe flag from the parent receiver, permitting malicious input to bypass the auto-escaping design.

Root Cause Analysis

The vulnerability stems from the implementation of the string formatting operator (%) within the ActiveSupport::SafeBuffer class. When a developer applies formatting to a SafeBuffer instance, the method intercepts the call to properly escape the provided arguments before interpolation.

After escaping the arguments, the method invokes the parent String#% method to perform the actual interpolation. The result of this interpolation is then wrapped in a completely new SafeBuffer instance to maintain the specialized class type.

Because the new instance is generated via self.class.new(), it defaults to its initial safe state. The method logic explicitly overlooks the @html_unsafe instance variable of the original receiver, failing to propagate it to the newly instantiated object. Consequently, an explicitly unsafe buffer yields a purportedly safe buffer after formatting.

Code Analysis

The vulnerable implementation of the % operator constructs the return value without assessing the receiver's state. Any existing mutation warning tracked by @html_unsafe is silently discarded during the instantiation of the new buffer. This logic oversight breaks the chain of trust established by the Active Support framework.

The patch introduced in commit 50d732af3b7c8aaf63cbcca0becbc00279b215b7 rectifies this by explicitly checking the receiver's state and propagating it. The developers added a mark_unsafe! protected helper method to allow internal state synchronization.

# Patched activesupport/lib/active_support/core_ext/string/output_safety.rb
def %(args)
  # [..] escaping logic [..]
  new_safe_buffer = self.class.new(super(escaped_args))
  if @html_unsafe
    new_safe_buffer.mark_unsafe!
  end
  new_safe_buffer
end
 
protected
  def mark_unsafe!
    @html_unsafe = true
  end

This modification guarantees that if the original buffer was marked unsafe due to prior destructive mutation, the resulting formatted buffer correctly inherits this restriction. The Rails ERB engine will subsequently enforce HTML escaping on the output, neutralizing any embedded malicious scripts.

Exploitation Mechanics

Exploiting this vulnerability requires a specific sequence of operations on user-controlled input within a Rails application. An attacker must locate an endpoint where a SafeBuffer object undergoes in-place mutation followed by string formatting.

The initial step involves supplying a malicious payload, such as <script>alert(document.cookie)</script>, to an input field. The application must then apply a destructive method, such as gsub!, to the buffer containing this input. This action correctly flags the buffer as @html_unsafe = true.

The exploitation succeeds when the application subsequently formats this buffer using the % operator. The operation strips the unsafe flag, returning a new buffer that reports html_safe? == true to the templating engine.

When the Rails view layer renders this resulting string, the ERB engine reads the erroneous safe status and skips auto-escaping. The raw JavaScript payload is embedded directly into the HTML document and executed by the victim's browser upon page load.

Impact Assessment

The successful exploitation of this vulnerability yields Cross-Site Scripting (XSS) within the context of the affected application. Because the ERB auto-escaping is fully bypassed, attackers can inject arbitrary HTML and JavaScript into the responses served to end users.

Code execution in the victim's browser enables comprehensive session hijacking, data exfiltration, and unauthorized actions performed on behalf of the user. This aligns with MITRE ATT&CK techniques T1189 (Drive-by Compromise) and T1185 (Browser Session Hijacking).

Attackers often leverage this class of vulnerability to target administrative users, executing actions with elevated privileges. Successful payload delivery requires bypassing any Web Application Firewall (WAF) rules that might detect the initial input string. Because the mutation happens server-side after ingestion, network-level inspection sees only the raw parameters, not the final rendered payload.

The severity is rated Medium (CVSS 5.3) due to the precise code prerequisites required for exploitation. The vulnerability is not a universal bypass; it strictly requires the sequence of destructive mutation followed by string formatting on a single SafeBuffer object.

Remediation and Mitigation

The primary remediation for CVE-2026-33170 is upgrading the activesupport gem to a patched version. The Rails core team has released versions 7.2.3.1, 8.0.4.1, and 8.1.2.1 to address this vulnerability across all currently supported release branches.

For applications where immediate upgrading is technically unfeasible, developers should audit their codebases for destructive string operations. Searching for methods ending in an exclamation mark (e.g., gsub!, sub!, insert) called on user-controlled data is necessary to identify vulnerable code paths.

Replacing destructive methods with their non-destructive counterparts (e.g., gsub instead of gsub!) acts as an effective workaround. Non-destructive methods correctly handle SafeBuffer state by returning entirely new, properly sanitized string objects rather than mutating existing buffers in place, preventing the specific state desynchronization required for this attack.

Official Patches

RailsGitHub Security Advisory GHSA-89vf-4333-qx8v
RailsRails v8.1.2.1 Release Notes

Fix Analysis (3)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N

Affected Systems

Ruby on Rails (activesupport component)

Affected Versions Detail

Product
Affected Versions
Fixed Version
activesupport
Rails
< 7.2.3.17.2.3.1
activesupport
Rails
>= 8.0.0.beta1, < 8.0.4.18.0.4.1
activesupport
Rails
>= 8.1.0.beta1, < 8.1.2.18.1.2.1
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS v4.05.3 (Medium)
EPSS Score0.0
Exploit StatusNone
CISA KEVNot Listed

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 fix commits authored by Jean Boussier
2026-03-04
Official vulnerability disclosure (GHSA-89vf-4333-qx8v) and release of fixed Rails versions
2026-03-23
Published to the National Vulnerability Database (NVD)
2026-03-24

References & Sources

  • [1]GitHub Advisory: GHSA-89vf-4333-qx8v
  • [2]NVD CVE Record for CVE-2026-33170
  • [3]Active Support Output Safety Source Code

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

•1 day ago•CVE-2026-58197
8.8

CVE-2026-58197: Host Escape and Lateral Movement via Insecure Container Network Defaults in ToolHive

A high-severity access control vulnerability in ToolHive CLI before v0.30.1 and ToolHive Studio before v0.38.0 allows local containerized MCP servers to bypass network isolation. This enables malicious workloads to establish TCP/IP connections to administrative and control plane endpoints exposed on the host loopback interface.

Amit Schendel
Amit Schendel
8 views•8 min read
•1 day ago•CVE-2026-63405
5.9

CVE-2026-63405: Insufficient Verification of Data Authenticity in AnyCable Pusher REST API

AnyCable is a real-time communication server. Prior to version 1.6.15, its Pusher-compatible REST API suffered from an authentication bypass vulnerability because it failed to verify that the request body matched the signature-validated body_md5 parameter. This allows attackers to perform replay attacks with modified body contents.

Amit Schendel
Amit Schendel
9 views•5 min read
•1 day ago•CVE-2026-64847
6.8

CVE-2026-64847: Indefinite Denial of Service via Undrained Stderr in AnyIO Process Pool Workers

A denial-of-service vulnerability exists in AnyIO prior to version 4.14.2. Standard error streams of process-pool workers are connected to an operating system pipe that is never drained by the parent process. This allows a worker to fill the pipe buffer and deadlock indefinitely.

Amit Schendel
Amit Schendel
8 views•6 min read
•2 days ago•CVE-2026-63349
7.0

CVE-2026-63349: Privilege Dropping Bypass and Denial of Service in AnyIO Subprocess Module

CVE-2026-63349 is a critical privilege-dropping bypass vulnerability in the AnyIO asynchronous framework (versions 4.14.0 and 4.14.1) on POSIX platforms. Due to a variable assignment typo, supplementary groups specified by the developer are not correctly propagated to the execution backend, resulting in subprocesses retaining the parent process's elevated supplementary group permissions.

Alon Barad
Alon Barad
14 views•5 min read
•2 days ago•CVE-2026-63406
5.9

CVE-2026-63406: Information Disclosure via Insecure Telemetry and Hardcoded Credentials in AnyCable-Go

CVE-2026-63406 is an information disclosure vulnerability in AnyCable-go prior to version 1.6.15. The built-in telemetry client is enabled by default with a hardcoded public authentication token ('secret'). This client digests highly sensitive configuration parameters and command-line arguments, including JWT secrets and RPC secrets, into a stable SHA-256 fingerprint. This fingerprint is sent over public networks, exposing those administrative secrets to offline dictionary and brute-force attacks if intercepted.

Alon Barad
Alon Barad
7 views•5 min read
•2 days ago•CVE-2026-84992
6.1

CVE-2026-84992: Cross-Site Scripting (XSS) via Fenced Code Block Parsing in md-editor-v3

CVE-2026-84992 is a Cross-Site Scripting (XSS) vulnerability affecting md-editor-v3 before version 6.5.4. It occurs because the fenced-code block language parser directly interpolates unescaped language metadata into unquoted HTML attributes inside the custom rendering callback. This bypasses the built-in XSSPlugin which runs during the parsing phase, before rendering.

Amit Schendel
Amit Schendel
9 views•6 min read