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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7ac22afdb92ac5afb935e234c7f3b431a3f7a51
4
- data.tar.gz: 776a00f300e5caca9a23464e7f164538750a5405
3
+ metadata.gz: 0de5c70ba259b93d21c8b7516b44699985fe6473
4
+ data.tar.gz: aebb63f21cb446003f34a24f78bda31666279250
5
5
  SHA512:
6
- metadata.gz: 0dd34aa9d265e3227bddc9838b9bd440a684e80c15a3dbc3ba97ecc81a0ab67d4d2762946e91b3fbc1a912d09e6e7ea5728c187e3ae3fe4199ab1038d2f26448
7
- data.tar.gz: 3b60bd1a693361e7ba723044851013983904ccf8471339841d70b03bb831f5e8d00c68ecbb3be864f041f931d722a81b5753fa0843e4dd0c32158aa6fc750fdf
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
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'pry'
7
+ gem 'rspec', '~> 3.6.0'
8
+ gem 'rubocop-rspec', '~> 1.15.0'
9
+ end
data/config/default.yml CHANGED
@@ -6,20 +6,32 @@ AllCops:
6
6
  - '.+'
7
7
 
8
8
  GitlabSecurity/DeepMunge:
9
- Description: Disallow removal of Deep Munge setting
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: Check for use of send()/public_send()
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
- # Check for disabling the deep munge security control via:
5
- # config.action_dispatch.perform_deep_munge = false
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. See CVE-2012-2660, CVE-2012-2694 and CVE-2013-0155'
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
- # Check for use of the dangerous public_send() and send() methods.
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 methods on behalf
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 = "Avoid using `%s`. If this method is not passed user input it can be white-listed
26
- by adding `#rubocop:disable GitlabSecurity/PublicSend`"
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
- return unless node.command?(:send) || node.command?(:public_send)
31
+ send?(node) do |match|
32
+ next unless node.arguments?
30
33
 
31
- append_error = node.command?(:send) ? "send()" : "public_send()"
32
- add_offense(node, :selector, format(MSG, append_error))
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 ...) ...)
@@ -2,9 +2,9 @@
2
2
 
3
3
  module RuboCop
4
4
  module GitlabSecurity
5
- # Version information for the GitlabSecurity Rubocop plugin.
5
+ # Version information for the GitlabSecurity Rubocop plugin.
6
6
  module Version
7
- STRING = '0.0.6'.freeze
7
+ STRING = '0.1.0'
8
8
  end
9
9
  end
10
10
  end
@@ -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 = 'http://gitlab.com/briann/rubocop-gitlab-security'
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.6
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-07-28 00:00:00.000000000 Z
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: http://gitlab.com/briann/rubocop-gitlab-security
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.6.11
101
+ rubygems_version: 2.5.2
99
102
  signing_key:
100
103
  specification_version: 4
101
104
  summary: Basic security checks for projects