rubocop-eightyfourcodes 0.0.3 → 0.0.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/.rubocop.yml +8 -1
- data/Gemfile.lock +28 -21
- data/config/default.yml +31 -2
- data/lib/rubocop/cop/eightyfourcodes_cops.rb +7 -0
- data/lib/rubocop/cop/gitlab_security/deep_munge.rb +36 -0
- data/lib/rubocop/cop/gitlab_security/json_serialization.rb +137 -0
- data/lib/rubocop/cop/gitlab_security/public_send.rb +47 -0
- data/lib/rubocop/cop/gitlab_security/redirect_to_params_update.rb +38 -0
- data/lib/rubocop/cop/gitlab_security/send_file_params.rb +40 -0
- data/lib/rubocop/cop/gitlab_security/sql_injection.rb +41 -0
- data/lib/rubocop/cop/gitlab_security/system_command_injection.rb +38 -0
- data/lib/rubocop/eightyfourcodes/version.rb +1 -1
- data/rubocop-eightyfourcodes.gemspec +34 -0
- metadata +17 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2337a72314ad6423017df81a2dcf8f83013dc6e873fd69b5125378182721640
|
4
|
+
data.tar.gz: b32af92eabaeea8c0d9d87f65bfdcbc7143dfe57721a389ad1c883f287134559
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af6326b9251b078270670d986af36041e0af768bb69d29ba9e960f0663dc420444e333057b886714c4184ac1201624d2ab0cd34f5b1425860f70c9e0b666c747
|
7
|
+
data.tar.gz: 84565456b4a0c98c085ec35f86da4bd4765a399b822068d6a51df0129ab786dc0ba97a147e221b187a48b3690bb130cc77592b035c447f6da92aaf8e48c50efc
|
data/.rubocop.yml
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
-
|
1
|
+
plugins:
|
2
2
|
- rubocop-rspec
|
3
3
|
- rubocop-rake
|
4
4
|
|
5
|
+
AllCops:
|
6
|
+
NewCops: enable
|
7
|
+
Exclude:
|
8
|
+
- 'lib/rubocop/cop/gitlab_security/*.rb'
|
9
|
+
- 'spec/rubocop/cop/gitlab_security/*.rb'
|
10
|
+
# avoid linting installed gems when running in GitHub Actions
|
11
|
+
- '**/vendor/bundle/**/*'
|
5
12
|
Naming/FileName:
|
6
13
|
Exclude:
|
7
14
|
- lib/rubocop-eightyfourcodes.rb
|
data/Gemfile.lock
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rubocop-eightyfourcodes (0.0.
|
5
|
-
rubocop
|
4
|
+
rubocop-eightyfourcodes (0.0.4)
|
5
|
+
rubocop (< 2)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
ast (2.4.2)
|
11
|
-
diff-lcs (1.
|
12
|
-
json (2.
|
13
|
-
language_server-protocol (3.17.0.
|
11
|
+
diff-lcs (1.6.0)
|
12
|
+
json (2.10.2)
|
13
|
+
language_server-protocol (3.17.0.4)
|
14
|
+
lint_roller (1.1.0)
|
14
15
|
parallel (1.26.3)
|
15
|
-
parser (3.3.
|
16
|
+
parser (3.3.7.1)
|
16
17
|
ast (~> 2.4.1)
|
17
18
|
racc
|
18
19
|
racc (1.8.1)
|
19
20
|
rainbow (3.1.1)
|
20
21
|
rake (13.2.1)
|
21
|
-
regexp_parser (2.
|
22
|
+
regexp_parser (2.10.0)
|
22
23
|
rspec (3.13.0)
|
23
24
|
rspec-core (~> 3.13.0)
|
24
25
|
rspec-expectations (~> 3.13.0)
|
25
26
|
rspec-mocks (~> 3.13.0)
|
26
|
-
rspec-core (3.13.
|
27
|
+
rspec-core (3.13.3)
|
27
28
|
rspec-support (~> 3.13.0)
|
28
29
|
rspec-expectations (3.13.3)
|
29
30
|
diff-lcs (>= 1.2.0, < 2.0)
|
@@ -31,28 +32,34 @@ GEM
|
|
31
32
|
rspec-mocks (3.13.2)
|
32
33
|
diff-lcs (>= 1.2.0, < 2.0)
|
33
34
|
rspec-support (~> 3.13.0)
|
34
|
-
rspec-support (3.13.
|
35
|
-
rubocop (1.
|
35
|
+
rspec-support (3.13.2)
|
36
|
+
rubocop (1.74.0)
|
36
37
|
json (~> 2.3)
|
37
|
-
language_server-protocol (
|
38
|
+
language_server-protocol (~> 3.17.0.2)
|
39
|
+
lint_roller (~> 1.1.0)
|
38
40
|
parallel (~> 1.10)
|
39
41
|
parser (>= 3.3.0.2)
|
40
42
|
rainbow (>= 2.2.2, < 4.0)
|
41
|
-
regexp_parser (>= 2.
|
42
|
-
rubocop-ast (>= 1.
|
43
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
44
|
+
rubocop-ast (>= 1.38.0, < 2.0)
|
43
45
|
ruby-progressbar (~> 1.7)
|
44
|
-
unicode-display_width (>= 2.4.0, <
|
45
|
-
rubocop-ast (1.
|
46
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
47
|
+
rubocop-ast (1.40.0)
|
46
48
|
parser (>= 3.3.1.0)
|
47
|
-
rubocop-rake (0.
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
rubocop-rake (0.7.1)
|
50
|
+
lint_roller (~> 1.1)
|
51
|
+
rubocop (>= 1.72.1)
|
52
|
+
rubocop-rspec (3.5.0)
|
53
|
+
lint_roller (~> 1.1)
|
54
|
+
rubocop (~> 1.72, >= 1.72.1)
|
51
55
|
ruby-progressbar (1.13.0)
|
52
|
-
unicode-display_width (
|
56
|
+
unicode-display_width (3.1.4)
|
57
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
58
|
+
unicode-emoji (4.0.4)
|
53
59
|
yard (0.9.37)
|
54
60
|
|
55
61
|
PLATFORMS
|
62
|
+
arm64-darwin-23
|
56
63
|
ruby
|
57
64
|
|
58
65
|
DEPENDENCIES
|
@@ -65,4 +72,4 @@ DEPENDENCIES
|
|
65
72
|
yard
|
66
73
|
|
67
74
|
BUNDLED WITH
|
68
|
-
2.
|
75
|
+
2.6.4
|
data/config/default.yml
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
---
|
3
2
|
EightyFourCodes/CommandLiteralInjection:
|
4
3
|
Description: "Do not include variables command literals"
|
5
4
|
Enabled: true
|
@@ -12,3 +11,33 @@ EightyFourCodes/EnsureRedirect:
|
|
12
11
|
Description: "Checks for `redirect` from an `ensure` block"
|
13
12
|
Enabled: true
|
14
13
|
VersionAdded: "0.0.3"
|
14
|
+
GitlabSecurity/DeepMunge:
|
15
|
+
Description: "Checks for disabling the deep munge security control."
|
16
|
+
Enabled: true
|
17
|
+
VersionAdded: "0.0.4"
|
18
|
+
GitlabSecurity/JsonSerialization:
|
19
|
+
Description: "Checks for `to_json` / `as_json` without allowing via `only`."
|
20
|
+
Enabled: true
|
21
|
+
VersionAdded: "0.0.4"
|
22
|
+
GitlabSecurity/PublicSend:
|
23
|
+
Description: "Checks for the use of `public_send`, `send`, and `__send__` methods."
|
24
|
+
Enabled: true
|
25
|
+
VersionAdded: "0.0.4"
|
26
|
+
GitlabSecurity/RedirectToParamsUpdate:
|
27
|
+
Description: "Check for use of redirect_to(params.update())"
|
28
|
+
Enabled: true
|
29
|
+
VersionAdded: "0.0.4"
|
30
|
+
GitlabSecurity/SendFileParams:
|
31
|
+
Description: "Check for use of send_file(..., params[], ...)"
|
32
|
+
Enabled: true
|
33
|
+
VersionAdded: "0.0.4"
|
34
|
+
GitlabSecurity/SqlInjection:
|
35
|
+
Description: |
|
36
|
+
Check for use of where("name = '#{params[:name]}'")"
|
37
|
+
Enabled: true
|
38
|
+
VersionAdded: "0.0.4"
|
39
|
+
GitlabSecurity/SystemCommandInjection:
|
40
|
+
Description: |
|
41
|
+
Check for use of system("/bin/ls #{params[:file]}")
|
42
|
+
Enabled: true
|
43
|
+
VersionAdded: "0.0.4"
|
@@ -3,3 +3,10 @@
|
|
3
3
|
require_relative 'eighty_four_codes/command_literal_injection'
|
4
4
|
require_relative 'eighty_four_codes/ensure_redirect'
|
5
5
|
require_relative 'eighty_four_codes/ruby_version_file'
|
6
|
+
|
7
|
+
require_relative 'gitlab_security/json_serialization'
|
8
|
+
require_relative 'gitlab_security/public_send'
|
9
|
+
require_relative 'gitlab_security/redirect_to_params_update'
|
10
|
+
require_relative 'gitlab_security/send_file_params'
|
11
|
+
require_relative 'gitlab_security/sql_injection'
|
12
|
+
require_relative 'gitlab_security/system_command_injection'
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module GitlabSecurity
|
6
|
+
# Checks for disabling the deep munge security control.
|
7
|
+
#
|
8
|
+
# Disabling this security setting can leave the application open to unsafe
|
9
|
+
# query generation
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# config.action_dispatch.perform_deep_munge = false
|
15
|
+
#
|
16
|
+
# See CVE-2012-2660, CVE-2012-2694, and CVE-2013-0155.
|
17
|
+
class DeepMunge < RuboCop::Cop::Base
|
18
|
+
MSG = 'Never disable the deep munge security option.'
|
19
|
+
|
20
|
+
# @!method disable_deep_munge?(node)
|
21
|
+
def_node_matcher :disable_deep_munge?, <<-PATTERN
|
22
|
+
(send
|
23
|
+
(send (send nil? :config) :action_dispatch) :perform_deep_munge=
|
24
|
+
{ (false) (send true :!) }
|
25
|
+
)
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def on_send(node)
|
29
|
+
return unless disable_deep_munge?(node)
|
30
|
+
|
31
|
+
add_offense(node.loc.selector)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module GitlabSecurity
|
6
|
+
# Checks for `to_json` / `as_json` without allowing via `only`.
|
7
|
+
#
|
8
|
+
# Either method called on an instance of a `Serializer` class will be
|
9
|
+
# ignored. Associations included via `include` are subject to the same
|
10
|
+
# rules.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# render json: @user.to_json
|
16
|
+
# render json: @user.to_json(except: %i[password])
|
17
|
+
# render json: @user.to_json(
|
18
|
+
# only: %i[username],
|
19
|
+
# include: [:identities]
|
20
|
+
# )
|
21
|
+
#
|
22
|
+
# # acceptable
|
23
|
+
# render json: UserSerializer.new.to_json
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# render json: @user.to_json(only: %i[name username])
|
27
|
+
# render json: @user.to_json(
|
28
|
+
# only: %i[username],
|
29
|
+
# include: { identities: { only: %i[provider] } }
|
30
|
+
# )
|
31
|
+
#
|
32
|
+
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/29661
|
33
|
+
class JsonSerialization < RuboCop::Cop::Base
|
34
|
+
MSG = "Don't use `%s` without specifying `only`"
|
35
|
+
|
36
|
+
# Check for `to_json` sent to any object that's not a Hash literal or
|
37
|
+
# Serializer instance
|
38
|
+
# @!method json_serialization?(node)
|
39
|
+
def_node_matcher :json_serialization?, <<~PATTERN
|
40
|
+
(send !{nil? hash #serializer?} ${:to_json :as_json} $...)
|
41
|
+
PATTERN
|
42
|
+
|
43
|
+
# Check if node is a `only: ...` pair
|
44
|
+
# @!method only_pair?(node)
|
45
|
+
def_node_matcher :only_pair?, <<~PATTERN
|
46
|
+
(pair (sym :only) ...)
|
47
|
+
PATTERN
|
48
|
+
|
49
|
+
# Check if node is a `include: {...}` pair
|
50
|
+
# @!method include_pair?(node)
|
51
|
+
def_node_matcher :include_pair?, <<~PATTERN
|
52
|
+
(pair (sym :include) (hash $...))
|
53
|
+
PATTERN
|
54
|
+
|
55
|
+
# Check for a `only: [...]` pair anywhere in the node
|
56
|
+
# @!method contains_only?(node)
|
57
|
+
def_node_search :contains_only?, <<~PATTERN
|
58
|
+
(pair (sym :only) (array ...))
|
59
|
+
PATTERN
|
60
|
+
|
61
|
+
# Check for `SomeConstant.new`
|
62
|
+
# @!method constant_init(node)
|
63
|
+
def_node_search :constant_init, <<~PATTERN
|
64
|
+
(send (const nil? $_) :new ...)
|
65
|
+
PATTERN
|
66
|
+
|
67
|
+
def on_send(node)
|
68
|
+
matched = json_serialization?(node)
|
69
|
+
return unless matched
|
70
|
+
|
71
|
+
@_has_top_level_only = false
|
72
|
+
@method = matched.first
|
73
|
+
|
74
|
+
if matched.last.nil? || matched.last.empty?
|
75
|
+
@offense_found = true
|
76
|
+
# Empty `to_json` call
|
77
|
+
add_offense(node.loc.selector, message: format_message)
|
78
|
+
else
|
79
|
+
check_arguments(node, matched)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def format_message
|
86
|
+
format(MSG, @method)
|
87
|
+
end
|
88
|
+
|
89
|
+
def serializer?(node)
|
90
|
+
constant_init(node).any? { |name| name.to_s.end_with?('Serializer') }
|
91
|
+
end
|
92
|
+
|
93
|
+
def check_arguments(node, matched)
|
94
|
+
options = matched.last.first
|
95
|
+
|
96
|
+
# If `to_json` was given an argument that isn't a Hash, we don't
|
97
|
+
# know what to do here, so just move along
|
98
|
+
return unless options.hash_type?
|
99
|
+
|
100
|
+
options.each_child_node do |child_node|
|
101
|
+
check_pair(child_node)
|
102
|
+
end
|
103
|
+
|
104
|
+
return unless requires_only?
|
105
|
+
|
106
|
+
@offense_found = true
|
107
|
+
|
108
|
+
# Add a top-level offense for the entire argument list, but only if
|
109
|
+
# we haven't yet added any offenses to the child Hash values (such
|
110
|
+
# as `include`)
|
111
|
+
add_offense(node.children.last, message: format_message)
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_pair(pair)
|
115
|
+
if only_pair?(pair)
|
116
|
+
@_has_top_level_only = true
|
117
|
+
elsif include_pair?(pair)
|
118
|
+
includes = pair.value
|
119
|
+
|
120
|
+
includes.each_child_node do |child_node|
|
121
|
+
next if contains_only?(child_node)
|
122
|
+
|
123
|
+
@offense_found = true
|
124
|
+
add_offense(child_node, message: format_message)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def requires_only?
|
130
|
+
return false if @_has_top_level_only
|
131
|
+
|
132
|
+
!@offense_found
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module GitlabSecurity
|
6
|
+
# Checks for the use of `public_send`, `send`, and `__send__` methods.
|
7
|
+
#
|
8
|
+
# If passed untrusted input these methods can be used to execute arbitrary
|
9
|
+
# methods on behalf of an attacker.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# myobj.public_send("#{params[:foo]}")
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# case params[:foo].to_s
|
18
|
+
# when 'choice1'
|
19
|
+
# items.choice1
|
20
|
+
# when 'choice2'
|
21
|
+
# items.choice2
|
22
|
+
# when 'choice3'
|
23
|
+
# items.choice3
|
24
|
+
# end
|
25
|
+
class PublicSend < RuboCop::Cop::Base
|
26
|
+
MSG = 'Avoid using `%s`.'
|
27
|
+
|
28
|
+
RESTRICT_ON_SEND = %i[send public_send __send__].freeze
|
29
|
+
|
30
|
+
# @!method send?(node)
|
31
|
+
def_node_matcher :send?, <<-PATTERN
|
32
|
+
(call _ ${:send :public_send :__send__} ...)
|
33
|
+
PATTERN
|
34
|
+
|
35
|
+
def on_send(node)
|
36
|
+
send?(node) do |match|
|
37
|
+
next unless node.arguments?
|
38
|
+
|
39
|
+
add_offense(node.loc.selector, message: format(MSG, match))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :on_csend, :on_send
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module GitlabSecurity
|
6
|
+
# Check for use of redirect_to(params.update())
|
7
|
+
#
|
8
|
+
# Passing user params to the redirect_to method provides an open redirect
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# redirect_to(params.update(action: 'main'))
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# redirect_to(allowed(params))
|
17
|
+
#
|
18
|
+
class RedirectToParamsUpdate < RuboCop::Cop::Base
|
19
|
+
MSG = 'Avoid using `redirect_to(params.%<name>s(...))`. ' \
|
20
|
+
'Only pass allowed arguments into redirect_to() (e.g. not including `host`)'
|
21
|
+
|
22
|
+
# @!method redirect_to_params_update_node(node)
|
23
|
+
def_node_matcher :redirect_to_params_update_node, <<-PATTERN
|
24
|
+
(send nil? :redirect_to $(send (send nil? :params) ${:update :merge} ...))
|
25
|
+
PATTERN
|
26
|
+
|
27
|
+
def on_send(node)
|
28
|
+
selected, name = redirect_to_params_update_node(node)
|
29
|
+
return unless name
|
30
|
+
|
31
|
+
message = format(MSG, name: name)
|
32
|
+
|
33
|
+
add_offense(selected, message: message)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module GitlabSecurity
|
6
|
+
# Check for use of send_file(..., params[], ...)
|
7
|
+
#
|
8
|
+
# Passing user params to the send_file() method allows directory traversal
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# send_file("/tmp/myproj/" + params[:filename])
|
14
|
+
#
|
15
|
+
# # good (verify directory)
|
16
|
+
|
17
|
+
# basename = File.expand_path("/tmp/myproj")
|
18
|
+
# filename = File.expand_path(File.join(basename, @file.public_filename))
|
19
|
+
# raise if basename != filename
|
20
|
+
# send_file filename, disposition: 'inline'
|
21
|
+
#
|
22
|
+
class SendFileParams < RuboCop::Cop::Base
|
23
|
+
MSG = 'Do not pass user provided params directly to send_file(), ' \
|
24
|
+
'verify the path with file.expand_path() first.'
|
25
|
+
|
26
|
+
# @!method params_node?(node)
|
27
|
+
def_node_search :params_node?, <<-PATTERN
|
28
|
+
(send (send nil? :params) ... )
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_send(node)
|
32
|
+
return unless node.command?(:send_file)
|
33
|
+
return unless node.arguments.any? { |e| params_node?(e) }
|
34
|
+
|
35
|
+
add_offense(node.loc.selector)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module GitlabSecurity
|
6
|
+
# Check for use of where("name = '#{params[:name]}'")
|
7
|
+
#
|
8
|
+
# Passing user input to where() without parameterization can result in SQL Injection
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# u = User.where("name = '#{params[:name]}'")
|
14
|
+
#
|
15
|
+
# # good (parameters)
|
16
|
+
# u = User.where("name = ? AND id = ?", params[:name], params[:id])
|
17
|
+
# u = User.where(name: params[:name], id: params[:id])
|
18
|
+
#
|
19
|
+
class SqlInjection < RuboCop::Cop::Base
|
20
|
+
MSG = 'Parameterize all user-input passed to where(), do not directly embed user input in SQL queries.'
|
21
|
+
|
22
|
+
# @!method where_user_input?(node)
|
23
|
+
def_node_matcher :where_user_input?, <<-PATTERN
|
24
|
+
(send _ :where ...)
|
25
|
+
PATTERN
|
26
|
+
|
27
|
+
# @!method string_var_string?(node)
|
28
|
+
def_node_matcher :string_var_string?, <<-PATTERN
|
29
|
+
(dstr (str ...) (begin ...) (str ...) ...)
|
30
|
+
PATTERN
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
return unless where_user_input?(node)
|
34
|
+
return unless node.arguments.any? { |e| string_var_string?(e) }
|
35
|
+
|
36
|
+
add_offense(node.loc.selector)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module GitlabSecurity
|
6
|
+
# Check for use of system("/bin/ls #{params[:file]}")
|
7
|
+
#
|
8
|
+
# Passing user input to system() without sanitization and parameterization can result in command injection
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# system("/bin/ls #{filename}")
|
14
|
+
#
|
15
|
+
# # good (parameters)
|
16
|
+
# system("/bin/ls", filename)
|
17
|
+
# # even better
|
18
|
+
# exec("/bin/ls", shell_escape(filename))
|
19
|
+
#
|
20
|
+
class SystemCommandInjection < RuboCop::Cop::Base
|
21
|
+
MSG = 'Do not include variables in the command name for system(). ' \
|
22
|
+
'Use parameters "system(cmd, params)" or exec() instead.'
|
23
|
+
|
24
|
+
# @!method system_var?(node)
|
25
|
+
def_node_matcher :system_var?, <<-PATTERN
|
26
|
+
(dstr (str ...) (begin ...) ...)
|
27
|
+
PATTERN
|
28
|
+
|
29
|
+
def on_send(node)
|
30
|
+
return unless node.command?(:system)
|
31
|
+
return unless node.arguments.any? { |e| system_var?(e) }
|
32
|
+
|
33
|
+
add_offense(node.loc.selector)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/rubocop/eightyfourcodes/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'rubocop-eightyfourcodes'
|
7
|
+
spec.version = RuboCop::EightyFourCodes::VERSION
|
8
|
+
spec.authors = ['Anders Bälter']
|
9
|
+
spec.email = ['anders@84codes.com']
|
10
|
+
|
11
|
+
spec.summary = 'This is a collection of cops developed and used by 84codes AB.'
|
12
|
+
spec.description = <<~DESCRIPTION
|
13
|
+
A plugin for the RuboCop code style enforcing & linting tool.
|
14
|
+
DESCRIPTION
|
15
|
+
spec.homepage = 'https://github.com/84codes/rubocop-eightyfourcodes/'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
spec.required_ruby_version = '>= 2.6.0'
|
18
|
+
|
19
|
+
spec.metadata = {
|
20
|
+
'rubygems_mfa_required' => 'true'
|
21
|
+
}
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
(File.expand_path(f) == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
spec.require_paths = ['lib']
|
32
|
+
spec.add_dependency 'rubocop', '< 2'
|
33
|
+
spec.extra_rdoc_files = ['LICENSE.md', 'README.md']
|
34
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,28 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-eightyfourcodes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anders Bälter
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-20 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: rubocop
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
16
15
|
requirements:
|
17
|
-
- - "
|
16
|
+
- - "<"
|
18
17
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
18
|
+
version: '2'
|
20
19
|
type: :runtime
|
21
20
|
prerelease: false
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
23
22
|
requirements:
|
24
|
-
- - "
|
23
|
+
- - "<"
|
25
24
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
25
|
+
version: '2'
|
27
26
|
description: 'A plugin for the RuboCop code style enforcing & linting tool.
|
28
27
|
|
29
28
|
'
|
@@ -49,15 +48,23 @@ files:
|
|
49
48
|
- lib/rubocop/cop/eighty_four_codes/ensure_redirect.rb
|
50
49
|
- lib/rubocop/cop/eighty_four_codes/ruby_version_file.rb
|
51
50
|
- lib/rubocop/cop/eightyfourcodes_cops.rb
|
51
|
+
- lib/rubocop/cop/gitlab_security/deep_munge.rb
|
52
|
+
- lib/rubocop/cop/gitlab_security/json_serialization.rb
|
53
|
+
- lib/rubocop/cop/gitlab_security/public_send.rb
|
54
|
+
- lib/rubocop/cop/gitlab_security/redirect_to_params_update.rb
|
55
|
+
- lib/rubocop/cop/gitlab_security/send_file_params.rb
|
56
|
+
- lib/rubocop/cop/gitlab_security/sql_injection.rb
|
57
|
+
- lib/rubocop/cop/gitlab_security/system_command_injection.rb
|
52
58
|
- lib/rubocop/eightyfourcodes.rb
|
53
59
|
- lib/rubocop/eightyfourcodes/inject.rb
|
54
60
|
- lib/rubocop/eightyfourcodes/version.rb
|
61
|
+
- rubocop-eightyfourcodes.gemspec
|
55
62
|
- sig/rubocop/eightyfourcodes.rbs
|
56
63
|
homepage: https://github.com/84codes/rubocop-eightyfourcodes/
|
57
64
|
licenses:
|
58
65
|
- MIT
|
59
|
-
metadata:
|
60
|
-
|
66
|
+
metadata:
|
67
|
+
rubygems_mfa_required: 'true'
|
61
68
|
rdoc_options: []
|
62
69
|
require_paths:
|
63
70
|
- lib
|
@@ -72,8 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
79
|
- !ruby/object:Gem::Version
|
73
80
|
version: '0'
|
74
81
|
requirements: []
|
75
|
-
rubygems_version: 3.
|
76
|
-
signing_key:
|
82
|
+
rubygems_version: 3.6.2
|
77
83
|
specification_version: 4
|
78
84
|
summary: This is a collection of cops developed and used by 84codes AB.
|
79
85
|
test_files: []
|