rack-utf8_sanitizer 1.9.0 → 1.10.0
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/.github/workflows/ci.yml +2 -2
- data/Gemfile +2 -0
- data/README.md +5 -1
- data/Rakefile +2 -0
- data/lib/rack/utf8_sanitizer.rb +30 -23
- data/rack-utf8_sanitizer.gemspec +7 -6
- data/test/test_utf8_sanitizer.rb +84 -24
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c33079dde3e7e3efb8c46742a50303be620b316243b5e11c5f026a89ce29bf7d
|
4
|
+
data.tar.gz: 537ff74a7f0c3edfe1bc3904540ae3c95c4ed08f15198a8872bf25a055376673
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 787fbd5b17de52dbd26bcef3e64acb359d026eb6eeb3f5900fa0fe641980235f795c0fa2067693ab2630b2781e8d8a9c03fda141e7ad2fbca6c65f663b571795
|
7
|
+
data.tar.gz: be57486cc8be56299013bf3b101363702a8bc2af26746293e6661dd762b11737a5ae76c1f14373d5200772a3e229b19c7687f3c1855fc1950256cf4e750e3ca8
|
data/.github/workflows/ci.yml
CHANGED
@@ -10,10 +10,10 @@ jobs:
|
|
10
10
|
strategy:
|
11
11
|
fail-fast: false
|
12
12
|
matrix:
|
13
|
-
ruby: ["2.5", "2.6", "2.7", "3.0", "3.1", "3.2", ruby-head, jruby-9.2, jruby-9.3, jruby-head]
|
13
|
+
ruby: ["2.5", "2.6", "2.7", "3.0", "3.1", "3.2", "3.3", ruby-head, jruby-9.2, jruby-9.3, jruby-head]
|
14
14
|
|
15
15
|
steps:
|
16
|
-
- uses: actions/checkout@
|
16
|
+
- uses: actions/checkout@v4
|
17
17
|
- name: Set up Ruby
|
18
18
|
uses: ruby/setup-ruby@v1
|
19
19
|
with:
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -113,7 +113,7 @@ config.middleware.insert 0, Rack::UTF8Sanitizer, strategy: :exception
|
|
113
113
|
```
|
114
114
|
|
115
115
|
```ruby
|
116
|
-
replace_string = lambda do |_invalid|
|
116
|
+
replace_string = lambda do |_invalid, sanitize_null_bytes: false|
|
117
117
|
Rails.logger.warn('Replacing invalid string')
|
118
118
|
|
119
119
|
'<Bad Encoding>'.freeze
|
@@ -122,6 +122,10 @@ end
|
|
122
122
|
config.middleware.insert 0, Rack::UTF8Sanitizer, strategy: replace_string
|
123
123
|
```
|
124
124
|
|
125
|
+
### Sanitizing Null Bytes
|
126
|
+
|
127
|
+
While null bytes are valid UTF-8, it can be useful to further restrict the valid character set to exclude null bytes. For example, PostgreSQL text columns do not allow storing null bytes. Passing `sanitize_null_bytes: true` in the configuration hash enables sanitizing null bytes, and the two built-in strategies both support this feature. Custom strategies should accept a keyword argument `sanitize_null_bytes` containing this configuration value.
|
128
|
+
|
125
129
|
## Contributing
|
126
130
|
|
127
131
|
1. Fork it
|
data/Rakefile
CHANGED
data/lib/rack/utf8_sanitizer.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'uri'
|
4
5
|
require 'stringio'
|
6
|
+
require 'rack/request'
|
5
7
|
|
6
8
|
module Rack
|
7
9
|
class UTF8Sanitizer
|
8
10
|
StringIO = ::StringIO
|
9
|
-
BAD_REQUEST = [400, { "Content-Type" => "text/plain" }, ["Bad Request"]]
|
10
11
|
NULL_BYTE_REGEX = /\x00/.freeze
|
11
12
|
|
12
13
|
class NullByteInString < StandardError; end
|
@@ -27,29 +28,31 @@ module Rack
|
|
27
28
|
begin
|
28
29
|
env = sanitize(env)
|
29
30
|
rescue EOFError
|
30
|
-
return
|
31
|
+
return [400, { "Content-Type" => "text/plain" }, ["Bad Request"]]
|
31
32
|
end
|
32
33
|
@app.call(env)
|
33
34
|
end
|
34
35
|
|
35
36
|
DEFAULT_STRATEGIES = {
|
36
37
|
replace: lambda do |input, sanitize_null_bytes: false|
|
37
|
-
if sanitize_null_bytes
|
38
|
-
input = input.gsub(NULL_BYTE_REGEX, "")
|
39
|
-
end
|
40
38
|
input.
|
41
39
|
force_encoding(Encoding::ASCII_8BIT).
|
42
40
|
encode!(Encoding::UTF_8,
|
43
41
|
invalid: :replace,
|
44
42
|
undef: :replace)
|
43
|
+
if sanitize_null_bytes
|
44
|
+
input = input.gsub(NULL_BYTE_REGEX, "")
|
45
|
+
end
|
46
|
+
input
|
45
47
|
end,
|
46
48
|
exception: lambda do |input, sanitize_null_bytes: false|
|
47
|
-
if sanitize_null_bytes && input =~ NULL_BYTE_REGEX
|
48
|
-
raise NullByteInString
|
49
|
-
end
|
50
49
|
input.
|
51
50
|
force_encoding(Encoding::ASCII_8BIT).
|
52
51
|
encode!(Encoding::UTF_8)
|
52
|
+
if sanitize_null_bytes && NULL_BYTE_REGEX.match?(input)
|
53
|
+
raise NullByteInString
|
54
|
+
end
|
55
|
+
input
|
53
56
|
end
|
54
57
|
}.freeze
|
55
58
|
|
@@ -62,20 +65,20 @@ module Rack
|
|
62
65
|
ORIGINAL_FULLPATH
|
63
66
|
ORIGINAL_SCRIPT_NAME
|
64
67
|
SERVER_NAME
|
65
|
-
).
|
68
|
+
).freeze
|
66
69
|
|
67
70
|
SANITIZABLE_CONTENT_TYPES = %w(
|
68
71
|
text/plain
|
69
72
|
application/x-www-form-urlencoded
|
70
73
|
application/json
|
71
74
|
text/javascript
|
72
|
-
).
|
75
|
+
).freeze
|
73
76
|
|
74
77
|
URI_ENCODED_CONTENT_TYPES = %w(
|
75
78
|
application/x-www-form-urlencoded
|
76
|
-
).
|
79
|
+
).freeze
|
77
80
|
|
78
|
-
HTTP_ = 'HTTP_'
|
81
|
+
HTTP_ = 'HTTP_'
|
79
82
|
|
80
83
|
def sanitize(env)
|
81
84
|
sanitize_rack_input(env)
|
@@ -113,17 +116,17 @@ module Rack
|
|
113
116
|
end
|
114
117
|
|
115
118
|
def sanitize_rack_input(env)
|
116
|
-
|
117
|
-
|
118
|
-
# Ignoring charset in content type.
|
119
|
-
content_type = env['CONTENT_TYPE']
|
120
|
-
content_type &&= content_type.split(/\s*[;,]\s*/, 2).first
|
121
|
-
content_type &&= content_type.downcase
|
119
|
+
request = Rack::Request.new(env)
|
120
|
+
content_type = request.media_type
|
122
121
|
return unless @sanitizable_content_types.any? {|type| content_type == type }
|
122
|
+
|
123
|
+
charset = request.content_charset
|
124
|
+
return if charset && charset.downcase != 'utf-8'
|
125
|
+
|
123
126
|
uri_encoded = URI_ENCODED_CONTENT_TYPES.any? {|type| content_type == type}
|
124
127
|
|
125
128
|
if env['rack.input']
|
126
|
-
sanitized_input = sanitize_io(env['rack.input'], uri_encoded)
|
129
|
+
sanitized_input = sanitize_io(env['rack.input'], uri_encoded, env['CONTENT_LENGTH']&.to_i)
|
127
130
|
|
128
131
|
env['rack.input'] = sanitized_input
|
129
132
|
env['CONTENT_LENGTH'] &&= sanitized_input.size.to_s
|
@@ -165,8 +168,12 @@ module Rack
|
|
165
168
|
end
|
166
169
|
end
|
167
170
|
|
168
|
-
def sanitize_io(io, uri_encoded = false)
|
169
|
-
input =
|
171
|
+
def sanitize_io(io, uri_encoded = false, content_length = nil)
|
172
|
+
input = if content_length && content_length >= 0
|
173
|
+
io.read(content_length)
|
174
|
+
else
|
175
|
+
io.read
|
176
|
+
end
|
170
177
|
sanitized_input = sanitize_string(strip_byte_order_mark(input))
|
171
178
|
if uri_encoded
|
172
179
|
sanitized_input = sanitize_uri_encoded_string(sanitized_input).
|
@@ -249,7 +256,7 @@ module Rack
|
|
249
256
|
# Performs the reverse function of `unescape_unreserved`. Unlike
|
250
257
|
# the previous function, we can reuse the logic in URI#encode
|
251
258
|
def escape_unreserved(input)
|
252
|
-
URI::
|
259
|
+
URI::RFC2396_PARSER.escape(input, UNSAFE)
|
253
260
|
end
|
254
261
|
|
255
262
|
def sanitize_string(input)
|
@@ -274,7 +281,7 @@ module Rack
|
|
274
281
|
end
|
275
282
|
end
|
276
283
|
|
277
|
-
UTF8_BOM = "\xef\xbb\xbf".force_encoding(Encoding::BINARY).freeze
|
284
|
+
UTF8_BOM = "\xef\xbb\xbf".dup.force_encoding(Encoding::BINARY).freeze
|
278
285
|
UTF8_BOM_SIZE = UTF8_BOM.bytesize
|
279
286
|
|
280
287
|
def strip_byte_order_mark(input)
|
data/rack-utf8_sanitizer.gemspec
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
Gem::Specification.new do |gem|
|
4
5
|
gem.name = "rack-utf8_sanitizer"
|
5
|
-
gem.version = '1.
|
6
|
-
gem.authors = ["
|
6
|
+
gem.version = '1.10.0'
|
7
|
+
gem.authors = ["Catherine"]
|
7
8
|
gem.license = "MIT"
|
8
9
|
gem.email = ["whitequark@whitequark.org"]
|
9
|
-
gem.description =
|
10
|
-
|
10
|
+
gem.description = "Rack::UTF8Sanitizer is a Rack middleware which cleans up " \
|
11
|
+
"invalid UTF8 characters in request URI and headers."
|
11
12
|
gem.summary = gem.description
|
12
|
-
gem.homepage = "
|
13
|
+
gem.homepage = "https://github.com/whitequark/rack-utf8_sanitizer"
|
13
14
|
|
14
15
|
gem.files = `git ls-files`.split($/)
|
15
16
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
17
|
gem.require_paths = ["lib"]
|
17
18
|
|
18
|
-
gem.required_ruby_version = '>=
|
19
|
+
gem.required_ruby_version = '>= 2.3'
|
19
20
|
|
20
21
|
gem.add_dependency "rack", '>= 1.0', '< 4.0'
|
21
22
|
|
data/test/test_utf8_sanitizer.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding:ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'bacon/colored_output'
|
4
5
|
require 'cgi'
|
@@ -31,7 +32,7 @@ describe Rack::UTF8Sanitizer do
|
|
31
32
|
|
32
33
|
describe "with invalid host input" do
|
33
34
|
it "sanitizes host entity (SERVER_NAME)" do
|
34
|
-
host = "host\xD0".force_encoding('UTF-8')
|
35
|
+
host = "host\xD0".dup.force_encoding('UTF-8')
|
35
36
|
env = @app.({ "SERVER_NAME" => host })
|
36
37
|
result = env["SERVER_NAME"]
|
37
38
|
|
@@ -42,8 +43,8 @@ describe Rack::UTF8Sanitizer do
|
|
42
43
|
|
43
44
|
describe "with invalid UTF-8 input" do
|
44
45
|
before do
|
45
|
-
@plain_input = "foo\xe0".force_encoding('UTF-8')
|
46
|
-
@uri_input = "http://bar/foo%E0".force_encoding('UTF-8')
|
46
|
+
@plain_input = "foo\xe0".dup.force_encoding('UTF-8')
|
47
|
+
@uri_input = "http://bar/foo%E0".dup.force_encoding('UTF-8')
|
47
48
|
end
|
48
49
|
|
49
50
|
behaves_like :does_sanitize_plain
|
@@ -52,7 +53,7 @@ describe Rack::UTF8Sanitizer do
|
|
52
53
|
|
53
54
|
describe "with invalid, incorrectly percent-encoded UTF-8 URI input" do
|
54
55
|
before do
|
55
|
-
@uri_input = "http://bar/foo%E0\xe0".force_encoding('UTF-8')
|
56
|
+
@uri_input = "http://bar/foo%E0\xe0".dup.force_encoding('UTF-8')
|
56
57
|
end
|
57
58
|
|
58
59
|
behaves_like :does_sanitize_uri
|
@@ -100,8 +101,8 @@ describe Rack::UTF8Sanitizer do
|
|
100
101
|
|
101
102
|
describe "with valid UTF-8 input" do
|
102
103
|
before do
|
103
|
-
@plain_input = "foo bar лол".force_encoding('UTF-8')
|
104
|
-
@uri_input = "http://bar/foo+bar+%D0%BB%D0%BE%D0%BB".force_encoding('UTF-8')
|
104
|
+
@plain_input = "foo bar лол".dup.force_encoding('UTF-8')
|
105
|
+
@uri_input = "http://bar/foo+bar+%D0%BB%D0%BE%D0%BB".dup.force_encoding('UTF-8')
|
105
106
|
end
|
106
107
|
|
107
108
|
behaves_like :identity_plain
|
@@ -109,7 +110,7 @@ describe Rack::UTF8Sanitizer do
|
|
109
110
|
|
110
111
|
describe "with URI characters from reserved range" do
|
111
112
|
before do
|
112
|
-
@uri_input = "http://bar/foo+%2F%3A+bar+%D0%BB%D0%BE%D0%BB".force_encoding('UTF-8')
|
113
|
+
@uri_input = "http://bar/foo+%2F%3A+bar+%D0%BB%D0%BE%D0%BB".dup.force_encoding('UTF-8')
|
113
114
|
end
|
114
115
|
|
115
116
|
behaves_like :identity_uri
|
@@ -118,7 +119,7 @@ describe Rack::UTF8Sanitizer do
|
|
118
119
|
|
119
120
|
describe "with valid, not percent-encoded UTF-8 URI input" do
|
120
121
|
before do
|
121
|
-
@uri_input = "http://bar/foo+bar+лол".force_encoding('UTF-8')
|
122
|
+
@uri_input = "http://bar/foo+bar+лол".dup.force_encoding('UTF-8')
|
122
123
|
@encoded = "http://bar/foo+bar+#{CGI.escape("лол")}"
|
123
124
|
end
|
124
125
|
|
@@ -152,8 +153,8 @@ describe Rack::UTF8Sanitizer do
|
|
152
153
|
|
153
154
|
describe "with frozen strings" do
|
154
155
|
before do
|
155
|
-
@plain_input = "bar baz"
|
156
|
-
@uri_input = "http://bar/bar+baz"
|
156
|
+
@plain_input = "bar baz"
|
157
|
+
@uri_input = "http://bar/bar+baz"
|
157
158
|
end
|
158
159
|
|
159
160
|
it "preserves the frozen? status of input" do
|
@@ -165,9 +166,24 @@ describe Rack::UTF8Sanitizer do
|
|
165
166
|
end
|
166
167
|
end
|
167
168
|
|
169
|
+
describe "with mutable strings" do
|
170
|
+
before do
|
171
|
+
@plain_input = "bar baz".dup
|
172
|
+
@uri_input = "http://bar/bar+baz".dup
|
173
|
+
end
|
174
|
+
|
175
|
+
it "preserves the frozen? status of input" do
|
176
|
+
env = @app.({ "HTTP_USER_AGENT" => @plain_input,
|
177
|
+
"REQUEST_PATH" => @uri_input })
|
178
|
+
|
179
|
+
env["HTTP_USER_AGENT"].should.not.be.frozen
|
180
|
+
env["REQUEST_PATH"].should.not.be.frozen
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
168
184
|
describe "with symbols in the env" do
|
169
185
|
before do
|
170
|
-
@uri_input = "http://bar/foo%E0\xe0".force_encoding('UTF-8')
|
186
|
+
@uri_input = "http://bar/foo%E0\xe0".dup.force_encoding('UTF-8')
|
171
187
|
end
|
172
188
|
|
173
189
|
it "sanitizes REQUEST_PATH with invalid UTF-8 URI input" do
|
@@ -183,7 +199,7 @@ describe Rack::UTF8Sanitizer do
|
|
183
199
|
|
184
200
|
describe "with form data" do
|
185
201
|
def request_env
|
186
|
-
@plain_input = "foo bar лол".force_encoding('UTF-8')
|
202
|
+
@plain_input = "foo bar лол".dup.force_encoding('UTF-8')
|
187
203
|
{
|
188
204
|
"REQUEST_METHOD" => "POST",
|
189
205
|
"CONTENT_TYPE" => "application/x-www-form-urlencoded;foo=bar",
|
@@ -193,7 +209,7 @@ describe Rack::UTF8Sanitizer do
|
|
193
209
|
end
|
194
210
|
|
195
211
|
def sanitize_form_data(request_env = request_env())
|
196
|
-
@uri_input = "http://bar/foo+%2F%3A+bar+%D0%BB%D0%BE%D0%BB".force_encoding('UTF-8')
|
212
|
+
@uri_input = "http://bar/foo+%2F%3A+bar+%D0%BB%D0%BE%D0%BB".dup.force_encoding('UTF-8')
|
197
213
|
@response_env = @app.(request_env)
|
198
214
|
sanitized_input = @response_env['rack.input'].read
|
199
215
|
|
@@ -219,6 +235,16 @@ describe Rack::UTF8Sanitizer do
|
|
219
235
|
@response_env.should == [400, {"Content-Type"=>"text/plain"}, ["Bad Request"]]
|
220
236
|
end
|
221
237
|
|
238
|
+
it "Bad Request response can safety be mutated" do
|
239
|
+
@rack_input = BrokenIO.new
|
240
|
+
response_env = @app.(request_env)
|
241
|
+
response_env.should == [400, {"Content-Type"=>"text/plain"}, ["Bad Request"]]
|
242
|
+
response_env[1]["Set-Cookie"] = "you_are_admin"
|
243
|
+
|
244
|
+
response_env = @app.(request_env)
|
245
|
+
response_env[1]["Set-Cookie"].should == nil
|
246
|
+
end
|
247
|
+
|
222
248
|
it "sanitizes StringIO rack.input" do
|
223
249
|
input = "foo=bla&quux=bar"
|
224
250
|
@rack_input = StringIO.new input
|
@@ -252,6 +278,18 @@ describe Rack::UTF8Sanitizer do
|
|
252
278
|
end
|
253
279
|
end
|
254
280
|
|
281
|
+
it "sanitizes the rack body if the charset is present and utf-8" do
|
282
|
+
input = "name=#{CGI.escape("まつもと")}"
|
283
|
+
@rack_input = StringIO.new input
|
284
|
+
|
285
|
+
env = request_env.update('CONTENT_TYPE' => "application/x-www-form-urlencoded; charset=utf-8")
|
286
|
+
sanitize_form_data(env) do |sanitized_input|
|
287
|
+
sanitized_input.encoding.should == Encoding::UTF_8
|
288
|
+
sanitized_input.should.be.valid_encoding
|
289
|
+
sanitized_input.should == input
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
255
293
|
it "strip UTF-8 BOM from StringIO rack.input" do
|
256
294
|
input = %(\xef\xbb\xbf{"Hello": "World"})
|
257
295
|
@rack_input = StringIO.new input
|
@@ -327,6 +365,18 @@ describe Rack::UTF8Sanitizer do
|
|
327
365
|
end
|
328
366
|
end
|
329
367
|
|
368
|
+
it "does not sanitize the rack body if the charset is present and not utf-8" do
|
369
|
+
input = "name=".encode("Shift_JIS") + CGI.escape("まつもと".encode("Shift_JIS", "UTF-8"))
|
370
|
+
@rack_input = StringIO.new input
|
371
|
+
|
372
|
+
env = request_env.update('CONTENT_TYPE' => "application/x-www-form-urlencoded; charset=Shift_JIS")
|
373
|
+
sanitize_form_data(env) do |sanitized_input|
|
374
|
+
sanitized_input.encoding.should == Encoding::SHIFT_JIS
|
375
|
+
sanitized_input.should.be.valid_encoding
|
376
|
+
sanitized_input.should == input
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
330
380
|
it "adjusts content-length when replacing input" do
|
331
381
|
input = "foo=bla&quux=bar\xED"
|
332
382
|
@rack_input = StringIO.new input
|
@@ -351,25 +401,25 @@ describe Rack::UTF8Sanitizer do
|
|
351
401
|
|
352
402
|
it "optionally sanitizes null bytes with the replace strategy" do
|
353
403
|
@app = Rack::UTF8Sanitizer.new(-> env { env }, sanitize_null_bytes: true)
|
354
|
-
input =
|
404
|
+
input = "foo=bla\xED&quux=bar\x00"
|
355
405
|
@rack_input = StringIO.new input
|
356
406
|
|
357
407
|
sanitize_form_data do |sanitized_input|
|
358
408
|
sanitized_input.encoding.should == Encoding::UTF_8
|
359
409
|
sanitized_input.should.be.valid_encoding
|
360
|
-
sanitized_input.should == "foo=bla&quux=bar"
|
410
|
+
sanitized_input.should == "foo=bla%EF%BF%BD&quux=bar"
|
361
411
|
end
|
362
412
|
end
|
363
413
|
|
364
414
|
it "optionally sanitizes encoded null bytes with the replace strategy" do
|
365
415
|
@app = Rack::UTF8Sanitizer.new(-> env { env }, sanitize_null_bytes: true)
|
366
|
-
input =
|
416
|
+
input = "foo=bla%ED&quux=bar%00"
|
367
417
|
@rack_input = StringIO.new input
|
368
418
|
|
369
419
|
sanitize_form_data do |sanitized_input|
|
370
420
|
sanitized_input.encoding.should == Encoding::UTF_8
|
371
421
|
sanitized_input.should.be.valid_encoding
|
372
|
-
sanitized_input.should == "foo=bla&quux=bar"
|
422
|
+
sanitized_input.should == "foo=bla%EF%BF%BD&quux=bar"
|
373
423
|
end
|
374
424
|
end
|
375
425
|
|
@@ -392,6 +442,16 @@ describe Rack::UTF8Sanitizer do
|
|
392
442
|
sanitize_form_data
|
393
443
|
end
|
394
444
|
end
|
445
|
+
|
446
|
+
it "gives precedence to encoding errors with the exception strategy and null byte sanitisation" do
|
447
|
+
@app = Rack::UTF8Sanitizer.new(-> env { env }, sanitize_null_bytes: true, strategy: :exception)
|
448
|
+
input = "foo=bla\x00&quux=bar\xED"
|
449
|
+
@rack_input = StringIO.new input
|
450
|
+
|
451
|
+
should.raise(EncodingError) do
|
452
|
+
sanitize_form_data
|
453
|
+
end
|
454
|
+
end
|
395
455
|
end
|
396
456
|
|
397
457
|
describe "with custom content-type" do
|
@@ -424,7 +484,7 @@ describe Rack::UTF8Sanitizer do
|
|
424
484
|
|
425
485
|
describe "with custom content-type" do
|
426
486
|
def request_env
|
427
|
-
@plain_input = "foo bar лол".force_encoding('UTF-8')
|
487
|
+
@plain_input = "foo bar лол".dup.force_encoding('UTF-8')
|
428
488
|
{
|
429
489
|
"REQUEST_METHOD" => "POST",
|
430
490
|
"CONTENT_TYPE" => "application/vnd.api+json",
|
@@ -434,7 +494,7 @@ describe Rack::UTF8Sanitizer do
|
|
434
494
|
end
|
435
495
|
|
436
496
|
def sanitize_data(request_env = request_env())
|
437
|
-
@uri_input = "http://bar/foo+%2F%3A+bar+%D0%BB%D0%BE%D0%BB".force_encoding('UTF-8')
|
497
|
+
@uri_input = "http://bar/foo+%2F%3A+bar+%D0%BB%D0%BE%D0%BB".dup.force_encoding('UTF-8')
|
438
498
|
@response_env = @app.(request_env)
|
439
499
|
sanitized_input = @response_env['rack.input'].read
|
440
500
|
|
@@ -508,7 +568,7 @@ describe Rack::UTF8Sanitizer do
|
|
508
568
|
|
509
569
|
describe "with only and/or except options" do
|
510
570
|
before do
|
511
|
-
@plain_input = "foo\xe0".force_encoding('UTF-8')
|
571
|
+
@plain_input = "foo\xe0".dup.force_encoding('UTF-8')
|
512
572
|
end
|
513
573
|
|
514
574
|
def request_env
|
@@ -565,7 +625,7 @@ describe Rack::UTF8Sanitizer do
|
|
565
625
|
|
566
626
|
describe "with custom strategy" do
|
567
627
|
def request_env
|
568
|
-
@plain_input = "foo bar лол".force_encoding('UTF-8')
|
628
|
+
@plain_input = "foo bar лол".dup.force_encoding('UTF-8')
|
569
629
|
{
|
570
630
|
"REQUEST_METHOD" => "POST",
|
571
631
|
"CONTENT_TYPE" => "application/json",
|
@@ -575,7 +635,7 @@ describe Rack::UTF8Sanitizer do
|
|
575
635
|
end
|
576
636
|
|
577
637
|
def sanitize_data(request_env = request_env())
|
578
|
-
@uri_input = "http://bar/foo+%2F%3A+bar+%D0%BB%D0%BE%D0%BB".force_encoding('UTF-8')
|
638
|
+
@uri_input = "http://bar/foo+%2F%3A+bar+%D0%BB%D0%BE%D0%BB".dup.force_encoding('UTF-8')
|
579
639
|
@response_env = @app.(request_env)
|
580
640
|
sanitized_input = @response_env['rack.input'].read
|
581
641
|
|
@@ -609,7 +669,7 @@ describe Rack::UTF8Sanitizer do
|
|
609
669
|
it "accepts a proc as a strategy" do
|
610
670
|
truncate = -> (input, sanitize_null_bytes:) do
|
611
671
|
sanitize_null_bytes.should == false
|
612
|
-
|
672
|
+
"replace".dup.force_encoding(Encoding::UTF_8)
|
613
673
|
end
|
614
674
|
|
615
675
|
@app = Rack::UTF8Sanitizer.new(-> env { env }, strategy: truncate)
|
@@ -628,7 +688,7 @@ describe Rack::UTF8Sanitizer do
|
|
628
688
|
it "accepts a proc as a strategy and passes along sanitize_null_bytes" do
|
629
689
|
truncate = -> (input, sanitize_null_bytes:) do
|
630
690
|
sanitize_null_bytes.should == true
|
631
|
-
|
691
|
+
"replace".dup.force_encoding(Encoding::UTF_8)
|
632
692
|
end
|
633
693
|
|
634
694
|
@app = Rack::UTF8Sanitizer.new(-> env { env }, sanitize_null_bytes: true, strategy: truncate)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-utf8_sanitizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Catherine
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -93,7 +93,7 @@ files:
|
|
93
93
|
- lib/rack/utf8_sanitizer.rb
|
94
94
|
- rack-utf8_sanitizer.gemspec
|
95
95
|
- test/test_utf8_sanitizer.rb
|
96
|
-
homepage:
|
96
|
+
homepage: https://github.com/whitequark/rack-utf8_sanitizer
|
97
97
|
licenses:
|
98
98
|
- MIT
|
99
99
|
metadata: {}
|
@@ -105,14 +105,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
105
|
requirements:
|
106
106
|
- - ">="
|
107
107
|
- !ruby/object:Gem::Version
|
108
|
-
version:
|
108
|
+
version: '2.3'
|
109
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
110
|
requirements:
|
111
111
|
- - ">="
|
112
112
|
- !ruby/object:Gem::Version
|
113
113
|
version: '0'
|
114
114
|
requirements: []
|
115
|
-
rubygems_version: 3.
|
115
|
+
rubygems_version: 3.3.15
|
116
116
|
signing_key:
|
117
117
|
specification_version: 4
|
118
118
|
summary: Rack::UTF8Sanitizer is a Rack middleware which cleans up invalid UTF8 characters
|