CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/spec/support/lib/module_validation.rb
Views: 1904
1
require 'active_model'
2
3
module ModuleValidation
4
# Checks if values within arrays included within the passed list of acceptable values
5
class ArrayInclusionValidator < ActiveModel::EachValidator
6
def validate_each(record, attribute, value)
7
unless value.is_a?(Array)
8
record.errors.add(attribute, "#{attribute} must be an array")
9
return
10
end
11
12
invalid_options = value - options[:in]
13
message = "contains invalid values #{invalid_options.inspect} - only #{options[:in].inspect} is allowed"
14
15
if invalid_options.any?
16
record.errors.add(attribute, :array_inclusion, message: message, value: value)
17
end
18
end
19
end
20
21
# Validates module metadata
22
class Validator < SimpleDelegator
23
include ActiveModel::Validations
24
25
validate :validate_filename_is_snake_case
26
validate :validate_reference_ctx_id
27
validate :validate_author_bad_chars
28
validate :validate_target_platforms
29
30
attr_reader :mod
31
32
def initialize(mod)
33
super
34
@mod = mod
35
end
36
37
#
38
# Acceptable Stability ratings
39
#
40
VALID_STABILITY_VALUES = [
41
Msf::CRASH_SAFE,
42
Msf::CRASH_SERVICE_RESTARTS,
43
Msf::CRASH_SERVICE_DOWN,
44
Msf::CRASH_OS_RESTARTS,
45
Msf::CRASH_OS_DOWN,
46
Msf::SERVICE_RESOURCE_LOSS,
47
Msf::OS_RESOURCE_LOSS
48
]
49
50
#
51
# Acceptable Side-effect ratings
52
#
53
VALID_SIDE_EFFECT_VALUES = [
54
Msf::ARTIFACTS_ON_DISK,
55
Msf::CONFIG_CHANGES,
56
Msf::IOC_IN_LOGS,
57
Msf::ACCOUNT_LOCKOUTS,
58
Msf::SCREEN_EFFECTS,
59
Msf::AUDIO_EFFECTS,
60
Msf::PHYSICAL_EFFECTS
61
]
62
63
#
64
# Acceptable Reliability ratings
65
#
66
VALID_RELIABILITY_VALUES = [
67
Msf::FIRST_ATTEMPT_FAIL,
68
Msf::REPEATABLE_SESSION,
69
Msf::UNRELIABLE_SESSION,
70
Msf::EVENT_DEPENDENT
71
]
72
73
#
74
# Acceptable site references
75
#
76
VALID_REFERENCE_CTX_ID_VALUES = %w[
77
CVE
78
CWE
79
BID
80
MSB
81
EDB
82
US-CERT-VU
83
ZDI
84
URL
85
WPVDB
86
PACKETSTORM
87
LOGO
88
SOUNDTRACK
89
OSVDB
90
VTS
91
OVE
92
]
93
94
def validate_notes_values_are_arrays
95
notes.each do |k, v|
96
unless v.is_a?(Array)
97
errors.add :notes, "note value #{k.inspect} must be an array, got #{v.inspect}"
98
end
99
end
100
end
101
102
def validate_crash_safe_not_present_in_stability_notes
103
if rank == Msf::ExcellentRanking && !stability.include?(Msf::CRASH_SAFE)
104
errors.add :stability, "must have CRASH_SAFE value if module has an ExcellentRanking, instead found #{stability.inspect}"
105
end
106
end
107
108
def validate_filename_is_snake_case
109
unless file_path.split('/').last.match?(/^[a-z0-9]+(?:_[a-z0-9]+)*\.rb$/)
110
errors.add :file_path, "must be snake case, instead found #{file_path.inspect}"
111
end
112
end
113
114
def validate_reference_ctx_id
115
references_ctx_id_list = references.map(&:ctx_id)
116
invalid_references = references_ctx_id_list - VALID_REFERENCE_CTX_ID_VALUES
117
118
invalid_references.each do |ref|
119
if ref.casecmp?('NOCVE')
120
errors.add :references, "#{ref} please include NOCVE values in the 'notes' section, rather than in 'references'"
121
elsif ref.casecmp?('AKA')
122
errors.add :references, "#{ref} please include AKA values in the 'notes' section, rather than in 'references'"
123
else
124
errors.add :references, "#{ref} is not valid, must be in #{VALID_REFERENCE_CTX_ID_VALUES}"
125
end
126
end
127
end
128
129
def validate_author_bad_chars
130
author.each do |i|
131
if i.name =~ /^@.+$/
132
errors.add :author, "must not include username handles, found #{i.name.inspect}. Try leaving it in a comment instead"
133
end
134
end
135
end
136
137
def validate_target_platforms
138
if platform.blank? && type == 'exploit'
139
targets.each do |target|
140
if target.platform.blank?
141
errors.add :platform, 'must be included either within targets or platform module metadata'
142
end
143
end
144
end
145
end
146
147
def has_notes?
148
!notes.empty?
149
end
150
151
validates :mod, presence: true
152
153
with_options if: :has_notes? do |mod|
154
mod.validate :validate_crash_safe_not_present_in_stability_notes
155
mod.validate :validate_notes_values_are_arrays
156
157
mod.validates :stability,
158
'module_validation/array_inclusion': { in: VALID_STABILITY_VALUES }
159
160
mod.validates :side_effects,
161
'module_validation/array_inclusion': { in: VALID_SIDE_EFFECT_VALUES }
162
163
mod.validates :reliability,
164
'module_validation/array_inclusion': { in: VALID_RELIABILITY_VALUES }
165
end
166
167
validates :license,
168
presence: true,
169
inclusion: { in: LICENSES, message: 'must include a valid license' }
170
171
validates :rank,
172
presence: true,
173
inclusion: { in: Msf::RankingName.keys, message: 'must include a valid module ranking' }
174
175
validates :author,
176
presence: true
177
178
validates :name,
179
presence: true,
180
format: { with: /\A[^&<>]+\z/, message: 'must not contain the characters &<>' }
181
182
validates :description,
183
presence: true
184
end
185
end
186
187