rails-html-sanitizer 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e73c95bdfd00d65afcc40a3ef436fe4bab7b7571e62b789a877ea2b201a2740
4
- data.tar.gz: 9ac916682a1d0b3b6f45059f5509a1f7785349e0c08102fac6cb1539bff0db3f
3
+ metadata.gz: c54afd99a374f11c67eb4b1c8ff543d30bd3ca66781a8fa2452719d781c6a07e
4
+ data.tar.gz: 324612d662c1dba47139fba7e1b976384bdc3a616b0d51bf6779d9b343fad2e0
5
5
  SHA512:
6
- metadata.gz: d70c999e3775bb58adcc8b6b785c49b7f79ea14990042c2a96105cd36b09c8126f25a317e8f9ab920b0aeaaf107e61870443e0afff78ea291ad163e659b043e6
7
- data.tar.gz: 440f779d178582a39723cc22191e7397becdbc2c2fbd36d3af7eac52f66ce722a9f9000f4cae43d46e36451da2e66249667a5a3d02c5914835a85fac6dd98331
6
+ metadata.gz: df37a5efc973fbe8d95f53dc98f08590bf8454f5d0f2d4e0d549aba63181ca0d83ef541b9a451f0c074ce487d7d4bc6eb6c517a4df6d675015caa55fe3468d42
7
+ data.tar.gz: b70b403bb0f4ca342387ca91d454b2efc94da30c2dcc653853a6f2070ca05cbf1c832853022e6fb91bafb672b753e45c1b44d9d84ab3f67af2a41235d55f5f0c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,57 @@
1
+ ## next / unreleased
2
+
3
+
4
+ ## v1.7.2 / 2026-11-02
5
+
6
+ * Deciding whether an SVG `href` or `xlink:href` is a local reference no longer takes quadratic time.
7
+
8
+ `PermitScrubber` matched the attribute value against a pattern that rescanned the value's
9
+ whitespace run from every line start, so an all-whitespace value took seconds to scrub. Only
10
+ Ruby 3.1 and earlier are affected, because Ruby 3.2 introduced linear-time regexp matching.
11
+ Through `PermitScrubber`, applications are only affected if the allowed tags are overridden to
12
+ include an SVG reference element such as `use`; the default configuration is not affected.
13
+
14
+ This change addresses GHSA-cpgf-5mjf-73p7. `PermitScrubber` now applies the html5lib attribute
15
+ value rules by calling `Loofah::HTML5::Scrub.scrub_attribute_value` rather than carrying its own
16
+ copy. The minimum Loofah dependency is now `~> 2.25, >= 2.25.3`.
17
+
18
+ *Mike Dalessio*
19
+
20
+ * rails-html-sanitizer now requires Ruby >= 3.2, because Loofah 2.25.3 requires it.
21
+
22
+ The `1.6.x` and `1.5.x` release branches no longer receive security updates. Every Rails release
23
+ in security support accepts rails-html-sanitizer 1.7 and requires Ruby >= 3.2.
24
+
25
+ *Mike Dalessio*
26
+
27
+ * `SafeListSanitizer` no longer shares a `PermitScrubber` across calls.
28
+
29
+ Previously one sanitizer instance reused a single `PermitScrubber`, assigning its `tags` and
30
+ `attributes` on every call. Action View memoizes one sanitizer per helper module, so two
31
+ concurrent `sanitize` calls with different `tags:` or `attributes:` options could interleave and
32
+ one call could be scrubbed with the other call's allowlist. Each call now builds its own
33
+ `PermitScrubber`.
34
+
35
+ This change addresses GHSA-h7wh-q2qr-458c.
36
+
37
+ *Mike Dalessio*
38
+
39
+
40
+ ## v1.7.1 / 2026-07-15
41
+
42
+ * SVG reference elements now restrict both `href` and `xlink:href` to local references.
43
+
44
+ Previously `PermitScrubber` restricted only `xlink:href` on elements in `SVG_ALLOW_LOCAL_HREF`,
45
+ so a plain `href` attribute on those elements could reference an external document. Applications
46
+ are only affected if the allowed tags are overridden to include an SVG reference element such as
47
+ `use`; the default configuration is not affected.
48
+
49
+ This change addresses GHSA-cj75-f6xr-r4g7 (CVE requested). The minimum Loofah dependency is now
50
+ `~> 2.25, >= 2.25.2`.
51
+
52
+ *Mike Dalessio*
53
+
54
+
1
55
  ## v1.7.0 / 2026-02-24
