2018-09-04 10:39:08 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-02-21 21:08:57 +00:00
|
|
|
# The method `filename` must be defined in classes that mix in this module.
|
2019-09-23 18:06:14 +00:00
|
|
|
#
|
|
|
|
# This module is intended to be used as a helper and not a security gate
|
|
|
|
# to validate that a file is safe, as it identifies files only by the
|
|
|
|
# file extension and not its actual contents.
|
|
|
|
#
|
|
|
|
# An example useage of this module is in `FileMarkdownLinkBuilder` that
|
|
|
|
# renders markdown depending on a file name.
|
|
|
|
#
|
|
|
|
# We use Workhorse to detect the real extension when we serve files with
|
|
|
|
# the `SendsBlob` helper methods, and ask Workhorse to set the content
|
|
|
|
# type when it serves the file:
|
2019-09-26 12:06:00 +00:00
|
|
|
# https://gitlab.com/gitlab-org/gitlab/blob/33e5955/app/helpers/workhorse_helper.rb#L48.
|
2019-09-23 18:06:14 +00:00
|
|
|
#
|
|
|
|
# Because Workhorse has access to the content when it is downloaded, if
|
|
|
|
# the type/extension doesn't match the real type, we adjust the
|
|
|
|
# `Content-Type` and `Content-Disposition` to the one we get from the detection.
|
2018-09-04 10:39:08 +00:00
|
|
|
module Gitlab
|
|
|
|
module FileTypeDetection
|
2021-01-25 15:09:00 +00:00
|
|
|
SAFE_IMAGE_EXT = %w[png jpg jpeg gif bmp tiff ico webp].freeze
|
2020-08-28 06:10:45 +00:00
|
|
|
SAFE_IMAGE_FOR_SCALING_EXT = %w[png jpg jpeg].freeze
|
|
|
|
|
2019-12-16 18:08:22 +00:00
|
|
|
PDF_EXT = 'pdf'
|
2018-09-04 10:39:08 +00:00
|
|
|
# We recommend using the .mp4 format over .mov. Videos in .mov format can
|
|
|
|
# still be used but you really need to make sure they are served with the
|
|
|
|
# proper MIME type video/mp4 and not video/quicktime or your videos won't play
|
|
|
|
# on IE >= 9.
|
|
|
|
# http://archive.sublimevideo.info/20150912/docs.sublimevideo.net/troubleshooting.html
|
2019-09-23 18:06:14 +00:00
|
|
|
SAFE_VIDEO_EXT = %w[mp4 m4v mov webm ogv].freeze
|
2019-10-09 12:06:13 +00:00
|
|
|
SAFE_AUDIO_EXT = %w[mp3 oga ogg spx wav].freeze
|
2019-09-23 18:06:14 +00:00
|
|
|
|
2018-09-04 10:39:08 +00:00
|
|
|
# These extension types can contain dangerous code and should only be embedded inline with
|
|
|
|
# proper filtering. They should always be tagged as "Content-Disposition: attachment", not "inline".
|
2019-09-23 18:06:14 +00:00
|
|
|
DANGEROUS_IMAGE_EXT = %w[svg].freeze
|
|
|
|
DANGEROUS_VIDEO_EXT = [].freeze # None, yet
|
2019-10-09 12:06:13 +00:00
|
|
|
DANGEROUS_AUDIO_EXT = [].freeze # None, yet
|
2018-09-04 10:39:08 +00:00
|
|
|
|
2020-02-21 21:08:57 +00:00
|
|
|
def self.extension_match?(filename, extensions)
|
|
|
|
return false unless filename.present?
|
|
|
|
|
|
|
|
extension = File.extname(filename).delete('.')
|
|
|
|
extensions.include?(extension.downcase)
|
|
|
|
end
|
|
|
|
|
2018-09-04 10:39:08 +00:00
|
|
|
def image?
|
2019-09-23 18:06:14 +00:00
|
|
|
extension_match?(SAFE_IMAGE_EXT)
|
2018-09-04 10:39:08 +00:00
|
|
|
end
|
|
|
|
|
2020-08-28 06:10:45 +00:00
|
|
|
# For the time being, we restrict image scaling requests to the most popular and safest formats only,
|
|
|
|
# which are JPGs and PNGs. See https://gitlab.com/gitlab-org/gitlab/-/issues/237848 for more info.
|
|
|
|
def image_safe_for_scaling?
|
|
|
|
extension_match?(SAFE_IMAGE_FOR_SCALING_EXT)
|
|
|
|
end
|
|
|
|
|
2018-09-04 10:39:08 +00:00
|
|
|
def video?
|
2019-09-23 18:06:14 +00:00
|
|
|
extension_match?(SAFE_VIDEO_EXT)
|
2018-09-04 10:39:08 +00:00
|
|
|
end
|
|
|
|
|
2019-10-09 12:06:13 +00:00
|
|
|
def audio?
|
|
|
|
extension_match?(SAFE_AUDIO_EXT)
|
|
|
|
end
|
|
|
|
|
2019-12-16 18:08:22 +00:00
|
|
|
def pdf?
|
|
|
|
extension_match?([PDF_EXT])
|
|
|
|
end
|
|
|
|
|
2019-10-09 12:06:13 +00:00
|
|
|
def embeddable?
|
|
|
|
image? || video? || audio?
|
2018-09-04 10:39:08 +00:00
|
|
|
end
|
|
|
|
|
2019-09-23 18:06:14 +00:00
|
|
|
def dangerous_image?
|
|
|
|
extension_match?(DANGEROUS_IMAGE_EXT)
|
|
|
|
end
|
|
|
|
|
|
|
|
def dangerous_video?
|
|
|
|
extension_match?(DANGEROUS_VIDEO_EXT)
|
|
|
|
end
|
|
|
|
|
2019-10-09 12:06:13 +00:00
|
|
|
def dangerous_audio?
|
|
|
|
extension_match?(DANGEROUS_AUDIO_EXT)
|
|
|
|
end
|
|
|
|
|
|
|
|
def dangerous_embeddable?
|
|
|
|
dangerous_image? || dangerous_video? || dangerous_audio?
|
2018-09-04 10:39:08 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def extension_match?(extensions)
|
2020-02-21 21:08:57 +00:00
|
|
|
::Gitlab::FileTypeDetection.extension_match?(filename, extensions)
|
2018-09-04 10:39:08 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|