Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/hotlinking_detector.rb')
-rw-r--r--lib/gitlab/hotlinking_detector.rb52
1 files changed, 52 insertions, 0 deletions
diff --git a/lib/gitlab/hotlinking_detector.rb b/lib/gitlab/hotlinking_detector.rb
new file mode 100644
index 00000000000..44901297870
--- /dev/null
+++ b/lib/gitlab/hotlinking_detector.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class HotlinkingDetector
+ IMAGE_FORMATS = %w(image/jpeg image/apng image/png image/webp image/svg+xml image/*).freeze
+ MEDIA_FORMATS = %w(video/webm video/ogg video/* application/ogg audio/webm audio/ogg audio/wav audio/*).freeze
+ CSS_FORMATS = %w(text/css).freeze
+ INVALID_FORMATS = (IMAGE_FORMATS + MEDIA_FORMATS + CSS_FORMATS).freeze
+ INVALID_FETCH_MODES = %w(cors no-cors websocket).freeze
+
+ class << self
+ def intercept_hotlinking?(request)
+ request_accepts = parse_request_accepts(request)
+
+ return false unless Feature.enabled?(:repository_archive_hotlinking_interception, default_enabled: true)
+
+ # Block attempts to embed as JS
+ return true if sec_fetch_invalid?(request)
+
+ # If no Accept header was set, skip the rest
+ return false if request_accepts.empty?
+
+ # Workaround for IE8 weirdness
+ return false if IMAGE_FORMATS.include?(request_accepts.first) && request_accepts.include?("application/x-ms-application")
+
+ # Block all other media requests if the first format is a media type
+ return true if INVALID_FORMATS.include?(request_accepts.first)
+
+ false
+ end
+
+ private
+
+ def sec_fetch_invalid?(request)
+ fetch_mode = request.headers["Sec-Fetch-Mode"]
+
+ return if fetch_mode.blank?
+ return true if INVALID_FETCH_MODES.include?(fetch_mode)
+ end
+
+ def parse_request_accepts(request)
+ # Rails will already have parsed the Accept header
+ return request.accepts if request.respond_to?(:accepts)
+
+ # Grape doesn't parse it, so we can use the Rails system for this
+ return Mime::Type.parse(request.headers["Accept"]) if request.respond_to?(:headers) && request.headers["Accept"].present?
+
+ []
+ end
+ end
+ end
+end