Module: RedQuilt::Inline::UrlSanitizer
- Defined in:
- lib/red_quilt/inline/url_sanitizer.rb
Overview
URL-scheme security policy for inline link / image / autolink destinations. Kept separate from Builder so the “which schemes are safe and how blocking is reported” concern has a single home and can change without touching the inline construction logic.
Stateless (module_function); diagnostics are appended to the caller’s array (or skipped when it is nil), so there is no per-call allocation.
Constant Summary collapse
- SAFE_SCHEMES =
%w[http https mailto ftp tel ssh].freeze
- UNSAFE_AUTOLINK_SCHEMES =
Autolinks (‘<scheme:…>`) are not run through the SAFE_SCHEMES allowlist: CommonMark permits arbitrary schemes there (e.g. `<made-up-scheme://x>`), and an allowlist would break that conformance. Only the schemes that execute script when the link is navigated are denied.
%w[javascript vbscript data].freeze
- SCHEME_RE =
/\A([a-zA-Z][a-zA-Z0-9+\-.]*):/
Class Method Summary collapse
-
.block_unsafe_autolink(destination, diagnostics) ⇒ Object
Autolink destinations: denylist.
- .report_blocked(diagnostics, scheme) ⇒ Object
-
.sanitize_destination(destination, diagnostics) ⇒ Object
Link / image destinations: allowlist.
Class Method Details
.block_unsafe_autolink(destination, diagnostics) ⇒ Object
Autolink destinations: denylist. The destination is returned unchanged unless its scheme executes script on navigation, in which case the href is emptied and a diagnostic is recorded.
44 45 46 47 48 49 50 51 |
# File 'lib/red_quilt/inline/url_sanitizer.rb', line 44 def block_unsafe_autolink(destination, diagnostics) scheme = destination[SCHEME_RE, 1] return destination if scheme.nil? return destination unless UNSAFE_AUTOLINK_SCHEMES.include?(scheme.downcase) report_blocked(diagnostics, scheme) "" end |
.report_blocked(diagnostics, scheme) ⇒ Object
53 54 55 56 57 58 59 60 61 |
# File 'lib/red_quilt/inline/url_sanitizer.rb', line 53 def report_blocked(diagnostics, scheme) return unless diagnostics diagnostics << Diagnostic.new( severity: :warning, rule: :unsafe_url, message: "Unsafe URL scheme #{scheme.downcase.inspect} blocked", ) end |
.sanitize_destination(destination, diagnostics) ⇒ Object
Link / image destinations: allowlist. Relative URLs (starting ‘/` or `#`) and scheme-less URLs pass; an unknown scheme is blocked (href emptied) and a diagnostic is recorded.
29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/red_quilt/inline/url_sanitizer.rb', line 29 def sanitize_destination(destination, diagnostics) return "" if destination.nil? return destination if destination.start_with?("/", "#") scheme = destination[SCHEME_RE, 1] return destination if scheme.nil? return destination if SAFE_SCHEMES.include?(scheme.downcase) report_blocked(diagnostics, scheme) "" end |