Class: Alchemy::SvgScrubber
- Inherits:
-
Loofah::Scrubber
- Object
- Loofah::Scrubber
- Alchemy::SvgScrubber
- Defined in:
- lib/alchemy/svg_scrubber.rb
Overview
A Loofah scrubber that sanitizes SVG content by removing dangerous elements and attributes that could execute scripts or load malicious external resources.
Constant Summary collapse
- DANGEROUS_ELEMENTS =
Elements that can execute scripts or load external resources
%w[ script foreignObject iframe object embed handler listener ].freeze
- ANIMATION_ELEMENTS =
Animation elements that are dangerous only when targeting URL attributes
%w[ animate animateMotion animateTransform set ].freeze
- DANGEROUS_ANIMATION_TARGETS =
Attributes that animations should not be allowed to target
%w[ href xlink:href ].freeze
- URL_ATTRIBUTES =
Attributes that can contain javascript: URLs
%w[ href xlink:href formaction src data srcdoc ].freeze
- SAFE_URL_PROTOCOLS =
Protocols that are safe in URL attributes
%w[ http https ].freeze
- SAFE_DATA_URI_TYPES =
Safe data URI MIME types (images only, no text/html or SVG)
%w[ data:image/png data:image/jpeg data:image/jpg data:image/gif data:image/webp data:image/avif ].freeze
Instance Method Summary collapse
Instance Method Details
#scrub(node) ⇒ Object
61 62 63 64 65 66 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 98 99 100 101 102 103 |
# File 'lib/alchemy/svg_scrubber.rb', line 61 def scrub(node) # Remove dangerous elements entirely if DANGEROUS_ELEMENTS.include?(node.name) node.remove return end # Remove animation elements only if they target dangerous attributes if ANIMATION_ELEMENTS.include?(node.name) target = node["attributeName"]&.downcase if DANGEROUS_ANIMATION_TARGETS.include?(target) node.remove return end end node.attributes.each do |attr_name, attr_obj| attr_lower = attr_name.downcase # Remove all event handlers (on*) if attr_lower.start_with?("on") node.remove_attribute(attr_name) next end # Check URL attributes for dangerous protocols if URL_ATTRIBUTES.include?(attr_lower) value = attr_obj.value.to_s.strip.downcase.gsub(/[\s\x00-\x1f]+/, "") unless safe_url?(value) node.remove_attribute(attr_name) end next end # Remove style attributes with dangerous content if attr_lower == "style" value = attr_obj.value.to_s.downcase if value.match?(/javascript:|expression\(|vbscript:|url\s*\(\s*["']?\s*(?:javascript|vbscript|data:text\/html):/i) node.remove_attribute(attr_name) end end end end |