CVE-2024-29034 (published 2024-03-24T20:15Z)

CarrierWave is a solution for file uploads for Rails, Sinatra and other Ruby web frameworks. The vulnerability CVE-2023-49090 wasn't fully addressed. This vulnerability is caused by the fact that when uploading to object storage, including Amazon S3, it is possible to set a Content-Type value that is interpreted by browsers to be different from what's allowed by `content_type_allowlist`, by providing multiple values separated by commas. This bypassed value can be used to cause XSS. Upgrade to 3.0.7 or 2.2.6.\n


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/carrierwaveuploader/carrierwave
commit_details: repo_url: https://github.com/carrierwaveuploader/carrierwave
author: Mitsuhiro Shibuya
author_date: 2024-03-20 14:10:19+09:00
msg: Fix Content-Type allowlist bypass vulnerability remained

Refs. https://github.com/carrierwaveuploader/carrierwave/security/advisories/GHSA-vfmv-jfc5-pjjw
repository: repo_url: https://github.com/carrierwaveuploader/carrierwave
repo_name: carrierwaveuploader/carrierwave
description: Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks
repo_language: Ruby
owner: carrierwaveuploader
file_changes: filename: sanitized_file.rb
change_type: ModificationType.MODIFY
diff: @@ -307,7 +307,7 @@ module CarrierWave
     def declared_content_type
       @declared_content_type ||
         if @file.respond_to?(:content_type) && @file.content_type
-          @file.content_type.to_s.chomp
+          Marcel::MimeType.for(declared_type: @file.content_type.to_s.chomp)
         end
     end
 

programming_language: Ruby
filename: sanitized_file_spec.rb
change_type: ModificationType.MODIFY
diff: @@ -326,6 +326,33 @@ describe CarrierWave::SanitizedFile do
 
       expect { sanitized_file.content_type }.not_to raise_error
     end
+
+    it "uses the first one when multiple mime types are given using a semicolon" do
+      file = File.open(file_path("bork.txt"))
+      allow(file).to receive(:content_type) { 'image/png; text/html' }
+
+      sanitized_file = CarrierWave::SanitizedFile.new(file)
+
+      expect(sanitized_file.content_type).to eq("image/png")
+    end
+
+    it "uses the first one when multiple mime types are given using a comma" do
+      file = File.open(file_path("bork.txt"))
+      allow(file).to receive(:content_type) { 'image/png, text/html' }
+
+      sanitized_file = CarrierWave::SanitizedFile.new(file)
+
+      expect(sanitized_file.content_type).to eq("image/png")
+    end
+
+    it "drops content type parameters" do
+      file = File.open(file_path("bork.txt"))
+      allow(file).to receive(:content_type) { 'text/html; charset=utf-8' }
+
+      sanitized_file = CarrierWave::SanitizedFile.new(file)
+
+      expect(sanitized_file.content_type).to eq("text/html")
+    end
   end
 
   describe "#content_type=" do

programming_language: Ruby
filename: content_type_allowlist_spec.rb
change_type: ModificationType.MODIFY
diff: @@ -87,22 +87,6 @@ describe CarrierWave::Uploader 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

programming_language: Ruby