Class: Banzai::Filter::SanitizationFilter

Inherits:
BaseSanitizationFilter show all
Defined in:
lib/banzai/filter/sanitization_filter.rb

Overview

Sanitize HTML produced by Markdown.

Extends Banzai::Filter::BaseSanitizationFilter with specific rules.

Constant Summary collapse

TABLE_ALIGNMENT_PATTERN =

Styles used by Markdown for table alignment

/text-align: (?<alignment>center|left|right)/
ALLOWED_IDIFF_CLASSES =
%w[idiff left right deletion addition].freeze
HEADER_NODE_NAMES =
%w[h1 h2 h3 h4 h5 h6].freeze

Constants inherited from BaseSanitizationFilter

BaseSanitizationFilter::UNSAFE_PROTOCOLS

Constants included from Gitlab::Utils::SanitizeNodeLink

Gitlab::Utils::SanitizeNodeLink::ATTRS_TO_SANITIZE, Gitlab::Utils::SanitizeNodeLink::UNSAFE_PROTOCOLS

Constants included from Concerns::TimeoutFilterHandler

Concerns::TimeoutFilterHandler::COMPLEX_MARKDOWN_MESSAGE, Concerns::TimeoutFilterHandler::RENDER_TIMEOUT, Concerns::TimeoutFilterHandler::SANITIZATION_RENDER_TIMEOUT

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseSanitizationFilter

#allowlist, #call, remove_rel

Methods included from Gitlab::Utils::SanitizeNodeLink

#permit_url?, #remove_unsafe_links, #safe_protocol?, #sanitize_unsafe_links

Methods included from Concerns::TimeoutFilterHandler

#call

Class Method Details

.remove_code_class?(node) ⇒ Boolean

Returns:

  • (Boolean)


154
155
156
# File 'lib/banzai/filter/sanitization_filter.rb', line 154

def remove_code_class?(node)
  node['class'] != 'idiff'
end

.remove_div_class?(node) ⇒ Boolean

Returns:

  • (Boolean)


136
137
138
139
140
141
142
# File 'lib/banzai/filter/sanitization_filter.rb', line 136

def remove_div_class?(node)
  node['class'] != 'markdown-alert markdown-alert-note' &&
    node['class'] != 'markdown-alert markdown-alert-tip' &&
    node['class'] != 'markdown-alert markdown-alert-important' &&
    node['class'] != 'markdown-alert markdown-alert-warning' &&
    node['class'] != 'markdown-alert markdown-alert-caution'
end

.remove_id_attributes(env) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/banzai/filter/sanitization_filter.rb', line 171

def remove_id_attributes(env)
  node = env[:node]
  return unless node.has_attribute?('id')

  id = node['id']

  case node.name
  when 'a'
    # footnote ids should not be removed
    return if id.start_with?(Banzai::Filter::FootnoteFilter::FOOTNOTE_LINK_ID_PREFIX)
  when 'li'
    # footnote ids should not be removed
    return if id.start_with?(Banzai::Filter::FootnoteFilter::FOOTNOTE_ID_PREFIX)
  when *HEADER_NODE_NAMES
    # headers with generated header anchors should not be removed
    return if id.start_with?(Banzai::Renderer::USER_CONTENT_ID_PREFIX)
  else
    return
  end

  node.remove_attribute('id')
end

.remove_input_class?(node) ⇒ Boolean

Returns:

  • (Boolean)


167
168
169
# File 'lib/banzai/filter/sanitization_filter.rb', line 167

def remove_input_class?(node)
  node['class'] != 'task-list-item-checkbox'
end

.remove_li_class?(node) ⇒ Boolean

Returns:

  • (Boolean)


162
163
164
165
# File 'lib/banzai/filter/sanitization_filter.rb', line 162

def remove_li_class?(node)
  node['class'] != 'task-list-item' &&
    node['class'] != 'inapplicable task-list-item'
end

Returns:

  • (Boolean)


132
133
134
# File 'lib/banzai/filter/sanitization_filter.rb', line 132

def remove_link_class?(node)
  node['class'] != 'anchor'
end

.remove_non_tasklist_inputs(env) ⇒ Object



194
195
196
197
198
199
200
201
202
# File 'lib/banzai/filter/sanitization_filter.rb', line 194

def remove_non_tasklist_inputs(env)
  node = env[:node]

  return unless node.name == 'input'

  return if node['type'] == 'checkbox' && node['class'] == 'task-list-item-checkbox' && node.parent.name == 'li'

  node.remove
end

.remove_p_class?(node) ⇒ Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/banzai/filter/sanitization_filter.rb', line 144

def remove_p_class?(node)
  node['class'] != 'markdown-alert-title'
end

.remove_span_class?(node) ⇒ Boolean

Returns:

  • (Boolean)


148
149
150
151
152
# File 'lib/banzai/filter/sanitization_filter.rb', line 148

def remove_span_class?(node)
  return true unless node['class'].include?('idiff')

  (node['class'].split - ALLOWED_IDIFF_CLASSES).present?
end

.remove_ul_ol_class?(node) ⇒ Boolean

Returns:

  • (Boolean)


158
159
160
# File 'lib/banzai/filter/sanitization_filter.rb', line 158

def remove_ul_ol_class?(node)
  node['class'] != 'task-list'
end

.remove_unsafe_classes(env) ⇒ Object

rubocop:disable Metrics/CyclomaticComplexity – dispatch method.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/banzai/filter/sanitization_filter.rb', line 107

def remove_unsafe_classes(env) # rubocop:disable Metrics/CyclomaticComplexity -- dispatch method.
  node = env[:node]

  return unless node.has_attribute?('class')

  case node.name
  when 'a'
    node.remove_attribute('class') if remove_link_class?(node)
  when 'div'
    node.remove_attribute('class') if remove_div_class?(node)
  when 'p'
    node.remove_attribute('class') if remove_p_class?(node)
  when 'span'
    node.remove_attribute('class') if remove_span_class?(node)
  when 'code'
    node.remove_attribute('class') if remove_code_class?(node)
  when 'ul', 'ol'
    node.remove_attribute('class') if remove_ul_ol_class?(node)
  when 'li'
    node.remove_attribute('class') if remove_li_class?(node)
  when 'input'
    node.remove_attribute('class') if remove_input_class?(node)
  end
end

.remove_unsafe_table_style(env) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/banzai/filter/sanitization_filter.rb', line 94

def remove_unsafe_table_style(env)
  node = env[:node]

  return unless node.name == 'th' || node.name == 'td'
  return unless node.has_attribute?('style')

  if node['style'] =~ TABLE_ALIGNMENT_PATTERN
    node['style'] = "text-align: #{$~[:alignment]}"
  else
    node.remove_attribute('style')
  end
end

Instance Method Details

#customize_allowlist(allowlist) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/banzai/filter/sanitization_filter.rb', line 14

def customize_allowlist(allowlist)
  allowlist[:allow_comments] = context[:allow_comments]

  allow_table_alignment(allowlist)
  allow_json_table_attributes(allowlist)
  allow_sourcepos_and_escaped_char(allowlist)
  allow_id_attributes(allowlist)
  allow_class_attributes(allowlist)
  allow_section_footnotes(allowlist)
  allow_anchor_data_heading_content(allowlist)
  allow_tasklists(allowlist)

  allowlist
end