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.
# 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
# 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.

