Class: CamaleonCms::UserUrlValidator

Inherits:
Object
  • Object
show all
Defined in:
app/validators/camaleon_cms/user_url_validator.rb

Constant Summary collapse

HTTPS_SCHEME =
'https'
LOCAL_IPS =
%w[0.0.0.0 ::].freeze
IPAddr.new('169.254.0.0/16').freeze
SHARED_ADDR_NETMASK =
IPAddr.new('100.64.0.0/10').freeze
IPV6_SITELOCAL =
IPAddr.new('fec0::/10').freeze
IPV6_UNIQUE_LOCAL =
IPAddr.new('fc00::/7').freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeUserUrlValidator

Returns a new instance of UserUrlValidator.



50
51
52
53
# File 'app/validators/camaleon_cms/user_url_validator.rb', line 50

def initialize
  @errors = []
  @resolved_ip = nil
end

Instance Attribute Details

#resolved_ipObject (readonly)

Returns the value of attribute resolved_ip.



48
49
50
# File 'app/validators/camaleon_cms/user_url_validator.rb', line 48

def resolved_ip
  @resolved_ip
end

Class Method Details

.validateObject



40
41
42
# File 'app/validators/camaleon_cms/user_url_validator.rb', line 40

def self.validate(...)
  new.validate(...)
end

.validate_external_httpsObject



44
45
46
# File 'app/validators/camaleon_cms/user_url_validator.rb', line 44

def self.validate_external_https(...)
  new.validate_external_https(...)
end

Instance Method Details

#validate(url, allow_localhost: false, allow_local_network: false, enforce_user: true, enforce_sanitizing: true, resolve: true, reject_path_traversal: false) ⇒ Object

Validates the given url according to the constraints specified by the received arguments.

allow_localhost - Registers error if URL resolves to a localhost IP address and argument is false. allow_local_network - Registers error if URL resolves to a link-local address and argument is false. enforce_user - Registers error if URL user doesn't start with alphanumeric characters and argument is true. enforce_sanitizing - Registers error if URL includes any HTML/CSS/JS tags and argument is true. resolve - When true (default), performs DNS resolution to check the IP. When false, only validates URL structure and checks IP literals statically (no DNS resolution, allowing unresolvable hostnames like custom scheme URLs). reject_path_traversal - When true, checks if URI path contains path traversal sequences.

Returns an array with error messages, or true if valid.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'app/validators/camaleon_cms/user_url_validator.rb', line 67

def validate(url, allow_localhost: false, allow_local_network: false, enforce_user: true, enforce_sanitizing: true,
             resolve: true, reject_path_traversal: false)
  return true if skip_validation?
  return invalid_url if url.blank?

  return invalid_url unless (uri = parse_url(url))

  validate_uri(uri: uri, enforce_sanitizing: enforce_sanitizing, enforce_user: enforce_user)

  validate_path_traversal(uri) if reject_path_traversal
  return @errors if @errors.any?

  if resolve
    return @errors if @errors.any?

    address_info = get_address_info(uri)
    return @errors if @errors.any?

    @resolved_ip = address_info.first&.ip_address

    validate_local_request(
      address_info: address_info,
      allow_localhost: allow_localhost,
      allow_local_network: allow_local_network
    )
  else
    validate_static_ip(uri.hostname, allow_localhost: allow_localhost, allow_local_network: allow_local_network)
  end

  @errors.empty? || @errors
end

#validate_external_https(url) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'app/validators/camaleon_cms/user_url_validator.rb', line 99

def validate_external_https(url)
  return true if skip_validation?

  uri = parse_url(url)
  return [I18n.t('camaleon_cms.admin.validate.url')] if uri.nil? || uri.scheme.blank? || uri.hostname.blank?
  return [I18n.t('camaleon_cms.admin.validate.https_only_url')] unless uri.scheme&.downcase == HTTPS_SCHEME

  validate(uri, allow_localhost: false, allow_local_network: false)
end