| ... | @@ -11,11 +11,14 @@ module Gitlab |
... | @@ -11,11 +11,14 @@ module Gitlab |
|
|
# Validates the given url according to the constraints specified by arguments.
|
|
# Validates the given url according to the constraints specified by arguments.
|
|
|
#
|
|
#
|
|
|
# ports - Raises error if the given URL port does is not between given ports.
|
|
# ports - Raises error if the given URL port does is not between given ports.
|
|
|
# allow_localhost - Raises error if URL resolves to a localhost IP address and argument is true.
|
|
# allow_localhost - Raises error if URL resolves to a localhost IP address and argument is false.
|
|
|
# allow_local_network - Raises error if URL resolves to a link-local address and argument is true.
|
|
# allow_local_network - Raises error if URL resolves to a link-local address and argument is false.
|
|
|
# ascii_only - Raises error if URL has unicode characters and argument is true.
|
|
# ascii_only - Raises error if URL has unicode characters and argument is true.
|
|
|
# enforce_user - Raises error if URL user doesn't start with alphanumeric characters and argument is true.
|
|
# enforce_user - Raises error if URL user doesn't start with alphanumeric characters and argument is true.
|
|
|
# enforce_sanitization - Raises error if URL includes any HTML/CSS/JS tags and argument is true.
|
|
# enforce_sanitization - Raises error if URL includes any HTML/CSS/JS tags and argument is true.
|
|
|
|
# require_absolute - Raises error if URL is not absolute and argument is true.
|
|
|
|
# Allow relative URLs beginning with slash when argument is false
|
|
|
|
# Raises error if relative URL does not begin with slash and argument is false
|
|
|
#
|
|
#
|
|
|
# Returns an array with [<uri>, <original-hostname>].
|
|
# Returns an array with [<uri>, <original-hostname>].
|
|
|
# rubocop:disable Metrics/ParameterLists
|
|
# rubocop:disable Metrics/ParameterLists
|
| ... | @@ -28,7 +31,8 @@ module Gitlab |
... | @@ -28,7 +31,8 @@ module Gitlab |
|
|
ascii_only: false,
|
|
ascii_only: false,
|
|
|
enforce_user: false,
|
|
enforce_user: false,
|
|
|
enforce_sanitization: false,
|
|
enforce_sanitization: false,
|
|
|
dns_rebind_protection: true)
|
|
dns_rebind_protection: true,
|
|
|
|
require_absolute: true)
|
|
|
# rubocop:enable Metrics/ParameterLists
|
|
# rubocop:enable Metrics/ParameterLists
|
|
|
|
|
|
|
|
return [nil, nil] if url.nil?
|
|
return [nil, nil] if url.nil?
|
| ... | @@ -42,13 +46,14 @@ module Gitlab |
... | @@ -42,13 +46,14 @@ module Gitlab |
|
|
ports: ports,
|
|
ports: ports,
|
|
|
enforce_sanitization: enforce_sanitization,
|
|
enforce_sanitization: enforce_sanitization,
|
|
|
enforce_user: enforce_user,
|
|
enforce_user: enforce_user,
|
|
|
ascii_only: ascii_only
|
|
ascii_only: ascii_only,
|
|
|
|
require_absolute: require_absolute
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
hostname = uri.hostname
|
|
hostname = uri.hostname
|
|
|
port = get_port(uri)
|
|
port = get_port(uri)
|
|
|
|
|
|
|
|
address_info = get_address_info(hostname, port)
|
|
address_info = get_address_info(hostname, port) if require_absolute || uri.absolute?
|
|
|
return [uri, nil] unless address_info
|
|
return [uri, nil] unless address_info
|
|
|
|
|
|
|
|
protected_uri_with_hostname = enforce_uri_hostname(address_info, uri, hostname, dns_rebind_protection)
|
|
protected_uri_with_hostname = enforce_uri_hostname(address_info, uri, hostname, dns_rebind_protection)
|
| ... | @@ -94,12 +99,14 @@ module Gitlab |
... | @@ -94,12 +99,14 @@ module Gitlab |
|
|
[uri, hostname]
|
|
[uri, hostname]
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
def validate_uri(uri:, schemes:, ports:, enforce_sanitization:, enforce_user:, ascii_only:)
|
|
def validate_uri(uri:, schemes:, ports:, enforce_sanitization:, enforce_user:, ascii_only:, require_absolute:)
|
|
|
validate_html_tags(uri) if enforce_sanitization
|
|
validate_html_tags(uri) if enforce_sanitization
|
|
|
|
validate_absolute(uri) if require_absolute
|
|
|
|
validate_relative(uri) unless require_absolute
|
|
|
|
|
|
|
|
return if internal?(uri)
|
|
return if internal?(uri)
|
|
|
|
|
|
|
|
validate_scheme(uri.scheme, schemes)
|
|
validate_scheme(uri.scheme, schemes, require_absolute)
|
|
|
validate_port(get_port(uri), ports) if ports.any?
|
|
validate_port(get_port(uri), ports) if ports.any?
|
|
|
validate_user(uri.user) if enforce_user
|
|
validate_user(uri.user) if enforce_user
|
|
|
validate_hostname(uri.hostname)
|
|
validate_hostname(uri.hostname)
|
| ... | @@ -169,8 +176,20 @@ module Gitlab |
... | @@ -169,8 +176,20 @@ module Gitlab |
|
|
raise BlockedUrlError, "Only allowed ports are #{ports.join(', ')}, and any over 1024"
|
|
raise BlockedUrlError, "Only allowed ports are #{ports.join(', ')}, and any over 1024"
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
def validate_scheme(scheme, schemes)
|
|
def validate_absolute(uri)
|
|
|
if scheme.blank? || (schemes.any? && !schemes.include?(scheme))
|
|
return if uri.absolute?
|
|
|
|
|
|
|
|
raise BlockedUrlError, 'must be absolute'
|
|
|
|
end
|
|
|
|
|
|
|
|
def validate_relative(uri)
|
|
|
|
return if uri.absolute? || uri.path.starts_with?('/')
|
|
|
|
|
|
|
|
raise BlockedUrlError, 'relative path must begin with a / (slash)'
|
|
|
|
end
|
|
|
|
|
|
|
|
def validate_scheme(scheme, schemes, require_absolute)
|
|
|
|
if (require_absolute && scheme.blank?) || (schemes.any? && !schemes.include?(scheme))
|
|
|
raise BlockedUrlError, "Only allowed schemes are #{schemes.join(', ')}"
|
|
raise BlockedUrlError, "Only allowed schemes are #{schemes.join(', ')}"
|
|
|
end
|
|
end
|
|
|
end
|
|
end
|
| ... | @@ -229,9 +248,10 @@ module Gitlab |
... | @@ -229,9 +248,10 @@ module Gitlab |
|
|
end
|
|
end
|
|
|
|
|
|
|
|
def internal_web?(uri)
|
|
def internal_web?(uri)
|
|
|
uri.scheme == config.gitlab.protocol &&
|
|
(uri.scheme.blank? && uri.hostname.blank? && uri.port.blank? && uri.path.starts_with?('/')) ||
|
|
|
uri.hostname == config.gitlab.host &&
|
|
(uri.scheme == config.gitlab.protocol &&
|
|
|
(uri.port.blank? || uri.port == config.gitlab.port)
|
|
uri.hostname == config.gitlab.host &&
|
|
|
|
(uri.port.blank? || uri.port == config.gitlab.port))
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
def internal_shell?(uri)
|
|
def internal_shell?(uri)
|
| ... | |
... | |
| ... | | ... | |