I. Understanding the problem

If you have ever used paperclip, maybe you have seen the message like that: Image has contents that are not what they are reported to be.

For this bug, we will have two solutions:

  • Specify an extension that cannot otherwise be mapped:
Paperclip.options[:content_type_mappings] = {
  pem: "text/plain"
}
  • Override media_type_spoof_detector method:
require 'paperclip/media_type_spoof_detector'
module Paperclip
  class MediaTypeSpoofDetector
    def spoofed?
      false
    end
  end
end

The second solution is very bad. Why? The monkey-patching will ignore check type of uploading file, if an attacker put an entire HTML page into the EXIF tag of a completely valid JPEG and named the file “gotcha.html,” they could potentially trick users into an XSS vulnerability.

II. How do paperclip determine Content Type Spoofing

Paperclip uses media_type_spoof_detector to determine content type spoofing.

def spoofed?
  if has_name? && has_extension? && media_type_mismatch? && mapping_override_mismatch?
    Paperclip.log("Content Type Spoof: Filename #{File.basename(@name)} (#{supplied_content_type} from Headers, #{content_types_from_name.map(&:to_s)} from Extension), content type discovered from file command: #{calculated_content_type}. See documentation to allow this combination.")
    true
  else
    false
  end
end

FULL CODE

  1. has_name?: check file name exists
  2. has_extension?: check file extension exists
  3. media_type_mismatch?: did content type include defined list by file name?
  4. mapping_override_mismatch?: content type discovered from file command
file -b --mime '/var/folders/w1/jljslm493yd9gfvbddn4ghp80000gn/T/224e20c3e580e19e06486bc62811c72d20161002-13093-q2f599.png'

Note: You should use code from verified source. Otherwise, you should try to understand what the code will do.