RedirectSafely
Sanitize return_to-style URLs, including some edge cases that you probably missed.
RedirectSafely is used in production and extracted from Shopify.
Installation
Add these lines to your application's Gemfile:
gem 'redirect_safely', '~> 1.0'And then execute:
$ bundle
Usage
-
RedirectSafely.safe?(url, options)Return true if the URL is considered "safe", false otherwise.
Parameters:
-
urlString (required) - The URL to test
Options:
-
path_matchRegexp (optional) - Match the path portion of the URL against a regexp -
require_absoluteBoolean (optional) - If true, require an absolute URL (domain must be included inwhitelist) -
require_sslBoolean (optional) - If true, and an absolute URL is provided, require a URL starting withhttps:// -
whitelistString[] (optional) - Whitelisted domains for checking absolute URLs -
subdomainsString[] (optional) - Whitelisted subdomains for checking absolute URLs. Must start with a leading..
-
-
RedirectSafely.make_safe(url, default, options)Return
urlif it's safe, otherwise returndefault.Shares options with
safe?, and is roughly equivalent to:safe_url = RedirectSafely.safe?(url) ? url : default
-
RedirectSafelyValidatorIf you persist a redirect URL on a model, you can validate that it is
safe?:class Request validates :return_to, redirect_safely: true end
You can pass any options supported by
safe?(but not those added bymake_safe). In the event that you need more control over the options (ie, dynamically producting a whitelist based on other model attributes), write a customvalidatemethod:class Request validates :store_url, presence: true validate :return_to, presence: true validate :return_to_is_safe private def return_to_is_safe errors.add(:return_to, :invalid) unless RedirectSafely.safe?(return_to, whitelist: URI.parse(store_uri).host) end end