rubocop-gitlab-security 0.0.6 → 0.1.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/CHANGELOG.md +8 -0
- data/Gemfile +9 -0
- data/config/default.yml +14 -2
- data/lib/rubocop-gitlab-security.rb +1 -0
- data/lib/rubocop/cop/gitlab-security/deep_munge.rb +8 -7
- data/lib/rubocop/cop/gitlab-security/json_serialization.rb +126 -0
- data/lib/rubocop/cop/gitlab-security/public_send.rb +12 -9
- data/lib/rubocop/cop/gitlab-security/redirect_to_params_update.rb +3 -3
- data/lib/rubocop/cop/gitlab-security/send_file_params.rb +1 -1
- data/lib/rubocop/cop/gitlab-security/sql_injection.rb +1 -1
- data/lib/rubocop/cop/gitlab-security/system_command_injection.rb +1 -1
- data/lib/rubocop/gitlab-security/version.rb +2 -2
- data/rubocop-gitlab-security.gemspec +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0de5c70ba259b93d21c8b7516b44699985fe6473
|
4
|
+
data.tar.gz: aebb63f21cb446003f34a24f78bda31666279250
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a355bd388fcf9e8b22757a289de2be26252c72e05a58e22017fe90f7a765f8a3d2309ad87988bd7a1687242539e168ee4cb743337e65fab41f7378d27b874c64
|
7
|
+
data.tar.gz: e50d20427b601c6f92ea8a66ade418e04a5bf256767440c62d3b8c2c5fc760d0c97173eeea198a4eac74624593e365071d90584bfde2ff5260b3ffca890fd7c0
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.1.0 (2017-08-24)
|
4
|
+
|
5
|
+
- `PublicSend`: Check for `__send__` calls. (!5)
|
6
|
+
- `PublicSend`: Correct checking for calls with and without arguments. (!5)
|
7
|
+
- Add `JsonSerialization` cop to check for `to_json` or `as_json` without explicit
|
8
|
+
whitelisting. (!6)
|
data/Gemfile
ADDED
data/config/default.yml
CHANGED
@@ -6,20 +6,32 @@ AllCops:
|
|
6
6
|
- '.+'
|
7
7
|
|
8
8
|
GitlabSecurity/DeepMunge:
|
9
|
-
Description:
|
9
|
+
Description: Checks for disabling the deep munge security control.
|
10
10
|
Enabled: true
|
11
|
+
StyleGuide: http://www.rubydoc.info/gems/rubocop-gitlab-security/RuboCop/Cop/GitlabSecurity/DeepMunge
|
12
|
+
|
13
|
+
GitlabSecurity/JsonSerialization:
|
14
|
+
Description: Checks for `to_json` / `as_json` without whitelisting via `only`.
|
15
|
+
Enabled: true
|
16
|
+
StyleGuide: http://www.rubydoc.info/gems/rubocop-gitlab-security/RuboCop/Cop/GitlabSecurity/JsonSerialization
|
17
|
+
|
11
18
|
GitlabSecurity/PublicSend:
|
12
|
-
Description:
|
19
|
+
Description: Checks for the use of `public_send`, `send`, and `__send__` methods.
|
13
20
|
Enabled: true
|
21
|
+
StyleGuide: http://www.rubydoc.info/gems/rubocop-gitlab-security/RuboCop/Cop/GitlabSecurity/PublicSend
|
22
|
+
|
14
23
|
GitlabSecurity/RedirectToParamsUpdate:
|
15
24
|
Description: Check for use of redirect_to(params.update())
|
16
25
|
Enabled: true
|
26
|
+
|
17
27
|
GitlabSecurity/SendFileParams:
|
18
28
|
Description: Check for passing of params hash to send_file()
|
19
29
|
Enabled: true
|
30
|
+
|
20
31
|
GitlabSecurity/SqlInjection:
|
21
32
|
Description: Check for SQL Injection in where()
|
22
33
|
Enabled: true
|
34
|
+
|
23
35
|
GitlabSecurity/SystemCommandInjection:
|
24
36
|
Description: Check for Command Injection in System()
|
25
37
|
Enabled: true
|
@@ -20,6 +20,7 @@ require 'rubocop/cop/gitlab-security/cop'
|
|
20
20
|
RuboCop::GitlabSecurity::Inject.defaults!
|
21
21
|
|
22
22
|
require 'rubocop/cop/gitlab-security/deep_munge'
|
23
|
+
require 'rubocop/cop/gitlab-security/json_serialization'
|
23
24
|
require 'rubocop/cop/gitlab-security/public_send'
|
24
25
|
require 'rubocop/cop/gitlab-security/redirect_to_params_update'
|
25
26
|
require 'rubocop/cop/gitlab-security/send_file_params'
|
@@ -1,19 +1,20 @@
|
|
1
1
|
module RuboCop
|
2
2
|
module Cop
|
3
3
|
module GitlabSecurity
|
4
|
-
#
|
5
|
-
#
|
4
|
+
# Checks for disabling the deep munge security control.
|
5
|
+
#
|
6
|
+
# Disabling this security setting can leave the application open to unsafe
|
7
|
+
# query generation
|
6
8
|
#
|
7
|
-
# Disabling this security setting can leave the application open to unsafe query generation
|
8
|
-
#
|
9
9
|
# @example
|
10
10
|
#
|
11
11
|
# # bad
|
12
12
|
# config.action_dispatch.perform_deep_munge = false
|
13
|
-
#
|
13
|
+
#
|
14
|
+
# See CVE-2012-2660, CVE-2012-2694, and CVE-2013-0155.
|
14
15
|
class DeepMunge < RuboCop::Cop::Cop
|
15
|
-
MSG = 'Never disable the deep munge security option.
|
16
|
-
|
16
|
+
MSG = 'Never disable the deep munge security option.'.freeze
|
17
|
+
|
17
18
|
def_node_matcher :disable_deep_munge?, <<-PATTERN
|
18
19
|
(send (send (send nil :config) :action_dispatch) :perform_deep_munge= (false))
|
19
20
|
PATTERN
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module RuboCop
|
2
|
+
module Cop
|
3
|
+
module GitlabSecurity
|
4
|
+
# Checks for `to_json` / `as_json` without whitelisting via `only`.
|
5
|
+
#
|
6
|
+
# Either method called on an instance of a `Serializer` class will be
|
7
|
+
# ignored. Associations included via `include` are subject to the same
|
8
|
+
# rules.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# render json: @user.to_json
|
14
|
+
# render json: @user.to_json(except: %i[password])
|
15
|
+
# render json: @user.to_json(
|
16
|
+
# only: %i[username],
|
17
|
+
# include: [:identities]
|
18
|
+
# )
|
19
|
+
#
|
20
|
+
# # acceptable
|
21
|
+
# render json: UserSerializer.new.to_json
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# render json: @user.to_json(only: %i[name username])
|
25
|
+
# render json: @user.to_json(
|
26
|
+
# only: %i[username],
|
27
|
+
# include: { identities: { only: %i[provider] } }
|
28
|
+
# )
|
29
|
+
#
|
30
|
+
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/29661
|
31
|
+
class JsonSerialization < RuboCop::Cop::Cop
|
32
|
+
MSG = "Don't use `%s` without specifying `only`".freeze
|
33
|
+
|
34
|
+
# Check for `to_json` sent to any object that's not a Hash literal or
|
35
|
+
# Serializer instance
|
36
|
+
def_node_matcher :json_serialization?, <<~PATTERN
|
37
|
+
(send !{nil hash #serializer?} ${:to_json :as_json} $...)
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
# Check if node is a `only: ...` pair
|
41
|
+
def_node_matcher :only_pair?, <<~PATTERN
|
42
|
+
(pair (sym :only) ...)
|
43
|
+
PATTERN
|
44
|
+
|
45
|
+
# Check if node is a `include: {...}` pair
|
46
|
+
def_node_matcher :include_pair?, <<~PATTERN
|
47
|
+
(pair (sym :include) (hash $...))
|
48
|
+
PATTERN
|
49
|
+
|
50
|
+
# Check for a `only: [...]` pair anywhere in the node
|
51
|
+
def_node_search :contains_only?, <<~PATTERN
|
52
|
+
(pair (sym :only) (array ...))
|
53
|
+
PATTERN
|
54
|
+
|
55
|
+
# Check for `SomeConstant.new`
|
56
|
+
def_node_search :constant_init, <<~PATTERN
|
57
|
+
(send (const nil $_) :new ...)
|
58
|
+
PATTERN
|
59
|
+
|
60
|
+
def on_send(node)
|
61
|
+
matched = json_serialization?(node)
|
62
|
+
return unless matched
|
63
|
+
|
64
|
+
@_has_top_level_only = false
|
65
|
+
@method = matched.first
|
66
|
+
|
67
|
+
if matched.last.nil? || matched.last.empty?
|
68
|
+
# Empty `to_json` call
|
69
|
+
add_offense(node, :selector, format_message)
|
70
|
+
else
|
71
|
+
check_arguments(node, matched)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def format_message
|
78
|
+
format(MSG, @method)
|
79
|
+
end
|
80
|
+
|
81
|
+
def serializer?(node)
|
82
|
+
constant_init(node).any? { |name| name.to_s.end_with?('Serializer') }
|
83
|
+
end
|
84
|
+
|
85
|
+
def check_arguments(node, matched)
|
86
|
+
options = matched.last.first
|
87
|
+
|
88
|
+
# If `to_json` was given an argument that isn't a Hash, we don't
|
89
|
+
# know what to do here, so just move along
|
90
|
+
return unless options.hash_type?
|
91
|
+
|
92
|
+
options.each_child_node do |child_node|
|
93
|
+
check_pair(child_node)
|
94
|
+
end
|
95
|
+
|
96
|
+
return unless requires_only?
|
97
|
+
|
98
|
+
# Add a top-level offense for the entire argument list, but only if
|
99
|
+
# we haven't yet added any offenses to the child Hash values (such
|
100
|
+
# as `include`)
|
101
|
+
add_offense(node.children.last, :expression, format_message)
|
102
|
+
end
|
103
|
+
|
104
|
+
def check_pair(pair)
|
105
|
+
if only_pair?(pair)
|
106
|
+
@_has_top_level_only = true
|
107
|
+
elsif include_pair?(pair)
|
108
|
+
includes = pair.value
|
109
|
+
|
110
|
+
includes.each_child_node do |child_node|
|
111
|
+
next if contains_only?(child_node)
|
112
|
+
|
113
|
+
add_offense(child_node, :expression, format_message)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def requires_only?
|
119
|
+
return false if @_has_top_level_only
|
120
|
+
|
121
|
+
offenses.count.zero?
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module RuboCop
|
2
2
|
module Cop
|
3
3
|
module GitlabSecurity
|
4
|
-
#
|
4
|
+
# Checks for the use of `public_send`, `send`, and `__send__` methods.
|
5
5
|
#
|
6
|
-
# If passed untrusted input these methods can be used to execute arbitrary
|
7
|
-
# of an attacker.
|
6
|
+
# If passed untrusted input these methods can be used to execute arbitrary
|
7
|
+
# methods on behalf of an attacker.
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
#
|
@@ -20,16 +20,19 @@ module RuboCop
|
|
20
20
|
# when 'choice3'
|
21
21
|
# items.choice3
|
22
22
|
# end
|
23
|
-
#
|
24
23
|
class PublicSend < RuboCop::Cop::Cop
|
25
|
-
MSG =
|
26
|
-
|
24
|
+
MSG = 'Avoid using `%s`.'.freeze
|
25
|
+
|
26
|
+
def_node_matcher :send?, <<-PATTERN
|
27
|
+
(send _ ${:send :public_send :__send__} ...)
|
28
|
+
PATTERN
|
27
29
|
|
28
30
|
def on_send(node)
|
29
|
-
|
31
|
+
send?(node) do |match|
|
32
|
+
next unless node.arguments?
|
30
33
|
|
31
|
-
|
32
|
-
|
34
|
+
add_offense(node, :selector, format(MSG, match))
|
35
|
+
end
|
33
36
|
end
|
34
37
|
end
|
35
38
|
end
|
@@ -4,17 +4,17 @@ module RuboCop
|
|
4
4
|
# Check for use of redirect_to(params.update())
|
5
5
|
#
|
6
6
|
# Passing user params to the redirect_to method provides an open redirect
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# @example
|
9
9
|
#
|
10
10
|
# # bad
|
11
11
|
# redirect_to(params.update(action:'main'))
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# # good
|
14
14
|
# redirect_to(whitelist(params))
|
15
15
|
#
|
16
16
|
class RedirectToParamsUpdate < RuboCop::Cop::Cop
|
17
|
-
MSG = 'Avoid using redirect_to(params.update()). Only pass whitelisted arguments into redirect_to() (e.g. not including `host`)'
|
17
|
+
MSG = 'Avoid using redirect_to(params.update()). Only pass whitelisted arguments into redirect_to() (e.g. not including `host`)'.freeze
|
18
18
|
|
19
19
|
def_node_matcher :redirect_to_params_update_node, <<-PATTERN
|
20
20
|
(send nil :redirect_to (send (send nil :params) ${:update :merge} ...))
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
class SendFileParams < RuboCop::Cop::Cop
|
21
21
|
MSG = 'Do not pass user provided params directly to send_file(), verify
|
22
22
|
the path with file.expand_path() first. If the path has already been verified
|
23
|
-
this warning can be disabled using `#rubocop:disable GitlabSecurity/SendFileParams`'
|
23
|
+
this warning can be disabled using `#rubocop:disable GitlabSecurity/SendFileParams`'.freeze
|
24
24
|
|
25
25
|
def_node_search :params_node?, <<-PATTERN
|
26
26
|
(send (send nil :params) ... )
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
#
|
17
17
|
class SqlInjection < RuboCop::Cop::Cop
|
18
18
|
MSG = 'Parameterize all user-input passed to where(), do not directly embed user input in SQL queries.
|
19
|
-
If this warning is in error you can white-list the line with `#rubocop:disable GitlabSecurity/SqlInjection`'
|
19
|
+
If this warning is in error you can white-list the line with `#rubocop:disable GitlabSecurity/SqlInjection`'.freeze
|
20
20
|
|
21
21
|
def_node_matcher :where_user_input?, <<-PATTERN
|
22
22
|
(send _ :where ...)
|
@@ -17,7 +17,7 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
class SystemCommandInjection < RuboCop::Cop::Cop
|
19
19
|
MSG = 'Do not include variables in the command name for system(). Use parameters "system(cmd, params)" or exec() instead.
|
20
|
-
If this warning is in error you can white-list the line with `#rubocop:disable GitLabSecurity/SystemCommandInjection`'
|
20
|
+
If this warning is in error you can white-list the line with `#rubocop:disable GitLabSecurity/SystemCommandInjection`'.freeze
|
21
21
|
|
22
22
|
def_node_matcher :system_var?, <<-PATTERN
|
23
23
|
(dstr (str ...) (begin ...) ...)
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
Basic security checking for Ruby files.
|
11
11
|
A plugin for the RuboCop code style enforcing & linting tool.
|
12
12
|
end_description
|
13
|
-
spec.homepage = '
|
13
|
+
spec.homepage = 'https://gitlab.com/gitlab-org/rubocop-gitlab-security/'
|
14
14
|
spec.authors = ['Brian Neel']
|
15
15
|
spec.email = [
|
16
16
|
'brian@gitlab.com'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-gitlab-security
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Neel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -49,12 +49,15 @@ extra_rdoc_files:
|
|
49
49
|
- MIT-LICENSE.md
|
50
50
|
- README.md
|
51
51
|
files:
|
52
|
+
- CHANGELOG.md
|
53
|
+
- Gemfile
|
52
54
|
- MIT-LICENSE.md
|
53
55
|
- README.md
|
54
56
|
- config/default.yml
|
55
57
|
- lib/rubocop-gitlab-security.rb
|
56
58
|
- lib/rubocop/cop/gitlab-security/cop.rb
|
57
59
|
- lib/rubocop/cop/gitlab-security/deep_munge.rb
|
60
|
+
- lib/rubocop/cop/gitlab-security/json_serialization.rb
|
58
61
|
- lib/rubocop/cop/gitlab-security/public_send.rb
|
59
62
|
- lib/rubocop/cop/gitlab-security/redirect_to_params_update.rb
|
60
63
|
- lib/rubocop/cop/gitlab-security/send_file_params.rb
|
@@ -75,7 +78,7 @@ files:
|
|
75
78
|
- lib/rubocop/gitlab-security/version.rb
|
76
79
|
- lib/rubocop/gitlab-security/wording.rb
|
77
80
|
- rubocop-gitlab-security.gemspec
|
78
|
-
homepage:
|
81
|
+
homepage: https://gitlab.com/gitlab-org/rubocop-gitlab-security/
|
79
82
|
licenses:
|
80
83
|
- MIT
|
81
84
|
metadata: {}
|
@@ -95,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
98
|
version: '0'
|
96
99
|
requirements: []
|
97
100
|
rubyforge_project:
|
98
|
-
rubygems_version: 2.
|
101
|
+
rubygems_version: 2.5.2
|
99
102
|
signing_key:
|
100
103
|
specification_version: 4
|
101
104
|
summary: Basic security checks for projects
|