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.
- checksums.yaml +7 -0
- data/.custom_simplycop.yml +11 -0
- data/.github/workflows/ci.yml +34 -0
- data/.github/workflows/publish_gem.yml +26 -0
- data/.github/workflows/version_forget_me_not.yml +17 -0
- data/.gitignore +37 -0
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -0
- data/.simplycop.yml +447 -0
- data/.simplycop_metaprogramming.yml +38 -0
- data/.simplycop_rails.yml +100 -0
- data/.simplycop_rspec.yml +234 -0
- data/.simplycop_security.yml +25 -0
- data/CODEOWNERS +3 -0
- data/Gemfile +6 -0
- data/README.md +73 -0
- data/Rakefile +3 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/lib/simplycop.rb +7 -0
- data/lib/simplycop/custom_cops/constantize.rb +24 -0
- data/lib/simplycop/custom_cops/define_method.rb +29 -0
- data/lib/simplycop/custom_cops/instance_eval.rb +35 -0
- data/lib/simplycop/custom_cops/method_missing.rb +25 -0
- data/lib/simplycop/custom_cops/timecop_without_block.rb +36 -0
- data/lib/simplycop/security/check_for_vulnerable_code.rb +34 -0
- data/lib/simplycop/security/csrf_token_validation.rb +18 -0
- data/lib/simplycop/security/reject_all_requests_local.rb +25 -0
- data/lib/simplycop/version.rb +11 -0
- data/simplycop.gemspec +26 -0
- data/vuln_db.json +8 -0
- metadata +159 -0
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -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
|
data/bin/setup
ADDED
data/lib/simplycop.rb
ADDED
@@ -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
|
data/simplycop.gemspec
ADDED
@@ -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
|
data/vuln_db.json
ADDED
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: []
|