Module: Alap::SanitizeUrl
- Defined in:
- lib/alap/sanitize_url.rb
Overview
URL sanitizer — Ruby port of src/core/sanitizeUrl.ts.
Blocks dangerous URI schemes (javascript:, data:, vbscript:, blob:) to prevent XSS when rendering links from untrusted configs.
Three entry points:
- ::call(url) — loose; allows http, https, mailto, tel,
relative, empty string; blocks the
dangerous set.
- ::strict(url) — http / https / mailto only (plus
relative / empty).
- ::with_schemes(url, list) — configurable scheme allowlist.
Constant Summary collapse
- CONTROL_CHARS =
/[\x00-\x1f\x7f]/- DANGEROUS_SCHEME =
/\A(javascript|data|vbscript|blob)\s*:/i- SCHEME_MATCH =
/\A([a-zA-Z][a-zA-Z0-9+\-.]*)\s*:/- SAFE_FALLBACK =
"about:blank"- DEFAULT_SCHEMES =
%w[http https].freeze
- STRICT_SCHEMES =
%w[http https mailto].freeze
Class Method Summary collapse
-
.call(url) ⇒ Object
Returns
urlunchanged if safe, orSAFE_FALLBACKif dangerous. -
.strict(url) ⇒ Object
Strict variant — permits only http / https / mailto (plus relative URLs and empty).
-
.with_schemes(url, allowed_schemes = nil) ⇒ Object
Sanitize
urlagainst a configurable scheme allowlist.
Class Method Details
.call(url) ⇒ Object
Returns url unchanged if safe, or SAFE_FALLBACK if dangerous.
29 30 31 32 33 34 35 36 |
# File 'lib/alap/sanitize_url.rb', line 29 def self.call(url) return url if url.nil? || url.empty? normalized = url.gsub(CONTROL_CHARS, "").strip return SAFE_FALLBACK if DANGEROUS_SCHEME.match?(normalized) url end |
.strict(url) ⇒ Object
Strict variant — permits only http / https / mailto (plus relative URLs and empty). Intended for non-author-tier links where the caller has not verified the scheme is a developer-intended one.
41 42 43 |
# File 'lib/alap/sanitize_url.rb', line 41 def self.strict(url) with_schemes(url, STRICT_SCHEMES) end |
.with_schemes(url, allowed_schemes = nil) ⇒ Object
Sanitize url against a configurable scheme allowlist.
Runs the dangerous-scheme blocklist first (defence-in-depth: javascript: is blocked even when it appears in the allowlist). Relative URLs pass through unchanged regardless of the allowlist. Default allowed_schemes is DEFAULT_SCHEMES (http / https).
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/alap/sanitize_url.rb', line 51 def self.with_schemes(url, allowed_schemes = nil) base = call(url) return base if base == SAFE_FALLBACK return base if base.nil? || base.empty? schemes = allowed_schemes || DEFAULT_SCHEMES normalized = base.gsub(CONTROL_CHARS, "").strip match = SCHEME_MATCH.match(normalized) if match scheme = match[1].downcase return SAFE_FALLBACK unless schemes.include?(scheme) end base end |