52 lines
1.4 KiB
Ruby
52 lines
1.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module Git
|
|
#
|
|
# PreReceiveError is special because its message gets displayed to users
|
|
# in the web UI. Because of this, we:
|
|
# - Only display errors that have been marked as safe with a prefix.
|
|
# This is to prevent leaking of stacktraces, or other sensitive info.
|
|
# - Sanitize the string of any XSS
|
|
class PreReceiveError < StandardError
|
|
SAFE_MESSAGE_PREFIXES = [
|
|
'GitLab:', # Messages from gitlab-shell
|
|
'GL-HOOK-ERR:' # Messages marked as safe by user
|
|
].freeze
|
|
|
|
SAFE_MESSAGE_REGEX = /^(#{SAFE_MESSAGE_PREFIXES.join('|')})\s*(?<safe_message>.+)/.freeze
|
|
|
|
attr_reader :raw_message
|
|
|
|
def initialize(message = '', fallback_message: '')
|
|
@raw_message = message
|
|
|
|
sanitized_msg = sanitize(message)
|
|
|
|
if sanitized_msg.present?
|
|
super(sanitized_msg)
|
|
else
|
|
super(fallback_message)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
# In gitaly-ruby we override this method to do nothing, so that
|
|
# sanitization happens in gitlab-rails only.
|
|
def sanitize(message)
|
|
return message if message.blank?
|
|
|
|
safe_messages = message.split("\n").map do |msg|
|
|
if (match = msg.match(SAFE_MESSAGE_REGEX))
|
|
match[:safe_message].presence
|
|
end
|
|
end
|
|
|
|
safe_messages = safe_messages.compact.join("\n")
|
|
|
|
Gitlab::Utils.nlbr(safe_messages)
|
|
end
|
|
end
|
|
end
|
|
end
|