simplycop 1.0.0.pre

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.
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'bundler/setup'
6
+ require 'simplycop'
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting
9
+ # with your gem easier. You can also use a different console, if you like.
10
+
11
+ # (If you use this, don't forget to add pry to your Gemfile!)
12
+ # require "pry"
13
+ # Pry.start
14
+
15
+ require 'irb'
16
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplycop/version'
4
+
5
+ module Simplycop
6
+ # NO-OP
7
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CustomCops
4
+ # This cop checks for the presence of dynamically generated constants
5
+ #
6
+ # @example
7
+ # #bad
8
+ # "FOO_BAR".constantize
9
+ #
10
+ # #good
11
+ # FOO_BAR
12
+ #
13
+ class Constantize < RuboCop::Cop::Cop
14
+ MSG = 'Avoid dynamically creating constants.'
15
+
16
+ def_node_matcher :constantizing?, '(send ... :constantize)'
17
+
18
+ def on_send(node)
19
+ return unless constantizing?(node)
20
+
21
+ add_offense(node, location: :selector)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CustomCops
4
+ # This cop checks for dynamically defining methods
5
+ #
6
+ # @example
7
+ # #bad
8
+ # Foo.define_method(:bar) { p 'bar }
9
+ #
10
+ # #good
11
+ # #create the method on the object
12
+ # class Foo
13
+ # def self.bar
14
+ # puts 'bar'
15
+ # end
16
+ # end
17
+ #
18
+ class DefineMethod < RuboCop::Cop::Cop
19
+ MSG = 'Avoid define_method.'
20
+
21
+ def_node_matcher :defining_method?, '(send _ :define_method ...)'
22
+
23
+ def on_send(node)
24
+ return unless defining_method?(node)
25
+
26
+ add_offense(node, location: :selector)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CustomCops
4
+ # This cop checks for usages of `instance_eval`
5
+ #
6
+ # @example
7
+ # #bad
8
+ # class Person
9
+ # end
10
+ #
11
+ # Person.instance_eval do
12
+ # def human?
13
+ # true
14
+ # end
15
+ # end
16
+ #
17
+ # #good
18
+ # class Person
19
+ # def self.human?
20
+ # true
21
+ # end
22
+ # end
23
+ #
24
+ class InstanceEval < RuboCop::Cop::Cop
25
+ MSG = 'Avoid instance_eval.'
26
+
27
+ def_node_matcher :instance_evaling?, '(send _ :instance_eval ...)'
28
+
29
+ def on_send(node)
30
+ return unless instance_evaling?(node)
31
+
32
+ add_offense(node, location: :selector)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CustomCops
4
+ # This cop checks for the presence of `method_missing`
5
+ #
6
+ # @example
7
+ # #bad
8
+ # def method_missing
9
+ # end
10
+ #
11
+ # #good
12
+ #
13
+ # not using method missing
14
+ #
15
+ class MethodMissing < RuboCop::Cop::Cop
16
+ MSG = 'Avoid method missing.'
17
+
18
+ def on_def(node)
19
+ return unless node.method?(:method_missing)
20
+
21
+ add_offense(node)
22
+ end
23
+ alias on_defs on_def
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CustomCops
4
+ class TimecopWithoutBlock < RuboCop::Cop::Cop
5
+ MSG = 'Avoid using `Timecop.%<method>s` without providing a block.'
6
+
7
+ def_node_matcher :timecop_method, '(send (const nil? :Timecop) ${:travel :freeze} ...)'
8
+
9
+ def on_send(node)
10
+ timecop_method(node) do |method_name|
11
+ return if !method_name || first_child_of_block?(node) || last_child_is_a_block(node)
12
+
13
+ add_offense(node, location: :selector, message: format(MSG, method: method_name))
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ # Checks if the given node's parent is a block, and the given node is its first child,
20
+ # which would mean that the block is supplied to the given node (i.e `node { block }`)
21
+ def first_child_of_block?(node)
22
+ return false unless (parent = node.parent)
23
+
24
+ return false unless parent.type == :block
25
+
26
+ parent.children.first == node
27
+ end
28
+
29
+ # Checks whether the last child of the given node is a block.
30
+ # this denotes the following structure:
31
+ # `Timecop.method(arg1, arg2, &block)`, which is also a valid way of passing in a block
32
+ def last_child_is_a_block(node)
33
+ node.children.last&.type == :block_pass
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ module Security
2
+ class CheckForVulnerableCode < RuboCop::Cop::Cop
3
+ RESULT = {}
4
+
5
+ def self.read_file
6
+ gem_path = File.expand_path("#{File.dirname(__FILE__)}../../../../")
7
+
8
+ file = File.open("#{gem_path}/vuln_db.json", "r").read.strip
9
+ json = JSON.parse(file)
10
+ json["vulnerabilities"]["rails"]
11
+ end
12
+
13
+ VULNERABILITY_LIST = read_file
14
+
15
+ VULNERABILITY_LIST.each do |string|
16
+ search = string["search_string"]
17
+ info = string["info"]
18
+
19
+ RESULT[search.to_sym] = info
20
+ def_node_matcher search.to_sym, "(send _ :#{search} _)"
21
+ end
22
+
23
+ def on_send(node)
24
+ _, method = *node
25
+ return unless method
26
+
27
+ if (info = RESULT[method])
28
+ message = "Rails: Possible vulnerability found, CVE Details - #{info} "
29
+
30
+ add_offense(node, location: :selector, message: message)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ module Security
2
+ class CSRFTokenValidation < RuboCop::Cop::Cop
3
+ MSG = 'Do not disable authenticity token validation'
4
+ def_node_matcher :skip_before_action, '(send _ :skip_before_action _)'
5
+
6
+ def on_send(node)
7
+ return unless skip_before_action(node)
8
+
9
+ _, _, parts = *node
10
+ method = parts.node_parts
11
+ add_offense(node, location: :selector) if found_match(method[0])
12
+ end
13
+
14
+ def found_match(method)
15
+ [:verify_authenticity_token , 'verify_authenticity_token'].include?(method)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ module Security
2
+ class RejectAllRequestsLocal < RuboCop::Cop::Cop
3
+ RAILS_ENV = ['integration', 'staging', 'production']
4
+
5
+ MSG = "RAILS CONFIG: Restrict usage of option 'consider_all_requests_local' on #{RAILS_ENV.join(', ')} envs"
6
+ def_node_matcher "consider_all_requests_local", '(send (send nil :config) :consider_all_requests_local= (true))'
7
+
8
+ def on_send(node)
9
+ source = node.source
10
+ file_name = node.loc.operator.to_s
11
+
12
+ add_offense(node, location: :selector) if found_match(source) && black_listed?(file_name)
13
+ end
14
+
15
+ def black_listed?(string)
16
+ RAILS_ENV.each_with_object([]) do |env, results|
17
+ results << string.include?(env)
18
+ end.any?(true)
19
+ end
20
+
21
+ def found_match(string)
22
+ string.match(/config.consider_all_requests\S?.*=\s?.*true/) ? true : false
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # === USE Semantic Versioning ===
4
+ # MAJOR version when you make incompatible API changes,
5
+ # MINOR version when you add functionality in a backwards compatible manner
6
+ # PATCH version when you make backwards compatible bug fixes.
7
+ #
8
+
9
+ module Simplycop
10
+ VERSION = '1.0.0.pre'
11
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'simplycop/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'simplycop'
9
+ spec.version = Simplycop::VERSION
10
+ spec.authors = ['Simply Business']
11
+ spec.email = ['tech@simplybusiness.co.uk']
12
+ spec.required_ruby_version = '>= 2.6.0'
13
+ spec.license = 'Copyright SimplyBusiness'
14
+ spec.summary = 'Provides a single point of reference for common rubocop rules.'
15
+ spec.description = 'Require this gem in your application to use Simply Business common rubocop rules.'
16
+ spec.homepage = 'https://github.com/simplybusiness/simplycop'
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_dependency 'rubocop', '~> 1.3.1'
21
+ spec.add_dependency 'rubocop-rails', '~> 2.8.1'
22
+ spec.add_dependency 'rubocop-rspec', '~> 2.0.0'
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake', '>= 12.3.3'
25
+ spec.add_development_dependency 'rspec', '~> 3.10'
26
+ end
@@ -0,0 +1,8 @@
1
+ {"vulnerabilities":
2
+ {"rails": [
3
+ {
4
+ "search_string": "caches_page",
5
+ "info": "https://nvd.nist.gov/vuln/detail/CVE-2020-8159"
6
+ }
7
+ ]}
8
+ }
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simplycop
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Simply Business
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubocop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.3.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.3.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.8.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.8.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 12.3.3
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 12.3.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.10'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.10'
97
+ description: Require this gem in your application to use Simply Business common rubocop
98
+ rules.
99
+ email:
100
+ - tech@simplybusiness.co.uk
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".custom_simplycop.yml"
106
+ - ".github/workflows/ci.yml"
107
+ - ".github/workflows/publish_gem.yml"
108
+ - ".github/workflows/version_forget_me_not.yml"
109
+ - ".gitignore"
110
+ - ".rspec"
111
+ - ".rubocop.yml"
112
+ - ".ruby-version"
113
+ - ".simplycop.yml"
114
+ - ".simplycop_metaprogramming.yml"
115
+ - ".simplycop_rails.yml"
116
+ - ".simplycop_rspec.yml"
117
+ - ".simplycop_security.yml"
118
+ - CODEOWNERS
119
+ - Gemfile
120
+ - README.md
121
+ - Rakefile
122
+ - bin/console
123
+ - bin/setup
124
+ - lib/simplycop.rb
125
+ - lib/simplycop/custom_cops/constantize.rb
126
+ - lib/simplycop/custom_cops/define_method.rb
127
+ - lib/simplycop/custom_cops/instance_eval.rb
128
+ - lib/simplycop/custom_cops/method_missing.rb
129
+ - lib/simplycop/custom_cops/timecop_without_block.rb
130
+ - lib/simplycop/security/check_for_vulnerable_code.rb
131
+ - lib/simplycop/security/csrf_token_validation.rb
132
+ - lib/simplycop/security/reject_all_requests_local.rb
133
+ - lib/simplycop/version.rb
134
+ - simplycop.gemspec
135
+ - vuln_db.json
136
+ homepage: https://github.com/simplybusiness/simplycop
137
+ licenses:
138
+ - Copyright SimplyBusiness
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: 2.6.0
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">"
152
+ - !ruby/object:Gem::Version
153
+ version: 1.3.1
154
+ requirements: []
155
+ rubygems_version: 3.1.4
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: Provides a single point of reference for common rubocop rules.
159
+ test_files: []