2
56
 
3
57
  * Add `Rails::HTML::Sanitizer.allowed_uri?` which delegates to `Loofah::HTML5::Scrub.allowed_uri?`,
data/README.md CHANGED
@@ -234,8 +234,9 @@ Or install it yourself as:
234
234
 
235
235
  | branch | ruby support | actively maintained | security support |
236
236
  |--------|--------------|---------------------|----------------------------------------|
237
- | 1.6.x | >= 2.7 | yes | yes |
238
- | 1.5.x | >= 2.5 | no | while Rails 6.1 is in security support |
237
+ | 1.7.x | >= 3.2 | yes | yes |
238
+ | 1.6.x | >= 2.7 | no | no |
239
+ | 1.5.x | >= 2.5 | no | no |
239
240
  | 1.4.x | >= 1.8.7 | no | no |
240
241
 
241
242
 
@@ -3,7 +3,7 @@
3
3
  module Rails
4
4
  module HTML
5
5
  class Sanitizer
6
- VERSION = "1.7.0"
6
+ VERSION = "1.7.2"
7
7
  end
8
8
  end
9
9
  end
@@ -154,7 +154,7 @@ module Rails
154
154
  end
155
155
 
156
156
  def initialize(prune: false)
157
- @permit_scrubber = PermitScrubber.new(prune: prune)
157
+ @prune = prune
158
158
  end
159
159
 
160
160
  def scrub(fragment, options = {})
@@ -162,9 +162,10 @@ module Rails
162
162
  # No duck typing, Loofah ensures subclass of Loofah::Scrubber
163
163
  fragment.scrub!(scrubber)
164
164
  elsif allowed_tags(options) || allowed_attributes(options)
165
- @permit_scrubber.tags = allowed_tags(options)
166
- @permit_scrubber.attributes = allowed_attributes(options)
167
- fragment.scrub!(@permit_scrubber)
165
+ permit_scrubber = PermitScrubber.new(prune: @prune)
166
+ permit_scrubber.tags = allowed_tags(options)
167
+ permit_scrubber.attributes = allowed_attributes(options)
168
+ fragment.scrub!(permit_scrubber)
168
169
  else
169
170
  fragment.scrub!(:strip)
170
171
  end
@@ -160,21 +160,9 @@ module Rails
160
160
  end
161
161
 
162
162
  def scrub_attribute(node, attr_node)
163
- attr_name = if attr_node.namespace
164
- "#{attr_node.namespace.prefix}:#{attr_node.node_name}"
165
- else
166
- attr_node.node_name
167
- end
168
-
169
- return if Loofah::HTML5::SafeList::ATTR_VAL_IS_URI.include?(attr_name) && Loofah::HTML5::Scrub.scrub_uri_attribute(attr_node)
163
+ attr_name = Loofah::HTML5::Scrub.prefixed_attribute_name(attr_node)
170
164
 
