module
Components::Elements::UrlAttributeValidation
Overview
SafeHTML v1 (docs/SAFE_HTML_V1.md ยง3.2): a construction/render-time
backstop for the handful of concrete elements whose whole reason for
existing is a URL-bearing attribute โ A#href, Img#src, and
similar. Before this module, href/src reached these elements as a
plain, unvalidated String through two paths: the constructor kwargs
(A.new(href: "javascript:...")) and the ordinary
#set_attribute("href", "javascript:...") call โ both of which
HTML.escape-based attribute escaping does nothing to neutralize,
since javascript:/vbscript:/data: survive attribute-value
escaping unchanged (escaping quotes/</> doesn't touch the scheme).
include-ing this module and overriding url_bearing_attribute? for
the one or two attribute names a tag actually has closes both paths at
once: the constructor kwargs path already funnels through
HTMLElement#set_attribute (see HTMLElement#initialize), so
overriding #set_attribute here covers it for free.
This deliberately does not touch HTMLElement#set_attribute
itself โ the shared, generic, String-typed setter every one of the
~94 element classes has, including the ~185 call sites in
src/ui/renderers/web_renderer.cr that set data-*/style/ARIA
attributes on elements that have nothing to do with URLs. Only
classes that include UrlAttributeValidation (the actual
link/src-bearing tags) get the extra check; every other element and
every other attribute name is unaffected, matching
docs/SAFE_HTML_V1.md's documented two-tier scope.
The already-typed HTMLElement#set_safe_url_attribute(name, SafeURL)
path is unaffected by (and redundant with, in a good way) this
module: it calls #set_attribute(name, url.to_s) with a String
that has already passed SafeURL.parse!, so it passes this check
trivially.
Direct including types
- Components::Elements::A
- Components::Elements::Area
- Components::Elements::Audio
- Components::Elements::Base
- Components::Elements::Button
- Components::Elements::Embed
- Components::Elements::Form
- Components::Elements::Iframe
- Components::Elements::Img
- Components::Elements::Input
- Components::Elements::Link
- Components::Elements::Object
- Components::Elements::Script
- Components::Elements::Source
- Components::Elements::Track
- Components::Elements::Video