sinatra-my-params 0.0.10 → 0.0.11
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/lib/permit_params.rb +37 -5
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6b1f2c6fc4b59ce732264ff359866988b740c93b3dd585c43dcd57ee0834a8a1
|
|
4
|
+
data.tar.gz: b9f6692a739211d236c32b1658a66dd71b2f0e4e40ecb22010d63031bc7c03a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 906f99e74e6bede4cbf4ee24dbf281a08d1c4c0856ea18a2434e445c01f0f028aa5b165e8a3219716043b4be82141744e2a10894b5aada1f677c9e0960d504cc
|
|
7
|
+
data.tar.gz: a07cdd0764f4f0c39bf83c17aca176204d9469ebc2583bbba7804a12d55f3fc60e8f07896536df5a7fc4f8961082ed91d05e1da8e9a9a9a2cb05ecd8bcc0557c
|
data/lib/permit_params.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'date'
|
|
4
|
+
require 'time'
|
|
5
|
+
|
|
3
6
|
module PermitParams
|
|
4
7
|
class InvalidParameterError < StandardError
|
|
5
8
|
attr_accessor :param, :options
|
|
@@ -8,7 +11,7 @@ module PermitParams
|
|
|
8
11
|
def permitted_params(params, permitted = {}, strong_validation = false, options = {})
|
|
9
12
|
return params if permitted.empty?
|
|
10
13
|
|
|
11
|
-
coerced_params =
|
|
14
|
+
coerced_params = {}
|
|
12
15
|
|
|
13
16
|
params.each do |key, value|
|
|
14
17
|
next unless permitted?(permitted: permitted, key: key, value: value)
|
|
@@ -30,6 +33,14 @@ module PermitParams
|
|
|
30
33
|
Any = :any
|
|
31
34
|
Shape = :shape
|
|
32
35
|
|
|
36
|
+
# Mirrors the fix Ruby itself shipped for CVE-2021-41817 (ReDoS in
|
|
37
|
+
# Date/Time/DateTime parsing methods): never hand an unbounded,
|
|
38
|
+
# attacker-controlled string to a parser that uses backtracking regexes.
|
|
39
|
+
PARSE_LENGTH_LIMIT = 128
|
|
40
|
+
|
|
41
|
+
DATE_TIME_TYPES = [Date, Time, DateTime].freeze
|
|
42
|
+
NUMERIC_PARSE_TYPES = [Integer, Float].freeze
|
|
43
|
+
|
|
33
44
|
def permitted?(permitted:, key:, value:)
|
|
34
45
|
permitted.keys.map(&:to_s).include?(key.to_s) && !value.nil?
|
|
35
46
|
end
|
|
@@ -44,6 +55,11 @@ module PermitParams
|
|
|
44
55
|
rescue StandardError
|
|
45
56
|
false
|
|
46
57
|
end
|
|
58
|
+
|
|
59
|
+
if param.is_a?(String) && (DATE_TIME_TYPES.include?(type) || NUMERIC_PARSE_TYPES.include?(type))
|
|
60
|
+
raise ArgumentError, "'#{type}' input exceeds #{PARSE_LENGTH_LIMIT} bytes" if param.bytesize > PARSE_LENGTH_LIMIT
|
|
61
|
+
end
|
|
62
|
+
|
|
47
63
|
return coerce_integer(param, options) if type == Integer
|
|
48
64
|
return Float(param) if type == Float
|
|
49
65
|
return String(param) if type == String
|
|
@@ -56,8 +72,14 @@ module PermitParams
|
|
|
56
72
|
return coerce_boolean(param) if [TrueClass, FalseClass, Boolean].include? type
|
|
57
73
|
|
|
58
74
|
nil
|
|
59
|
-
rescue
|
|
75
|
+
rescue StandardError
|
|
76
|
+
# Any failure while coercing untrusted input (malformed value,
|
|
77
|
+
# unexpected nested shape, missing stdlib constant, etc.) must never
|
|
78
|
+
# crash the caller's request handler - it's either rejected loudly
|
|
79
|
+
# (strong_validation) or dropped silently, same as an invalid value.
|
|
60
80
|
raise InvalidParameterError, "'#{param}' is not a valid #{type}" if strong_validation
|
|
81
|
+
|
|
82
|
+
nil
|
|
61
83
|
end
|
|
62
84
|
end
|
|
63
85
|
|
|
@@ -88,10 +110,13 @@ module PermitParams
|
|
|
88
110
|
end
|
|
89
111
|
|
|
90
112
|
def coerce_boolean(param)
|
|
91
|
-
|
|
113
|
+
# \A/\z (not ^/$) anchor to the start/end of the *whole string*. In Ruby
|
|
114
|
+
# ^ and $ only anchor to line boundaries, so e.g. "true\nDROP TABLE..."
|
|
115
|
+
# would incorrectly match as a clean boolean with ^/$.
|
|
116
|
+
coerced = if /\A(false|f|no|n|0)\z/i === param.to_s
|
|
92
117
|
false
|
|
93
118
|
else
|
|
94
|
-
|
|
119
|
+
/\A(true|t|yes|y|1)\z/i === param.to_s ? true : nil
|
|
95
120
|
end
|
|
96
121
|
raise ArgumentError if coerced.nil?
|
|
97
122
|
|
|
@@ -109,11 +134,18 @@ module PermitParams
|
|
|
109
134
|
end
|
|
110
135
|
|
|
111
136
|
def coerce_shape(param, options = {})
|
|
112
|
-
hash = coerce_hash(param)
|
|
137
|
+
hash = coerce_hash(param, options)
|
|
113
138
|
has_shape?(hash, options[:shape]) ? hash : nil
|
|
114
139
|
end
|
|
115
140
|
|
|
116
141
|
def has_shape?(hash, shape)
|
|
142
|
+
# `hash` can be nil (coerce_hash gave up on a malformed string) and
|
|
143
|
+
# `shape` can be nil/non-Hash (caller forgot to pass shape:, or an
|
|
144
|
+
# attacker sent an unexpected nested hash the shape never described).
|
|
145
|
+
# Either used to raise NoMethodError deep inside a supposedly "safe"
|
|
146
|
+
# input filter, crashing the whole request. Reject instead of raising.
|
|
147
|
+
return false unless hash.is_a?(Hash) && shape.is_a?(Hash)
|
|
148
|
+
|
|
117
149
|
hash.all? do |k, v|
|
|
118
150
|
v.is_a?(Hash) ? has_shape?(v, shape[k]) : shape[k] === v
|
|
119
151
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sinatra-my-params
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marco Aviles
|
|
@@ -39,7 +39,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
requirements: []
|
|
42
|
-
rubygems_version: 3.
|
|
42
|
+
rubygems_version: 3.4.19
|
|
43
43
|
signing_key:
|
|
44
44
|
specification_version: 3
|
|
45
45
|
summary: permit_params!
|