### Chaining Scrubbers
Source: https://github.com/flavorjones/loofah/blob/main/README.md
Scrubbers can be chained together for sequential HTML sanitization. This example prunes unsafe tags and then converts spans to divs.
```ruby
Loofah.html5_fragment("hello ") \
.scrub!(:prune) \
.scrub!(span2div).to_s
# => "
hello
"
```
--------------------------------
### Initialize Firehose UI and Event Handlers
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
This JavaScript code initializes the firehose UI, sets up focus and blur event handlers for the filter input, and applies updates. It configures various firehose settings like start date, mode, and sorting.
```javascript
firehose_exists = 1; $(function(){ $('#firehose-filter'). focus(function(event){ gFocusedText = this; }). blur(function(event){ if ( gFocusedText === this ) { gFocusedText = null; } }); var $fhitems = firehose_init_tag_ui(); firehose_init_idle($fhitems); apply_updates_when( 'at-end', true); }); firehose_settings.startdate = ""; firehose_settings.mode = "mixed"; firehose_settings.fhfilter = ""; firehose_settings.orderdir = "DESC"; firehose_settings.orderby = "createtime"; firehose_settings.duration = -1; firehose_settings.color = "green"; firehose_settings.view = "stories"; firehose_settings.viewtitle = "Stories"; firehose_settings.tab = ""; firehose_settings.base_filter = ""; firehose_settings.user_view_uid = ""; firehose_settings.sectionname = "Main"; firehose_settings.issue = ""; firehose_settings.section = 13; $('#searchquery').val(firehose_settings.fhfilter); view_change_hide_show(firehose_settings.view); firehose_sitename = "Slashdot"; firehose_slogan = "News for nerds, stuff that matters"; firehose_update_title_count(); fh_idle_skin = 1; firehose_settings.index = 1; var firehose_action_time = 0; var firehose_user_class = 0; var fh_color = "green"; fh_colors = [ "red", "orange", "yellow", "green", "blue", "indigo", "violet", "black" ]; var fh_colors_hash = new Array(0); for (var i=0; i< fh_colors.length; i++) { fh_colors_hash[fh_colors[i]] = i; } var fh_view_mode = "mixed"; firehose_settings.page = 0; fh_is_admin = 0; var updateIntervalType = 2; var inactivity_timeout = 3600; setFirehoseAction(); var update_time = "2009-07-01 01:58:36"; var maxtime = "2009-07-01 01:58:36"; var insert_new_at = "top"; firehose_play("init"); fh_adTimerUrl = '/images/iframe/firehose.html'; fh_ticksize = 15; sitename = 'idle.slashdot.org';
```
--------------------------------
### Create Custom Scrubber to Change Tag Names
Source: https://github.com/flavorjones/loofah/blob/main/README.md
A Loofah::Scrubber can be initialized with a block to define custom scrubbing logic. This example changes all `` tags to `
` tags.
```ruby
# change all tags to
tags
span2div = Loofah::Scrubber.new do |node|
node.name = "div" if node.name == "span"
end
```
--------------------------------
### Sanitize HTML with Allowed Tags in Ruby
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Demonstrates how to use Rails::Html::WhiteListSanitizer to sanitize HTML input, specifying a list of allowed tags. This example highlights a vulnerability when 'svg' and 'style' tags are allowed, leading to script execution.
```ruby
#! /usr/bin/env ruby
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "rails-html-sanitizer", "=1.4.3" # contains the select/style fix
end
require "rails-html-sanitizer"
def sanitize(input, tags)
Rails::Html::WhiteListSanitizer.new.sanitize(input, tags: tags)
end
input, tags = "", %w(svg style)
sanitize(input, tags) # => ""
input, tags = "", %w(math style img)
sanitize(input, tags) # => ""
```
--------------------------------
### Chaining multiple scrubbers
Source: https://context7.com/flavorjones/loofah/llms.txt
Demonstrates applying multiple Loofah transformations in sequence for comprehensive HTML processing.
```ruby
require 'loofah'
```
--------------------------------
### Create and Manipulate HTML Elements
Source: https://context7.com/flavorjones/loofah/llms.txt
Shows how to create a new HTML structure, add child elements dynamically, and serialize the result.
```ruby
doc = Loofah.html5_fragment("
")
ul = doc.at_css("ul")
3.times { |i| ul.add_child("
Item #{i + 1}
") }
doc.to_s
```
--------------------------------
### Escape unsafe tags to HTML entities
Source: https://context7.com/flavorjones/loofah/llms.txt
Use the :escape scrubber to convert unsafe HTML tags into visible HTML entities. This is useful for safely displaying code examples.
```ruby
require 'loofah'
unsafe_html = "Check this:
safe
tag"
result = Loofah.html5_fragment(unsafe_html).scrub!(:escape).to_s
# => "Check this:
safe
<script>alert('XSS')</script> <custom>tag</custom>"
```
```ruby
require 'loofah'
# Useful when you want to display code examples safely
code_example = ""
safe_display = Loofah.scrub_html5_fragment(code_example, :escape).to_s
# => "<script>document.write('Hello')</script>"
```
--------------------------------
### Shorthand XML Scrubbing Methods
Source: https://context7.com/flavorjones/loofah/llms.txt
Demonstrates shorthand methods for scrubbing XML fragments and documents, including the use of custom scrubbers.
```ruby
xml = "ok"
custom_scrubber = Loofah::Scrubber.new { |n| n.remove if n["attr"] == "bad" }
Loofah.scrub_xml_fragment(xml, custom_scrubber).to_s
Loofah.scrub_xml_document(xml, custom_scrubber).to_s
```
--------------------------------
### Get Text Content from HTML Fragment
Source: https://github.com/flavorjones/loofah/blob/main/README.md
The `text` method returns the plain text content of the document. For better handling of whitespace around block elements, use `to_text`.
```ruby
doc = Loofah.html5_fragment("
Title
Content Next line
")
doc.text # => "TitleContentNext line" # probably not what you want
doc.to_text # => "\nTitle\n\nContent\nNext line\n" # better
```
--------------------------------
### Input HTML String
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
The initial HTML input string used for demonstrating parsing behavior.
```html
```
--------------------------------
### Google Analytics Initialization
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Initializes Google Analytics tracking for the page. Requires the _gat object to be available.
```javascript
dfp_ord=Math.random()*
10000000000000000;
dfp_tile = 1;
var pageTracker = _gat._getTracker("UA-32013-5");
pageTracker._setDomainName("slashdot.org");
pageTracker._initData();
```
--------------------------------
### Equivalent HTML5 for Math Case
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
The HTML string equivalent to the HTML5 DOM, demonstrating the 'img' tag as a sibling.
```html
```
--------------------------------
### Initialize and Update Section Metadata
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Initializes metadata for a section element and updates section signatures. Used for matching properties to existing sections.
```javascript
function init_metadata( el ){
var $el=$(el),
result=$el.metadata({
type:'elem',
name:'script'
});
$el.find('script[type=data]').remove();
return result;
}
```
```javascript
update_section = function( el, update, opts ){
var section = init_metadata(el),
id = section.id,
// assert(id);
oldsig = signatures[id],
newsig = signature($.extend(section, // Make the color explicit.
!section.color && {
color:default_color[section.viewname]
},
// Roll-in the updated data, if any; but protect the id.
update,
{ id:id }
));
// Update the signatures that let us match properties to existing sections.
if ( id!=='unsaved' && newsig!==oldsig ) {
ids[ signatures[id]=newsig ] = id;
if ( oldsig ) {
delete ids[ oldsig ];
// Discard cached skin if the search has changed.
section.skin && oldsig.split(';')[2]!==newsig.split(';')[2] && delete section.skin;
// This must be a change to an existing menu item, so let's save the menu as a whole.
save_menu();
}
}
if ( opts ) {
opts.highlight && highlight_menu_item(id);
opts.make_default && ($section_menu.metadata().default_id=id);
}
};
```
--------------------------------
### Sanitizer Behavior Comparison for Select/Style Input
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Compares the sanitization output for a specific input involving `"
v1.4.2: ""
v1.4.3: ""
proposed: ""
```
--------------------------------
### Create Custom Scrubber Classes
Source: https://context7.com/flavorjones/loofah/llms.txt
Define reusable scrubber classes by inheriting from `Loofah::Scrubber` for complex or frequently used transformations. Specify the `direction` in the initializer.
```ruby
require 'loofah'
# Custom scrubber class that adds a CSS class to all elements
class AddClassScrubber < Loofah::Scrubber
def initialize(class_name)
@class_name = class_name
@direction = :top_down # or :bottom_up
end
def scrub(node)
return Loofah::Scrubber::CONTINUE unless node.element?
existing_class = node["class"] || ""
node["class"] = "#{existing_class} #{@class_name}".strip
Loofah::Scrubber::CONTINUE # Continue traversing children
end
end
# Use the custom scrubber
html = "
Paragraph
Span
"
scrubber = AddClassScrubber.new("processed")
result = Loofah.html5_fragment(html).scrub!(scrubber).to_s
# => '
Paragraph
Span
'
```
```ruby
require 'loofah'
# Custom scrubber that removes elements by attribute
class RemoveByAttribute < Loofah::Scrubber
def initialize(attr_name, attr_value)
@attr_name = attr_name
@attr_value = attr_value
@direction = :top_down
end
def scrub(node)
if node.element? && node[@attr_name] == @attr_value
node.remove
return Loofah::Scrubber::STOP
end
Loofah::Scrubber::CONTINUE
end
end
html = '
Remove me
Keep me
'
result = Loofah.html5_fragment(html).scrub!(RemoveByAttribute.new("data-remove", "true")).to_s
# => '
Keep me
'
```
--------------------------------
### Shorthand HTML Scrubbing Methods
Source: https://context7.com/flavorjones/loofah/llms.txt
Provides convenience methods for common HTML parsing and scrubbing operations, supporting both fragments and documents, and HTML4/HTML5.
```ruby
require 'loofah'
unsafe_html = "
Safe
"
# These shorthand methods combine parsing and scrubbing
Loofah.scrub_html5_fragment(unsafe_html, :prune).to_s # HTML5 fragment
Loofah.scrub_html5_document(unsafe_html, :prune).to_s # HTML5 document
Loofah.scrub_html4_fragment(unsafe_html, :prune).to_s # HTML4 fragment
Loofah.scrub_html4_document(unsafe_html, :prune).to_s # HTML4 document
```
--------------------------------
### Contextual Suggestions Object
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Defines objects mapping context keywords to lists of suggestion types. Used for categorizing user feedback or content.
```javascript
var suggestions_for_context = {
nod: 'fresh funny insightful interesting maybe ',
nix: 'binspam dupe notthebest offtopic slownewsday stale stupid ',
feedback: 'typo dupe error',
metanod: 'insightful interesting informative funny underrated',
metanix: 'offtopic flamebait troll redundant overrated'
};
```
--------------------------------
### Add security rel attributes to hyperlinks
Source: https://context7.com/flavorjones/loofah/llms.txt
Use :noopener and :noreferrer scrubbers to add security-related `rel` attributes to hyperlinks. These prevent `window.opener` access and the sending of the referer header, respectively. Scrubbers can be chained for comprehensive security.
```ruby
require 'loofah'
link_html = 'Click here'
# Add rel="noopener" to prevent window.opener access
result = Loofah.html5_fragment(link_html).scrub!(:noopener).to_s
# => 'Click here'
```
```ruby
require 'loofah'
link_html = 'Click here'
# Add rel="noreferrer" to prevent referer header
result = Loofah.html5_fragment(link_html).scrub!(:noreferrer).to_s
# => 'Click here'
```
```ruby
require 'loofah'
link_html = 'Click here'
# Chain multiple scrubbers for comprehensive link security
secure_links = Loofah.html5_fragment(link_html)
.scrub!(:nofollow)
.scrub!(:noopener)
.scrub!(:noreferrer)
.to_s
# => 'Click here'
```
--------------------------------
### Chain Scrubbers for HTML Sanitization
Source: https://context7.com/flavorjones/loofah/llms.txt
Chain multiple scrubbers to progressively clean and secure HTML content. Use `html5_fragment` for HTML fragments or `scrub_html5_fragment` with shorthand.
```ruby
user_content = <<-HTML
HTML
clean = Loofah.html5_fragment(user_content)
.scrub!(:prune) # Remove unsafe tags
.scrub!(:nofollow) # Add nofollow to links
.scrub!(:targetblank) # Open links in new tab
.to_s
clean = Loofah.scrub_html5_fragment(user_content, :strip)
.scrub!(:nofollow)
.scrub!(:noopener)
.to_s
```
--------------------------------
### Initialize Slashdot Search Functionality
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/fragment.html
Initializes the search functionality for Slashdot, including event listeners for search input and button clicks. Requires jQuery and assumes the presence of specific HTML elements and a `has_hose()` function.
```javascript
var slash_search;
$(function(){
if (has_hose()) {
var $search_text = $any('searchquery'), $panel = $search_text.closest('fieldset');
$search_buttons = $('#viewsearch,#fhsearch'), ws = /\s+/;
// The search buttons set the firehose option named by their class.
$search_buttons. click(function(){
var which=this.className;
$search_text.each(function(){
firehose_set_options(which, this.value);
});
return false;
});
// Provide a globally available function that does whatever clicking the search button would do.
slash_search = function( query ){
query!==undefined && $search_text.val(query);
$search_buttons.filter(':visible:first').click();
};
$search_text. keydown(function( e ){
// ESCAPE restores the filter in-effect.
if ( e.which == $.ui.keyCode.ESCAPE ) {
$search_text.val(firehose_settings.fhfilter||"");
return true;
}
if ( e.which == $.ui.keyCode.ENTER ) {
slash_search();
return false;
}
});
$(document). bind('firehose-setting-setfhfilter firehose-setting-setsearchfilter', function( e, new_query ){
$('fieldset input[type=text]').each(function(){
$(this).blur().val(new_query);
});
}). bind('set-options.firehose', function( e, data ){
data.select_section && $panel.toggleClass('mode-filter', data.id!=='unsaved');
});
}
});
```
--------------------------------
### Ad Management Script Initialization
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Initializes an ad script, likely for DoubleClick, by dynamically writing a script tag to the document. This snippet includes CDATA for script content.
```javascript
var ad6 = 'inactive';
//<\/script>');
dfp_tile++;
//]]>
```
--------------------------------
### Create Custom Scrubber with Block
Source: https://github.com/flavorjones/loofah/blob/main/README.md
Define a custom document transformation by wrapping a block of code. This scrubber renames 'span' nodes to 'div'.
```ruby
span2div = Loofah::Scrubber.new do |node|
node.name = "div" if node.name == "span"
end
```
--------------------------------
### Parse HTML4 Fragments and Documents with Loofah
Source: https://context7.com/flavorjones/loofah/llms.txt
Use Loofah.html4_fragment and Loofah.html4_document for HTML4 parsing. Shorthand aliases Loofah.fragment and Loofah.document are also available, currently pointing to HTML4 parsing.
```ruby
require 'loofah'
# HTML4 fragment parsing
fragment = Loofah.html4_fragment("Hello World")
fragment.scrub!(:strip).to_s # => "Hello World"
# HTML4 document parsing
doc = Loofah.html4_document("
Content
")
doc.scrub!(:prune).to_s
# Shorthand aliases (currently point to HTML4, may change in future)
Loofah.fragment("
text
") # Same as html4_fragment
Loofah.document("...") # Same as html4_document
```
--------------------------------
### Sanitizer Behavior for Allowed Img Tag
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Illustrates the sanitization output when an `` tag is allowed within a `"
v1.4.2: ""
v1.4.3: ""
proposed: ""
```
--------------------------------
### Built-In HTML Scrubbers
Source: https://github.com/flavorjones/loofah/blob/main/README.md
Use these scrubbers with `Loofah.html5_document` for different sanitization strategies. They are based on html5lib's safelist algorithm.
```ruby
doc = Loofah.html5_document(input)
doc.scrub!(:strip) # replaces unknown/unsafe tags with their inner text
doc.scrub!(:prune) # removes unknown/unsafe tags and their children
doc.scrub!(:escape) # escapes unknown/unsafe tags, like this: <script>
doc.scrub!(:whitewash) # removes unknown/unsafe/namespaced tags and their children,
# and strips all node attributes
```
```ruby
doc.scrub!(:nofollow) # adds rel="nofollow" attribute to links
doc.scrub!(:noopener) # adds rel="noopener" attribute to links
doc.scrub!(:noreferrer) # adds rel="noreferrer" attribute to links
doc.scrub!(:unprintable) # removes unprintable characters from text nodes
doc.scrub!(:targetblank) # adds target="_blank" attribute to links
doc.scrub!(:double_breakpoint) # where `
` appears in a `p` tag, close the `p` and open a new one
```
--------------------------------
### Shorthand Scrubbing Methods
Source: https://github.com/flavorjones/loofah/blob/main/README.md
Use these shorthand class methods for common sanitization tasks, providing a more direct way to apply a scrubber to HTML content.
```ruby
Loofah.scrub_html5_fragment(unsafe_html, :prune)
Loofah.scrub_html5_document(unsafe_html, :prune)
Loofah.scrub_html4_fragment(unsafe_html, :prune)
Loofah.scrub_html4_document(unsafe_html, :prune)
Loofah.scrub_xml_fragment(bad_xml, custom_scrubber)
Loofah.scrub_xml_document(bad_xml, custom_scrubber)
```
```ruby
Loofah.html5_fragment(unsafe_html).scrub!(:prune)
Loofah.html5_document(unsafe_html).scrub!(:prune)
Loofah.html4_fragment(unsafe_html).scrub!(:prune)
Loofah.html4_document(unsafe_html).scrub!(:prune)
Loofah.xml_fragment(bad_xml).scrub!(custom_scrubber)
Loofah.xml_document(bad_xml).scrub!(custom_scrubber)
```
--------------------------------
### Handle Section Menu Mouse Down and Click Events
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Manages user interactions with the section menu, including activating sections on mouse down and initiating modal dialogs for editing on click.
```javascript
$any('links-sections'). mousedown(function( event ){
// "activate" a section (immediately) on mousedown in the section menu
$(event.originalTarget||event.target). // mouseDown was on this element...
closest('li,div.title').not('.active,:has(.active)').
each(function(){
var section = $(this).metadata();
if ( section.id !== 'unsaved' ) {
} else {
}
});
// allow other handlers to run (by not returning false)
}). click(function( event ){
// edit only for a click in the edit button
var handled;
$(event.originalTarget||event.target). // mouseDown was on this element...
closest('a.links-sections-edit'). // ...in this edit icon (if any)
each(function(){
var id = $(this).closest('li,div.title').metadata().id;
id==='unsaved' && (id=void(0));
getModalPrefs('firehoseview', 'Save Custom Section', 0, {
id: id
});
handled = true;
});
return !handled;
});
```
--------------------------------
### Apply Custom Scrubber to HTML Fragment
Source: https://github.com/flavorjones/loofah/blob/main/README.md
The custom scrubber can be applied to a document or fragment using the scrub! method. The result is the modified HTML string.
```ruby
Loofah.html5_fragment("foo
bar
").scrub!(span2div).to_s
# => "
foo
bar
"
```
--------------------------------
### Lazy Load Image Initialization
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Initializes lazy loading for images, likely to improve page performance. This snippet is commented out.
```javascript
// $("img\[src*='images.slashdot.org'\]").lazyload({ threshold : 150 });
```
--------------------------------
### Sanitizer Behavior for Disallowed Img Tag
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Compares sanitization results when an `` tag is disallowed within a `"
v1.4.2: ""
v1.4.3: ""
proposed: ""
```
--------------------------------
### Style Tag Sanitization Comparison
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Compares the output of HTML sanitization for a style tag with simple CSS across different versions (v1.4.2, v1.4.3, proposed). Useful for understanding version-specific behavior changes.
```text
input: ""
v1.4.2: ""
v1.4.3: ""
proposed: ""
```
--------------------------------
### Save Firehose Section Menu
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Saves the current order of firehose sections to the server. Requires user to be logged in.
```javascript
function save_menu(){
if ( !check_logged_in() ) {
return false;
}
// tell the server our current (ordered) list of sections
ajax_update({
op: 'firehose_save_section_menu',
reskey: reskey_static,
fsids: $section_menu. children('li:not(#fhsection-unsaved)'). map(function(){
return this.id.slice(10);
}).get().join(',')
});
}
```
--------------------------------
### Serialized HTML4 for Math Case
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
The serialized HTML string corresponding to the HTML4 DOM of the 'math' case.
```html
```
--------------------------------
### Handle Firehose Setting Events
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Listens for custom events to update the UI when firehose settings change, such as section selection or view options.
```javascript
$(document). bind('firehose-setting-section', function( e, section_id ){
// Request to change sections is on its way to the server; update the UI now (don't wait for response)
var section = highlight_menu_item(section_id).metadata();
$(document). trigger('firehose-setting-setfhfilter', section.filter). trigger('firehose-setting-view', section.viewname). trigger('firehose-setting-color', section.color);
}). bind('set-options.firehose', function( e, data ){
// Changing some option (possibly even the 'section' option)
if ( !data.select_section ) {
// OK, _not_ the 'section' option. Activate a section that matches the new options, or else "unsaved"
delete data.id;
data = section_matching(data)||data;
if ( !data.id ) {
var $unsaved = unsaved();
data = $.extend($unsaved.metadata(), data);
$(document). one('update.firehose', function( e, updated ){
$unsaved.
});
}
}
});
```
--------------------------------
### Modify HTML using Nokogiri API and Scrub
Source: https://context7.com/flavorjones/loofah/llms.txt
Demonstrates modifying an HTML fragment using CSS selectors and then scrubbing it to remove unwanted elements like scripts.
```ruby
doc = Loofah.html5_fragment("
Text
")
doc.at_css("p")["class"] = "highlight"
doc.at_css("div").add_child("")
doc.scrub!(:prune).to_s
```
--------------------------------
### Generic Shorthand Scrubbing
Source: https://context7.com/flavorjones/loofah/llms.txt
Utilizes generic shorthand methods for scrubbing HTML fragments and documents. Note that the underlying implementation defaults to HTML4 and may change in future versions.
```ruby
Loofah.scrub_fragment(unsafe_html, :strip).to_s
Loofah.scrub_document(unsafe_html, :strip).to_s
```
--------------------------------
### Require Loofah Helpers
Source: https://github.com/flavorjones/loofah/blob/main/README.md
To use Loofah's view helpers, which mimic Rails Action View helpers, you must explicitly require the `loofah/helpers` file.
```ruby
require 'loofah/helpers'
```
--------------------------------
### Sanitize HTML with Allowed Tags in Ruby
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Demonstrates how to use Rails::Html::WhiteListSanitizer to sanitize HTML input, specifying allowed tags. Useful for controlling which HTML elements are permitted in the output.
```ruby
#! /usr/bin/env ruby
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "rails-html-sanitizer", path: "."
end
puts Rails::Html::Sanitizer::VERSION
require "rails-html-sanitizer"
def sanitize(input, tags)
Rails::Html::WhiteListSanitizer.new.sanitize(input, tags: tags)
end
input, tags = "", %w(select style)
sanitize(input, tags) # => ""
input, tags = "", %w(style)
sanitize(input, tags) # => ""
input, tags = "", %w(select style)
sanitize(input, tags) # => ""
input, tags = "", %w(select style)
sanitize(input, tags) # => ""
input, tags = "", %w(svg style)
sanitize(input, tags) # => ""
input, tags = "", %w(math style)
sanitize(input, tags) # => ""
input, tags = "", %w(math style img)
sanitize(input, tags) # => ""
```
--------------------------------
### Sanitize HTML with Allowed Tags in Ruby
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Demonstrates how to use Rails::Html::WhiteListSanitizer to sanitize HTML input, specifying allowed tags. This is useful for cleaning user-provided HTML to prevent XSS attacks.
```ruby
#! /usr/bin/env ruby
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "rails-html-sanitizer", path: "."
end
require "rails-html-sanitizer"
def sanitize(input, tags)
Rails::Html::WhiteListSanitizer.new.sanitize(input, tags: tags)
end
input, tags = "", %w(select style)
sanitize(input, tags) # => ""
input, tags = "", %w(style)
sanitize(input, tags) # => ""
input, tags = "", %w(select style)
sanitize(input, tags) # => ""
input, tags = "", %w(select style)
sanitize(input, tags) # => ""
input, tags = "", %w(svg style)
sanitize(input, tags) # => ""
input, tags = "", %w(math style)
sanitize(input, tags) # => ""
input, tags = "", %w(math style img)
sanitize(input, tags) # => ""
```
--------------------------------
### Foreign Element Image Sanitization Comparison
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Compares the output of HTML sanitization for an image tag within MathML and style tags across different versions. Shows that permitting 'img' does not affect the sanitization of onerror attributes in this context.
```text
input: ""
v1.4.2: ""
v1.4.3: ""
proposed: ""
```
--------------------------------
### HTML4 vs HTML5 Sanitization: Math Style Img
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Shows the sanitization difference for a MathML tag with a style element containing an image payload. HTML4 attempts to preserve it, while HTML5 removes it.
```text
2) Failure:
SanitizersTest#test_unsafe_combination_of_math_and_style_with_img_payload [/home/flavorjones/code/oss/rails-html-sanitizer/test/sanitizer_test.rb:609]:
---
+++ actual
@@ -1 +1 @@
-""
+""
```
--------------------------------
### HTML5 DOM for Math Case
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Represents the HTML5 DOM structure after parsing the 'math' case, showing the 'img' tag lifted out.
```text
#(Element:0x67c {
name = "body",
children = [
#(Text "\n"),
#(Element:0x690 {
name = "math",
namespace = #(Namespace:0x6a4 { prefix = "math", href = "http://www.w3.org/1998/Math/MathML" }),
children = [
#(Element:0x6b8 {
name = "style",
namespace = #(Namespace:0x6a4 { prefix = "math", href = "http://www.w3.org/1998/Math/MathML" })
})]
}),
#(Element:0x6cc {
name = "img",
attributes = [
#(Attr:0x6e0 { name = "src", value = "x" }),
#(Attr:0x6f4 { name = "onerror", value = "alert(1)" })]
}),
#(Text "\n" + "\n")]
])
```
--------------------------------
### Parse HTML5 Document and Fragment
Source: https://github.com/flavorjones/loofah/blob/main/README.md
Use Loofah.html5_document and Loofah.html5_fragment to parse HTML. These methods return Nokogiri::HTML5::Document and Nokogiri::HTML5::DocumentFragment objects respectively.
```ruby
Loofah.html5_document(unsafe_html).is_a?(Nokogiri::HTML5::Document) # => true
Loofah.html5_fragment(unsafe_html).is_a?(Nokogiri::HTML5::DocumentFragment) # => true
```
--------------------------------
### Loofah: Unsanitized Nested Script Tags (Vulnerable)
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Demonstrates the vulnerability in Loofah v2.1.1 where nested script tags are not fully sanitized, allowing malicious scripts to pass through.
```ruby
#! /usr/bin/env ruby
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "loofah", "=2.1.1"
end
require "loofah"
def sanitize(input)
Loofah.fragment(input).scrub!(:strip).to_html
end
input = ""
sanitize(input) # => ""
```
--------------------------------
### Test Safe Combination of Select and Style
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Verifies that the sanitizer correctly handles a 'select' element containing a 'style' element when both are explicitly allowed.
```ruby
def test_safe_combination_of_select_and_style
input, tags = "", ["select", "style"]
expected = input
actual = safe_list_sanitize(input, tags: tags)
assert_equal(expected, actual)
end
```
--------------------------------
### Create Custom Scrubbers with Blocks
Source: https://context7.com/flavorjones/loofah/llms.txt
Define inline scrubbers using blocks for simple, one-off transformations. The block receives a node and can modify it or return a Scrubber::STOP or Scrubber::CONTINUE signal.
```ruby
require 'loofah'
# Transform all span tags to div tags
span_to_div = Loofah::Scrubber.new do |node|
node.name = "div" if node.name == "span"
end
html = "First
Middle
Last"
result = Loofah.html5_fragment(html).scrub!(span_to_div).to_s
# => "
First
Middle
Last
"
```
```ruby
require 'loofah'
# Remove all images
remove_images = Loofah::Scrubber.new do |node|
if node.name == "img"
node.remove
Loofah::Scrubber::STOP # Don't traverse children (there are none for img, but good practice)
end
end
html = "
Text more text
"
result = Loofah.html5_fragment(html).scrub!(remove_images).to_s
# => "
Text more text
"
```
--------------------------------
### Page Load Timing and Profiling
Source: https://github.com/flavorjones/loofah/blob/main/benchmark/www.slashdot.com.html
Tracks page load times and reports performance metrics for a small percentage of users. Requires jQuery, pageload, and pageload_done functions.
```javascript
var pageload = { pagemark: '202832641597314907', before_content: (new Date).getTime() }; function pageload_done( $, console, maybe ){
pageload.after_readycode = (new Date).getTime();
pageload.content_ready_time = pageload.content_ready - pageload.before_content;
pageload.script_ready_time = pageload.after_readycode - pageload.content_ready;
pageload.ready_time = pageload.after_readycode - pageload.before_content;
// Only report 1% of cases.
maybe || (Math.random()>0.01) || $.ajax({
data: {
op: 'page_profile',
pagemark: pageload.pagemark,
dom: pageload.content_ready_time,
js: pageload.script_ready_time
}
});
}
```
```javascript
(function( $, pageload, pageload_done, console ){
$. && pageload && $(
function(){
pageload.content_ready = (new Date).getTime();
pageload_done && $(
function(){
pageload_done($, console, 'maybe');
}
);
}
);
})(window.jQuery, window.pageload, window.pageload_done, window.console);
```
--------------------------------
### Sanitizer Behavior Comparison for SVG/Script Input
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Shows the sanitization output for an SVG containing a script tag within a style tag, comparing different versions. Demonstrates the sanitizer's ability to handle foreign elements and prevent script execution.
```text
input: ""
v1.4.2: ""
v1.4.3: ""
proposed: ""
```
--------------------------------
### Add target="_blank" to hyperlinks
Source: https://context7.com/flavorjones/loofah/llms.txt
The :targetblank scrubber adds `target="_blank"` to all hyperlinks, causing them to open in new tabs. It skips anchor links. On modern browsers, `target="_blank"` implicitly provides noopener behavior.
```ruby
require 'loofah'
# Content with various link types
content = '
'
# On modern browsers, target="_blank" implicitly provides noopener behavior
```
--------------------------------
### Parse HTML5 Documents with Loofah
Source: https://context7.com/flavorjones/loofah/llms.txt
Use Loofah.html5_document to parse complete HTML5 documents including DOCTYPE, html, head, and body tags. Sanitize the document using scrub! and serialize it back to HTML with to_s.
```ruby
require 'loofah'
# Parse a complete HTML5 document
html = "Test
Hello
"
doc = Loofah.html5_document(html)
# Sanitize the document
doc.scrub!(:strip)
# Serialize back to HTML
doc.to_s
# => "Test
Hello
"
```
--------------------------------
### Equivalent HTML5 Document
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
The HTML5 DOM structure is equivalent to this HTML5 document. Browsers will execute the embedded JavaScript.
```html
```
--------------------------------
### Scrub Specific Nodes with XPath
Source: https://context7.com/flavorjones/loofah/llms.txt
Apply scrubbers to specific parts of a document or XML by selecting nodes using XPath. Use `doc.xpath(...)` or `doc.at_xpath(...)` before calling `scrub!`.
```ruby
require 'loofah'
# Scrub only specific nodes, not the whole document
xml = <<-XML
John50000Jane60000Bob70000
XML
doc = Loofah.xml_document(xml)
# Remove salary info only from employees section
remove_salary = Loofah::Scrubber.new do |node|
node.remove if node.name == "salary"
end
# Scrub only nodes matching XPath
doc.xpath("//employees/employee").scrub!(remove_salary)
# Employees section has no salaries, public-info still has them
# Scrub single node
doc.at_xpath("//public-info").scrub!(remove_salary)
```
--------------------------------
### Sanitizer Behavior Comparison for Script Tag Removal
Source: https://github.com/flavorjones/loofah/blob/main/docs/2022-10-decision-on-cdata-nodes.md
Illustrates how the sanitizer recursively removes `"
v1.4.2: ""
v1.4.3: ""
proposed: ""
```