Class: UniversalRenderer::SSR::Scrubber
- Inherits:
-
Loofah::Scrubber
- Object
- Loofah::Scrubber
- UniversalRenderer::SSR::Scrubber
- Defined in:
- lib/universal_renderer/ssr/scrubber.rb
Overview
Removes executable content from HTML returned by the SSR service while preserving the elements and data attributes needed to hydrate an app.
A blocklist over the whole HTML grammar cannot be a boundary against attacker-controlled markup, because the sanitizer and the browser have to agree on how the document parses. Treat it as defense in depth over HTML your own renderer produced.
Constant Summary collapse
- PARSER_CONTEXT_ELEMENTS =
Elements that change how the rest of the markup is tokenized, so the tree this scrubber inspects is not the tree the browser builds.
<noscript>is raw text with scripting enabled (the browser) and markup without it (the sanitizer), so<noscript><p title="</noscript><img src=x onerror=...>">reaches the browser as a live element. The MathML three flip the parser between foreign content and HTML integration points for the same effect. None belong in a server render. %w[ noscript mglyph malignmark annotation-xml ].freeze
- BLOCKED_ELEMENTS =
( %w[ base embed frame frameset iframe object script animate animatemotion animatetransform set ] + PARSER_CONTEXT_ELEMENTS ).freeze
- ALLOWED_SCRIPT_TYPES =
Non-executable data-script MIME types. HTML treats a script whose type is neither a JavaScript MIME type nor one of the special types (
module,importmap,speculationrules) as an inert data block.The exception exists for JSON-LD, which the render emits and which would otherwise be sanitized away along with the SEO that motivates SSR.
%w[application/json application/ld+json].freeze
- URI_ATTRIBUTES =
%w[ action background cite codebase data formaction href longdesc poster src srcset xlink:href ].freeze
- ALLOWED_PROTOCOLS =
%w[http https mailto tel].freeze
- DANGEROUS_PROTOCOL =
/\A(?:javascript|vbscript):/i- DANGEROUS_DATA =
%r{\Adata:(?:text/html|application/xhtml\+xml|image/svg\+xml)}i- SAFE_DATA_IMAGE =
%r{\Adata:image/(?:avif|gif|jpeg|png|webp);base64,}i- INLINE_SVG_DATA =
An SVG referenced by
renders in a restricted mode: no scripts, no external references. Bundlers routinely inline icons as data URIs, so the render would otherwise lose them.
<source>inside<picture>feeds the same mode; inside<video>/<audio>it does not. %r{\Adata:image/svg\+xml[,;]}i- IMAGE_SOURCE_ATTRIBUTES =
%w[src srcset].freeze
Instance Method Summary collapse
-
#initialize ⇒ Scrubber
constructor
A new instance of Scrubber.
- #scrub(node) ⇒ Object
Constructor Details
#initialize ⇒ Scrubber
Returns a new instance of Scrubber.
54 55 56 57 |
# File 'lib/universal_renderer/ssr/scrubber.rb', line 54 def initialize super @direction = :top_down end |
Instance Method Details
#scrub(node) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/universal_renderer/ssr/scrubber.rb', line 59 def scrub(node) return Loofah::Scrubber::CONTINUE unless node.element? if blocked_element?(node) || (node) node.remove return Loofah::Scrubber::STOP end clean_attributes(node) Loofah::Scrubber::CONTINUE end |