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 +4 -4
- data/CHANGELOG.md +54 -0
- data/README.md +3 -2
- data/lib/rails/html/sanitizer/version.rb +1 -1
- data/lib/rails/html/sanitizer.rb +5 -4
- data/lib/rails/html/scrubbers.rb +2 -14
- metadata +13 -15
- data/test/rails_api_test.rb +0 -101
- data/test/sanitizer_test.rb +0 -1284
- data/test/scrubbers_test.rb +0 -294
- data/test/test_helper.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c54afd99a374f11c67eb4b1c8ff543d30bd3ca66781a8fa2452719d781c6a07e
|
|
4
|
+
data.tar.gz: 324612d662c1dba47139fba7e1b976384bdc3a616b0d51bf6779d9b343fad2e0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
238
|
-
| 1.
|
|
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
|
|
data/lib/rails/html/sanitizer.rb
CHANGED
|
@@ -154,7 +154,7 @@ module Rails
|
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
def initialize(prune: false)
|
|
157
|
-
@
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
data/lib/rails/html/scrubbers.rb
CHANGED
|
@@ -160,21 +160,9 @@ module Rails
|
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
def scrub_attribute(node, attr_node)
|
|
163
|
-
attr_name =
|
|
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::
|
|
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.
|
|
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.
|
|
122
|
-
documentation_uri: https://www.rubydoc.info/gems/rails-html-sanitizer/1.7.
|
|
123
|
-
source_code_uri: https://github.com/rails/rails-html-sanitizer/tree/v1.7.
|
|
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.
|
|
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.
|
|
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: []
|
data/test/rails_api_test.rb
DELETED
|
@@ -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
|