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-33167
1.3

CVE-2026-33167: Cross-Site Scripting (XSS) in Ruby on Rails Action Pack Debug Exceptions

Amit Schendel
Amit Schendel
Senior Security Researcher

Mar 23, 2026·6 min read·7 visits

PoC Available

Executive Summary (TL;DR)

Ruby on Rails Action Pack versions 8.1.0 through 8.1.2 contain a Cross-Site Scripting vulnerability in the debug exceptions page. Attackers can execute arbitrary JavaScript by reflecting crafted input into an unhandled exception message.

Action Pack is a Rubygem for building web applications on the Rails framework. In versions on the 8.1 branch prior to 8.1.2.1, the debug exceptions page does not properly escape exception messages. A carefully crafted exception message could inject arbitrary HTML and JavaScript into the page, leading to Cross-Site Scripting (XSS). This affects applications with detailed exception pages enabled, which is the default in development environments.

Vulnerability Overview

Action Pack is a core component of the Ruby on Rails framework responsible for handling web requests and responses. Within this gem, the debug exceptions middleware intercepts unhandled application errors and generates a diagnostic HTML page. This page provides developers with stack traces, request parameters, and environment variables to facilitate debugging.

In Rails versions 8.1.0 through 8.1.2, this middleware introduces a Cross-Site Scripting (XSS) vulnerability classified under CWE-79. The flaw resides in a specific feature designed to allow developers to copy exception messages to their clipboard. The template rendering this feature fails to adequately neutralize user-controlled input before reflecting it into the HTML document.

If an attacker can manipulate the application into throwing an exception containing crafted HTML payloads, the debug page will execute arbitrary JavaScript within the context of the application's origin. This vulnerability primarily affects applications running with config.consider_all_requests_local = true, which is the default behavior in development environments but strictly discouraged in production deployments.

Root Cause Analysis

The vulnerability stems from improper output encoding within the Action Pack debug exceptions middleware template. Specifically, the framework utilizes the layout.erb file to construct the structure of the diagnostic error page. To support the copy-to-clipboard functionality, the template embeds the raw exception message inside a hidden HTML <script> block.

The precise defect occurs where the raw helper is applied to the @exception_message_for_copy instance variable. By invoking raw, the framework explicitly bypasses the default HTML escaping mechanisms provided by ERB templates. The template wraps this raw output in a script tag defined as <script type="text/plain" id="exception-message-for-copy">.

Although the script tag specifies type="text/plain", standard browser HTML parsers do not evaluate the internal content to find the closing boundary. Instead, the parser scans the raw byte stream for the literal </script> sequence. When an exception message contains this sequence, the parser immediately terminates the text block, allowing any subsequent content to be parsed as executable HTML or JavaScript.

Code Analysis

The patch provided in commit 6752711c8c31d79ba50d13af6a6698a3b85415e0 addresses the root cause by removing the explicit bypass of HTML escaping. In the vulnerable implementation, the layout.erb file explicitly commanded the rendering engine to emit unencoded output.

-  <script type="text/plain" id="exception-message-for-copy"><%= raw @exception_message_for_copy %></script>
+  <script type="text/plain" id="exception-message-for-copy"><%= @exception_message_for_copy %></script>

By removing the raw helper, the ERB engine falls back to its secure default behavior of HTML-encoding all dynamic output. Characters such as <, >, and & are automatically converted into their corresponding HTML entities (&lt;, &gt;, &amp;). This transformation prevents the browser parser from recognizing the injected </script> tag.

The framework maintainers also introduced a regression test in actionpack/test/dispatch/debug_exceptions_test.rb to verify the fix. The test generates an exception containing a malicious payload and asserts that the resulting response body contains the safely encoded string &lt;script&gt;alert(1)&lt;/script&gt; rather than the executable raw payload.

Exploitation Methodology

Exploitation requires the attacker to identify an application endpoint that incorporates user-controlled input into an unhandled exception message. Attackers typically target endpoints that process parameters, headers, or URL fragments in ways that trigger framework-level or application-level errors. Common triggers include submitting malformed data types, triggering ActionController::BadRequest, or violating database constraints where the input is reflected in the error output.

Once a suitable endpoint is identified, the attacker crafts a payload designed to break out of the target script block. The payload must begin with </script> to terminate the text/plain container. This is followed by a new, executable script block containing the malicious JavaScript, such as <script>alert(document.domain)</script>.

When the framework processes the request, the unhandled exception propagates to the debug exceptions middleware. The middleware renders the layout.erb template, embedding the raw payload into the document. The victim's browser parses the document, incorrectly closes the initial script block upon encountering the injected </script> string, and executes the attacker's script in the context of the application origin.

Impact Assessment

The security impact of CVE-2026-33167 is context-dependent, directly correlating with the environment configuration of the target application. In development environments, successful exploitation allows attackers to execute arbitrary JavaScript in the developer's browser session. This access facilitates the theft of session tokens, access to local development credentials, or pivoting into internal development networks.

The CVSS v4.0 score of 1.3 accurately reflects the low severity for standard production environments. The prerequisite condition, config.consider_all_requests_local = true, is inherently disabled in production configurations by default. Exploitation against a production system strictly requires a severe misconfiguration where developers have explicitly overridden this safety default.

If successfully exploited in a misconfigured production environment, the vulnerability constitutes a complete compromise of the client-side session. Attackers can perform actions on behalf of the victim, exfiltrate sensitive data rendered in the browser, or interact with backend APIs using the victim's authentication context. The lack of interaction requirements beyond navigating to the crafted URL increases the viability of targeted phishing campaigns.

Remediation and Mitigation

The primary remediation strategy requires updating the rails gem dependency to version 8.1.2.1 or later. This patch fundamentally eliminates the vulnerability by enforcing correct output encoding within the diagnostic template. Development teams must ensure all components of the Rails framework, specifically actionpack, are updated uniformly to maintain compatibility and security.

In environments where immediate patching is not feasible, administrators must verify their configuration settings. The config.consider_all_requests_local directive must be set to false in config/environments/production.rb. Disabling this feature replaces the detailed diagnostic page with a generic HTTP 500 error, removing the vulnerable code path entirely from external access.

Organizations utilizing Web Application Firewalls (WAF) can implement supplementary detection rules to block common XSS patterns. Rules targeting the literal string </script> within request parameters, headers, and URI structures effectively mitigate the primary exploitation vector. This defense-in-depth approach provides temporary coverage while the application dependencies undergo the update and deployment lifecycle.

Fix Analysis (1)

Technical Appendix

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

Affected Systems

Ruby on Rails Action PackRuby on Rails Web Applications

Affected Versions Detail

Product
Affected Versions
Fixed Version
rails
rails
>= 8.1.0, < 8.1.2.18.1.2.1
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS v4.0 Score1.3
Exploit StatusProof of Concept
CISA KEVNo
Authentication RequiredNone

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-79
Cross-site Scripting

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Known Exploits & Detection

Official Rails Test SuiteFunctional proof of concept within actionpack/test/dispatch/debug_exceptions_test.rb

Vulnerability Timeline

Fix commit authored by John Hawthorn.
2026-03-17
Rails 8.1.2.1 released.
2026-03-23
Security advisory published (GHSA-pgm4-439c-5jp6).
2026-03-23
CVE-2026-33167 published.
2026-03-23

References & Sources

  • [1]GitHub Advisory: GHSA-pgm4-439c-5jp6
  • [2]Fix Commit: 6752711c8c31d79ba50d13af6a6698a3b85415e0
  • [3]Rails Release Tag: v8.1.2.1
  • [4]CVE.org Record

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.