171
- if Loofah::HTML5::SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
172
- Loofah::HTML5::Scrub.scrub_attribute_that_allows_local_ref(attr_node)
173
- end
174
-
175
- if Loofah::HTML5::SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) && attr_name == "xlink:href" && attr_node.value =~ /^\s*[^#\s].*/m
176
- attr_node.remove
177
- end
165
+ return if Loofah::HTML5::Scrub.scrub_attribute_value(node, attr_node, attr_name)
178
166
 
179
167
  node.remove_attribute(attr_node.name) if attr_name == "src" && attr_node.value !~ /[^[:space:]]/
180
168
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-html-sanitizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael Mendonça França
@@ -18,6 +18,9 @@ dependencies:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: '2.25'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.25.3
21
24
  type: :runtime
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -25,6 +28,9 @@ dependencies:
25
28
  - - "~>"
26
29
  - !ruby/object:Gem::Version
27
30
  version: '2.25'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.25.3
28
34
  - !ruby/object:Gem::Dependency
29
35
  name: nokogiri
30
36
  requirement: !ruby/object:Gem::Requirement
@@ -109,18 +115,14 @@ files:
109
115
  - lib/rails/html/sanitizer.rb
110
116
  - lib/rails/html/sanitizer/version.rb
111
117
  - lib/rails/html/scrubbers.rb
112
- - test/rails_api_test.rb
113
- - test/sanitizer_test.rb
114
- - test/scrubbers_test.rb
115
- - test/test_helper.rb
116
118
  homepage: https://github.com/rails/rails-html-sanitizer
117
119
  licenses:
118
120
  - MIT
119
121
  metadata:
120
122
  bug_tracker_uri: https://github.com/rails/rails-html-sanitizer/issues
121
- changelog_uri: https://github.com/rails/rails-html-sanitizer/blob/v1.7.0/CHANGELOG.md
122
- documentation_uri: https://www.rubydoc.info/gems/rails-html-sanitizer/1.7.0
123
- source_code_uri: https://github.com/rails/rails-html-sanitizer/tree/v1.7.0
123
+ changelog_uri: https://github.com/rails/rails-html-sanitizer/blob/v1.7.2/CHANGELOG.md
124
+ documentation_uri: https://www.rubydoc.info/gems/rails-html-sanitizer/1.7.2
125
+ source_code_uri: https://github.com/rails/rails-html-sanitizer/tree/v1.7.2
124
126
  rdoc_options: []
125
127
  require_paths:
126
128
  - lib
@@ -128,18 +130,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
130
  requirements:
129
131
  - - ">="
130
132
  - !ruby/object:Gem::Version
131
- version: 2.7.0
133
+ version: 3.2.0
132
134
  required_rubygems_version: !ruby/object:Gem::Requirement
133
135
  requirements:
134
136
  - - ">="
135
137
  - !ruby/object:Gem::Version
136
138
  version: '0'
137
139
  requirements: []
138
- rubygems_version: 4.0.3
140
+ rubygems_version: 4.0.20
139
141
  specification_version: 4
140
142
  summary: This gem is responsible to sanitize HTML fragments in Rails applications.
141
- test_files:
142
- - test/rails_api_test.rb
143
- - test/sanitizer_test.rb
144
- - test/scrubbers_test.rb
145
- - test/test_helper.rb
143
+ test_files: []
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "test_helper"
4
-
5
- class RailsApiTest < Minitest::Test
6
- def test_html_module_name_alias
7
- assert_equal(Rails::Html, Rails::HTML)
8
- assert_equal("Rails::HTML", Rails::Html.name)
9
- assert_equal("Rails::HTML", Rails::HTML.name)
10
- end
11
-
12
- def test_html_scrubber_class_names
13
- assert(Rails::Html::PermitScrubber)
14
- assert(Rails::Html::TargetScrubber)
15
- assert(Rails::Html::TextOnlyScrubber)
16
- assert(Rails::Html::Sanitizer)
17
- end
18
-
19
- def test_best_supported_vendor_when_html5_is_not_supported_returns_html4
20
- Rails::HTML::Sanitizer.stub(:html5_support?, false) do
21
- assert_equal(Rails::HTML4::Sanitizer, Rails::HTML::Sanitizer.best_supported_vendor)
22
- end
23
- end
24
-
25
- def test_best_supported_vendor_when_html5_is_supported_returns_html5
26
- skip("no HTML5 support on this platform") unless Rails::HTML::Sanitizer.html5_support?
27
-
28
- Rails::HTML::Sanitizer.stub(:html5_support?, true) do
29
- assert_equal(Rails::HTML5::Sanitizer, Rails::HTML::Sanitizer.best_supported_vendor)
30
- end
31
- end
32
-
33
- def test_html4_sanitizer_alias_full
34
- assert_equal(Rails::HTML4::FullSanitizer, Rails::HTML::FullSanitizer)
35
- assert_equal("Rails::HTML4::FullSanitizer", Rails::HTML::FullSanitizer.name)
36
- end
37
-
38
- def test_html4_sanitizer_alias_link
39
- assert_equal(Rails::HTML4::LinkSanitizer, Rails::HTML::LinkSanitizer)
40
- assert_equal("Rails::HTML4::LinkSanitizer", Rails::HTML::LinkSanitizer.name)
41
- end
42
-
43
- def test_html4_sanitizer_alias_safe_list
44
- assert_equal(Rails::HTML4::SafeListSanitizer, Rails::HTML::SafeListSanitizer)
45
- assert_equal("Rails::HTML4::SafeListSanitizer", Rails::HTML::SafeListSanitizer.name)
46
- end
47
-
48
- def test_html4_full_sanitizer
49
- assert_equal(Rails::HTML4::FullSanitizer, Rails::HTML::Sanitizer.full_sanitizer)
50
- assert_equal(Rails::HTML4::FullSanitizer, Rails::HTML4::Sanitizer.full_sanitizer)
51
- end
52
-
53
- def test_html4_link_sanitizer
54
- assert_equal(Rails::HTML4::LinkSanitizer, Rails::HTML::Sanitizer.link_sanitizer)
55
- assert_equal(Rails::HTML4::LinkSanitizer, Rails::HTML4::Sanitizer.link_sanitizer)
56
- end
57
-
58
- def test_html4_safe_list_sanitizer
59
- assert_equal(Rails::HTML4::SafeListSanitizer, Rails::HTML::Sanitizer.safe_list_sanitizer)
60
- assert_equal(Rails::HTML4::SafeListSanitizer, Rails::HTML4::Sanitizer.safe_list_sanitizer)
61
- end
62
-
63
- def test_html4_white_list_sanitizer
64
- assert_equal(Rails::HTML4::SafeListSanitizer, Rails::HTML::Sanitizer.white_list_sanitizer)
65
- assert_equal(Rails::HTML4::SafeListSanitizer, Rails::HTML4::Sanitizer.white_list_sanitizer)
66
- end
67
-
68
- def test_html5_full_sanitizer
69
- skip("no HTML5 support on this platform") unless Rails::HTML::Sanitizer.html5_support?
70
- assert_equal(Rails::HTML5::FullSanitizer, Rails::HTML5::Sanitizer.full_sanitizer)
71
- end
72
-
73
- def test_html5_link_sanitizer
74
- skip("no HTML5 support on this platform") unless Rails::HTML::Sanitizer.html5_support?
75
- assert_equal(Rails::HTML5::LinkSanitizer, Rails::HTML5::Sanitizer.link_sanitizer)
76
- end
77
-
78
- def test_html5_safe_list_sanitizer
79
- skip("no HTML5 support on this platform") unless Rails::HTML::Sanitizer.html5_support?
80
- assert_equal(Rails::HTML5::SafeListSanitizer, Rails::HTML5::Sanitizer.safe_list_sanitizer)
81
- end
82
-
83
- def test_html5_white_list_sanitizer
84
- skip("no HTML5 support on this platform") unless Rails::HTML::Sanitizer.html5_support?
85
- assert_equal(Rails::HTML5::SafeListSanitizer, Rails::HTML5::Sanitizer.white_list_sanitizer)
86
- end
87
-
88
- def test_allowed_uri_returns_true_for_allowed_protocols
89
- assert(Rails::HTML::Sanitizer.allowed_uri?("https://example.com"))
90
- assert(Rails::HTML::Sanitizer.allowed_uri?("http://example.com"))
91
- assert(Rails::HTML::Sanitizer.allowed_uri?("mailto:user@example.com"))
92
- end
93
-
94
- def test_allowed_uri_returns_false_for_disallowed_protocols
95
- refute(Rails::HTML::Sanitizer.allowed_uri?("javascript:alert(1)"))
96
- end
97
-
98
- def test_allowed_uri_returns_true_for_relative_uris
99
- assert(Rails::HTML::Sanitizer.allowed_uri?("/relative/path"))
100
- end
101
- end