CarrierWave has a content-type allowlist bypass vulnerability, possibly leading to XSS
Description
CarrierWave is a solution for file uploads for Rails, Sinatra and other Ruby web frameworks. CarrierWave has a Content-Type allowlist bypass vulnerability, possibly leading to XSS. The validation in allowlisted_content_type? determines Content-Type permissions by performing a partial match. If the content_type argument of allowlisted_content_type? is passed a value crafted by the attacker, Content-Types not included in the content_type_allowlist will be allowed. This issue has been patched in versions 2.2.5 and 3.0.5.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
carrierwaveRubyGems | >= 3.0.0, < 3.0.5 | 3.0.5 |
carrierwaveRubyGems | < 2.2.5 | 2.2.5 |
Affected products
1- Range: >= 2.2.0, < 2.2.5
Patches
2863d425c76ebFix Content-Type allowlist bypass vulnerability
2 files changed · +28 −1
lib/carrierwave/uploader/content_type_allowlist.rb+1 −1 modified@@ -53,7 +53,7 @@ def check_content_type_allowlist!(new_file) def allowlisted_content_type?(allowlist, content_type) Array(allowlist).any? do |item| item = Regexp.quote(item) if item.class != Regexp - content_type =~ /#{item}/ + content_type =~ /\A#{item}/ end end
spec/uploader/content_type_allowlist_spec.rb+27 −0 modified@@ -76,6 +76,33 @@ expect { uploader.cache!(ruby_file) }.not_to raise_error end end + + context "with a crafted content type" do + before do + allow(bork_file).to receive(:content_type).and_return('text/plain; image/png') + allow(uploader).to receive(:content_type_allowlist).and_return('image/png') + end + + it "does not allow spoofing" do + expect { uploader.cache!(bork_file) }.to raise_error(CarrierWave::IntegrityError) + end + end + + context "when the allowlist contains charset" do + before do + allow(uploader).to receive(:content_type_allowlist).and_return(%r{text/plain;\s*charset=utf-8}) + end + + it "accepts the content with allowed charset" do + allow(bork_file).to receive(:content_type).and_return('text/plain; charset=utf-8') + expect { uploader.cache!(bork_file) }.not_to raise_error + end + + it "rejects the content without charset" do + allow(bork_file).to receive(:content_type).and_return('text/plain') + expect { uploader.cache!(bork_file) }.to raise_error(CarrierWave::IntegrityError) + end + end end context "when there is a whitelist" do
39b282db5c13Fix Content-Type allowlist bypass vulnerability
2 files changed · +28 −1
lib/carrierwave/uploader/content_type_whitelist.rb+1 −1 modified@@ -51,7 +51,7 @@ def check_content_type_whitelist!(new_file) def whitelisted_content_type?(content_type) Array(content_type_allowlist).any? do |item| item = Regexp.quote(item) if item.class != Regexp - content_type =~ /#{item}/ + content_type =~ /\A#{item}/ end end
spec/uploader/content_type_whitelist_spec.rb+27 −0 modified@@ -76,6 +76,33 @@ expect { uploader.cache!(ruby_file) }.not_to raise_error end end + + context "with a crafted content type" do + before do + allow(bork_file).to receive(:content_type).and_return('text/plain; image/png') + allow(uploader).to receive(:content_type_allowlist).and_return('image/png') + end + + it "does not allow spoofing" do + expect { uploader.cache!(bork_file) }.to raise_error(CarrierWave::IntegrityError) + end + end + + context "when the allowlist contains charset" do + before do + allow(uploader).to receive(:content_type_allowlist).and_return(%r{text/plain;\s*charset=utf-8}) + end + + it "accepts the content with allowed charset" do + allow(bork_file).to receive(:content_type).and_return('text/plain; charset=utf-8') + expect { uploader.cache!(bork_file) }.not_to raise_error + end + + it "rejects the content without charset" do + allow(bork_file).to receive(:content_type).and_return('text/plain') + expect { uploader.cache!(bork_file) }.to raise_error(CarrierWave::IntegrityError) + end + end end context "when there is a whitelist" do
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-gxhx-g4fq-49hjghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-49090ghsaADVISORY
- github.com/carrierwaveuploader/carrierwave/blob/master/lib/carrierwave/uploader/content_type_allowlist.rbghsaWEB
- github.com/carrierwaveuploader/carrierwave/commit/39b282db5c1303899b3d3381ce8a837840f983b5ghsax_refsource_MISCWEB
- github.com/carrierwaveuploader/carrierwave/commit/863d425c76eba12c3294227b39018f6b2dccbbf3ghsax_refsource_MISCWEB
- github.com/carrierwaveuploader/carrierwave/security/advisories/GHSA-gxhx-g4fq-49hjghsax_refsource_CONFIRMWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/carrierwave/CVE-2023-49090.ymlghsaWEB
- rubygems.org/gems/carrierwave/versions/2.2.5ghsaWEB
- rubygems.org/gems/carrierwave/versions/3.0.5ghsaWEB
News mentions
0No linked articles in our index yet.