spektr 0.5.2 → 0.5.4
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 +9 -0
- data/lib/spektr/checks/base.rb +79 -19
- data/lib/spektr/checks/link_to_href.rb +5 -1
- data/lib/spektr/checks/mass_assignment.rb +3 -3
- data/lib/spektr/checks/xss.rb +6 -1
- data/lib/spektr/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3856f34c87bf7f347c90149e5cc0a824e68d80df6c6a4704a204e4862ea3e54b
|
|
4
|
+
data.tar.gz: f0c98f054f09841c3de0e7f756c80537b5d0a409a2fe0a70d555b63715958691
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fb99134225086acbaab6417f03594c7cb1b44893bdd413faf5056d3990afdd8e6bea3812c6a5a61344fc518e7d47b78bdbe49dfdb49e75722f6c5303df43101a
|
|
7
|
+
data.tar.gz: 7c20a2d6f2ec1a7c1a5e006b2ce4bb41e527a55fae099fd66d4e120f7fdffd9c6849496269abd998226f303b4602b5ac23b703a8be448abcd851a4f25bdb974a
|
data/CHANGELOG.md
CHANGED
data/lib/spektr/checks/base.rb
CHANGED
|
@@ -54,11 +54,11 @@ module Spektr
|
|
|
54
54
|
return true if user_input?(argument)
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
|
-
when :embedded_statements_node
|
|
57
|
+
when :embedded_statements_node, :if_node, :else_node, :case_node, :embedded_variable_node
|
|
58
58
|
node.statements.body.each do |item|
|
|
59
59
|
return true if user_input? item
|
|
60
60
|
end
|
|
61
|
-
when :interpolated_string_node, :interpolated_x_string_node
|
|
61
|
+
when :interpolated_string_node, :interpolated_x_string_node, :interpolated_symbol_node, :interpolated_regular_expression_node
|
|
62
62
|
node.parts.each do |part|
|
|
63
63
|
return true if user_input?(part)
|
|
64
64
|
end
|
|
@@ -67,6 +67,10 @@ module Spektr
|
|
|
67
67
|
return true if user_input?(element.key)
|
|
68
68
|
return true if user_input?(element.value)
|
|
69
69
|
end
|
|
70
|
+
when :array_node
|
|
71
|
+
node.elements.each do |element|
|
|
72
|
+
return true if user_input?(element)
|
|
73
|
+
end
|
|
70
74
|
# TODO: make this better. ivars can be overridden in the view as well and
|
|
71
75
|
# can be set in non controller targets too
|
|
72
76
|
when :instance_variable_read_node
|
|
@@ -84,26 +88,84 @@ module Spektr
|
|
|
84
88
|
end
|
|
85
89
|
end
|
|
86
90
|
when :local_variable_read_node
|
|
87
|
-
|
|
91
|
+
variable = @target.lvars.find do |n|
|
|
92
|
+
n.name == node.name
|
|
93
|
+
end
|
|
94
|
+
return if variable && variable.location.start_line == node.location.start_line
|
|
95
|
+
return user_input?(variable)
|
|
96
|
+
when :instance_variable_or_write_node, :local_variable_or_write_node
|
|
97
|
+
return user_input?(node.value)
|
|
88
98
|
when :instance_variable_write_node, :local_variable_write_node
|
|
89
99
|
return user_input? node.value
|
|
100
|
+
when :and_node, :or_node
|
|
101
|
+
return user_input?(node.left)
|
|
102
|
+
return user_input?(node.right)
|
|
103
|
+
when :splat_node
|
|
104
|
+
return user_input? node.expression
|
|
90
105
|
when :parentheses_node
|
|
91
106
|
node.body.body.each do |item|
|
|
92
107
|
return user_input? item
|
|
93
108
|
end
|
|
94
|
-
when :string_node, :symbol_node, :constant_read_node, :integer_node, :true_node, :constant_path_node, :nil_node
|
|
109
|
+
when :string_node, :symbol_node, :constant_read_node, :integer_node, :true_node, :constant_path_node, :nil_node, :true_node, :false_node, :self_node, :global_variable_read_node, :and_node
|
|
95
110
|
# do nothing
|
|
96
111
|
else
|
|
97
|
-
|
|
112
|
+
Spektr::Logger.debug "Unknown argument type #{node.type.inspect} #{node.inspect}"
|
|
98
113
|
end
|
|
99
114
|
false
|
|
100
115
|
end
|
|
101
116
|
|
|
102
117
|
# TODO: this doesn't work properly
|
|
103
118
|
def model_attribute?(node)
|
|
119
|
+
return false if node.nil?
|
|
104
120
|
model_names = @app.models.collect(&:name)
|
|
105
121
|
case node.type
|
|
106
|
-
when :
|
|
122
|
+
when :call_node
|
|
123
|
+
return model_attribute?(node.receiver) if node.receiver
|
|
124
|
+
if node.arguments
|
|
125
|
+
node.arguments.arguments.each do |argument|
|
|
126
|
+
return true if model_attribute?(argument)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
when :embedded_statements_node, :if_node, :else_node, :case_node, :embedded_variable_node
|
|
130
|
+
node.statements.body.each do |item|
|
|
131
|
+
return true if model_attribute? item
|
|
132
|
+
end
|
|
133
|
+
when :interpolated_string_node, :interpolated_x_string_node, :interpolated_symbol_node, :interpolated_regular_expression_node
|
|
134
|
+
node.parts.each do |part|
|
|
135
|
+
return true if model_attribute?(part)
|
|
136
|
+
end
|
|
137
|
+
when :keyword_hash_node, :hash_node
|
|
138
|
+
node.elements.each do |element|
|
|
139
|
+
return true if model_attribute?(element.key)
|
|
140
|
+
return true if model_attribute?(element.value)
|
|
141
|
+
end
|
|
142
|
+
when :array_node
|
|
143
|
+
node.elements.each do |element|
|
|
144
|
+
return true if model_attribute?(element)
|
|
145
|
+
end
|
|
146
|
+
# TODO: make this better. ivars can be overridden in the view as well and
|
|
147
|
+
# can be set in non controller targets too
|
|
148
|
+
when :_instance_variable_read_node
|
|
149
|
+
return false unless @target.respond_to?(:view_path)
|
|
150
|
+
actions = []
|
|
151
|
+
@app.controllers.each do |controller|
|
|
152
|
+
actions = actions.concat controller.actions.select { |action|
|
|
153
|
+
action.template == @target.view_path
|
|
154
|
+
}
|
|
155
|
+
end
|
|
156
|
+
actions.each do |action|
|
|
157
|
+
next unless action.body
|
|
158
|
+
action.body.each do |exp|
|
|
159
|
+
return true if exp.name == node.name && model_attribute?(exp)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
when :local_variable_read_node
|
|
163
|
+
variable = @target.lvars.find do |n|
|
|
164
|
+
n.name == node.name
|
|
165
|
+
end
|
|
166
|
+
return if variable && variable.location.start_line == node.location.start_line
|
|
167
|
+
return model_attribute?(variable)
|
|
168
|
+
when :instance_variable_read_node
|
|
107
169
|
# TODO: handle helpers here too
|
|
108
170
|
if ["Spektr::Targets::Controller", "Spektr::Targets::View"].include?(@target.class.name)
|
|
109
171
|
actions = []
|
|
@@ -119,27 +181,25 @@ module Spektr
|
|
|
119
181
|
end
|
|
120
182
|
end
|
|
121
183
|
end
|
|
122
|
-
when :
|
|
123
|
-
return model_attribute?(node.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
184
|
+
when :instance_variable_or_write, :local_variable_or_write_node
|
|
185
|
+
return model_attribute?(node.value)
|
|
186
|
+
when :instance_variable_write_node, :local_variable_write_node
|
|
187
|
+
return model_attribute? node.value
|
|
188
|
+
when :and_node, :or_node
|
|
189
|
+
return model_attribute?(node.left)
|
|
190
|
+
return model_attribute?(node.right)
|
|
191
|
+
when :splat_node
|
|
192
|
+
return model_attribute? node.expression
|
|
129
193
|
when :parentheses_node
|
|
130
194
|
node.body.body.each do |item|
|
|
131
195
|
return model_attribute? item
|
|
132
196
|
end
|
|
133
197
|
when :constant_read_node
|
|
134
198
|
return true if model_names.include? node.name.to_s
|
|
135
|
-
when :
|
|
136
|
-
node.parts.each do |item|
|
|
137
|
-
return model_attribute? item
|
|
138
|
-
end
|
|
139
|
-
when :string_node, :symbol_node, :integer_node, :constant_path_node, :nil_node
|
|
199
|
+
when :string_node, :symbol_node, :integer_node, :constant_path_node, :nil_node, :true_node, :false_node, :self_node, :global_variable_read_node
|
|
140
200
|
# do nothing
|
|
141
201
|
else
|
|
142
|
-
|
|
202
|
+
Spektr::Logger.debug "Unknown argument type #{node.type}"
|
|
143
203
|
end
|
|
144
204
|
end
|
|
145
205
|
|
|
@@ -26,7 +26,11 @@ module Spektr
|
|
|
26
26
|
next unless call.arguments
|
|
27
27
|
::Spektr.logger.debug "#{@target.path} #{call.location.start_line} #{call.arguments.arguments[1].inspect}"
|
|
28
28
|
next unless call.arguments.arguments[1]
|
|
29
|
-
|
|
29
|
+
require 'byebug'
|
|
30
|
+
if call.arguments.arguments[1] && call.arguments.arguments[1].respond_to?(:name)
|
|
31
|
+
name = call.arguments.arguments[1].name
|
|
32
|
+
end
|
|
33
|
+
next if name && name =~ /_url$|_path$/
|
|
30
34
|
if user_input? call.arguments.arguments[1]
|
|
31
35
|
warn! @target, self, call.location, "Cross-Site Scripting: Unsafe user supplied value in link_to"
|
|
32
36
|
end
|
|
@@ -16,7 +16,7 @@ module Spektr
|
|
|
16
16
|
calls = []
|
|
17
17
|
model_names.each do |receiver|
|
|
18
18
|
[:new, :build, :create].each do |method|
|
|
19
|
-
calls.concat @target.find_calls(method, receiver
|
|
19
|
+
calls.concat @target.find_calls(method, receiver&.to_sym)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
calls.each do |call|
|
|
@@ -25,9 +25,9 @@ module Spektr
|
|
|
25
25
|
::Spektr.logger.debug "Mass assignment check at #{call.location.start_line}"
|
|
26
26
|
if user_input?(argument)
|
|
27
27
|
# we check for permit! separately
|
|
28
|
-
next if argument.name == :permit!
|
|
28
|
+
next if argument.respond_to?(:name) && argument.name == :permit!
|
|
29
29
|
# check for permit with arguments
|
|
30
|
-
next if argument.name == :permit && argument.arguments
|
|
30
|
+
next if argument.respond_to?(:name) && argument.name == :permit && argument.arguments
|
|
31
31
|
warn! @target, self, call.location, "Mass assignment"
|
|
32
32
|
end
|
|
33
33
|
end
|
data/lib/spektr/checks/xss.rb
CHANGED
|
@@ -43,7 +43,12 @@ module Spektr
|
|
|
43
43
|
warn! @target, self, call.location, "Cross-Site Scripting: Unescaped user input"
|
|
44
44
|
end
|
|
45
45
|
if model_attribute?(call.receiver)
|
|
46
|
-
|
|
46
|
+
name = if call.receiver.respond_to?(:name)
|
|
47
|
+
call.receiver.name
|
|
48
|
+
else
|
|
49
|
+
""
|
|
50
|
+
end
|
|
51
|
+
warn! @target, self, call.location, "Cross-Site Scripting: Unescaped model attribute #{name}"
|
|
47
52
|
end
|
|
48
53
|
end
|
|
49
54
|
end
|
data/lib/spektr/version.rb
CHANGED