Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-44587

CVE-2026-44587: CarrierWave XSS Vulnerability

CVE-2026-44587 is an XSS vulnerability in CarrierWave file upload framework caused by improper regex handling in content type denylists. Attackers can bypass protections to upload malicious SVG files. This article covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-44587 Overview

CVE-2026-44587 is a stored Cross-Site Scripting (XSS) vulnerability [CWE-79] in CarrierWave, a widely used Ruby file upload framework. The flaw resides in the content_type_denylist check, which fails to escape regex metacharacters when building its matching pattern. As a result, denylist entries like image/svg+xml are compiled into regular expressions where + is interpreted as a quantifier rather than a literal character, so the denylist silently fails to block the intended MIME types. Applications that rely on this control to block SVG uploads remain unprotected, allowing an attacker to upload an SVG containing JavaScript and trigger stored XSS when the file is served inline. The issue affects CarrierWave versions prior to 2.2.7 and 3.1.3.

Critical Impact

Applications relying on content_type_denylist to block image/svg+xml or application/xhtml+xml are silently unprotected, enabling stored XSS through malicious SVG uploads served from the application's origin.

Affected Products

  • CarrierWave (Ruby gem) versions prior to 2.2.7
  • CarrierWave (Ruby gem) versions prior to 3.1.3
  • Ruby applications using content_type_denylist to block MIME types containing regex metacharacters

Discovery Timeline

  • 2026-06-17 - CVE-2026-44587 published to NVD
  • 2026-06-18 - Last updated in NVD database

Technical Details for CVE-2026-44587

Vulnerability Analysis

The vulnerability stems from unsafe regex interpolation in lib/carrierwave/uploader/content_type_denylist.rb. Denylist entries are inserted directly into a regular expression without applying Regexp.quote or anchoring with \A. When the entry image/svg+xml is interpolated, Ruby compiles it into /image\/svg+xml/, where + acts as a quantifier matching one or more g characters. The actual MIME type string image/svg+xml never matches that pattern, so the denylist returns false for content it is intended to block.

This behavior is inconsistent with the corresponding allowlist implementation, which correctly applies both Regexp.quote and the \A anchor. Any MIME type containing regex metacharacters such as +, ., or * is affected, including application/xhtml+xml.

Root Cause

The root cause is missing input sanitization on denylist entries before they are compiled into a regex. Without Regexp.quote, special characters in MIME type strings change the semantics of the matching pattern, producing silent matching failures rather than visible errors.

Attack Vector

An attacker uploads an SVG file containing a <script> element or inline event handler. Because the denylist fails to block image/svg+xml, the upload succeeds. When the application later serves the file inline from its own origin, the browser parses it as XML and executes the embedded JavaScript in the victim's session context, producing stored XSS. User interaction is required to trigger the payload by viewing the uploaded asset.

ruby
# Patch from lib/carrierwave/uploader/content_type_denylist.rb
      end

      def denylisted_content_type?(denylist, content_type)
-        Array(denylist).any? { |item| content_type =~ /#{item}/ }
+        Array(denylist).any? do |item|
+          item = Regexp.quote(item) if item.class != Regexp
+          content_type =~ /#{item}/
+        end
      end

    end # ContentTypeDenylist

Source: CarrierWave commit 21221cc6

The fix applies Regexp.quote to non-Regexp denylist items so metacharacters are treated as literals. An equivalent patch was applied to the legacy content_type_blacklist.rb path in commit 4c4a0057.

Detection Methods for CVE-2026-44587

Indicators of Compromise

  • Uploaded files with Content-Type: image/svg+xml containing <script> tags, on* event handlers, or javascript: URIs
  • SVG files with embedded <foreignObject> or external xlink:href references pointing to attacker domains
  • Outbound requests from end-user browsers to unexpected origins immediately after rendering a stored asset

Detection Strategies

  • Scan application dependency manifests (Gemfile.lock) for CarrierWave versions earlier than 2.2.7 or 3.1.3
  • Inspect uploader classes for use of content_type_denylist with entries containing regex metacharacters (+, ., *, ?)
  • Parse stored upload payloads for SVG content containing scriptable elements before they are served inline

Monitoring Recommendations

  • Log and review HTTP responses serving user-uploaded SVG content from the application origin
  • Alert on file uploads where the declared MIME type or file signature corresponds to SVG or XHTML
  • Correlate upload events with subsequent file retrieval and Content Security Policy (CSP) violation reports

How to Mitigate CVE-2026-44587

Immediate Actions Required

  • Upgrade CarrierWave to version 2.2.7 (2.x branch) or 3.1.3 (3.x branch)
  • Switch to content_type_allowlist with an explicit list of safe MIME types instead of relying on a denylist
  • Serve user-uploaded files from a separate, sandboxed origin or with Content-Disposition: attachment to prevent inline script execution
  • Audit existing stored uploads for SVG files containing executable script content

Patch Information

The issue was fixed in CarrierWave 2.2.7 and 3.1.3. The corrective change applies Regexp.quote to each non-Regexp denylist entry before interpolation, ensuring metacharacters are matched literally. Reference the GHSA-7g26-2qgj-chfg advisory for full vendor guidance.

Workarounds

  • Replace denylist entries containing metacharacters with pre-quoted Regexp objects, for example Regexp.new(Regexp.quote('image/svg+xml'))
  • Enforce a strict Content Security Policy that disables inline scripts on responses that serve user-generated content
  • Strip or sanitize SVG payloads server-side before storage using a vetted XML sanitizer
bash
# Update CarrierWave in your Gemfile and refresh the lockfile
bundle update carrierwave

# Or pin a fixed version explicitly
# Gemfile
# gem 'carrierwave', '>= 3.1.3'
# gem 'carrierwave', '~> 2.2.7'  # for 2.x users

bundle install

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.