Class: MyPrecious::CVEs::Applicability_V4_0

Inherits:
Hash
  • Object
show all
Defined in:
lib/myprecious/cves.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(package, configs) ⇒ Applicability_V4_0

Returns a new instance of Applicability_V4_0.



123
124
125
126
127
# File 'lib/myprecious/cves.rb', line 123

def initialize(package, configs)
  super()
  self.update(configs)
  @package = package.downcase
end

Instance Attribute Details

#packageObject (readonly)

Returns the value of attribute package.



128
129
130
# File 'lib/myprecious/cves.rb', line 128

def package
  @package
end

Instance Method Details

#applies_to?(version) ⇒ Boolean

Returns:

  • (Boolean)


134
135
136
137
138
# File 'lib/myprecious/cves.rb', line 134

def applies_to?(version)
  package_nodes(nodes).any? do |node|
    version_matches_node?(version, node)
  end
end

#cpe_entry_indicates_vulnerable_version?(version, pattern) ⇒ Boolean

Returns:

  • (Boolean)


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/myprecious/cves.rb', line 188

def cpe_entry_indicates_vulnerable_version?(version, pattern)
  return false unless pattern['vulnerable']
  
  cpe_vendor, cpe_product, cpe_version, cpe_update = pattern['cpe23Uri'].split(':')[3,4]
  return false if (CVEs.config['blockedProducts'] ||= []).include?([cpe_vendor, cpe_product].join(':'))
  return false if cpe_product != @package
  if version == '*'
    return true
  end
  return false unless [nil, '*', '-'].include?(cpe_update) # We'll ignore prerelease versions
  if cpe_version != '*' && cpe_version == version
    return true
  end
  
  if (range_start = pattern['versionStartIncluding'])
    range_test = :<=
  elsif (range_start = pattern['versionStartExcluding'])
    range_test = :<
  else
    range_test = nil
  end
  if range_test && !version_compare(range_start, version).send(range_test, 0)
    return false
  end
  
  if (range_end = pattern['versionEndIncluding'])
    range_test = :<=
  elsif (range_end = pattern['versionEndExcluding'])
    range_test = :<
  else
    range_test = nil
  end
  if range_test && !version_compare(version, range_end).send(range_test, 0)
    return false
  end
  
  return range_start || range_end
end

#each_vulnerable_cpeObject



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/myprecious/cves.rb', line 154

def each_vulnerable_cpe
  return enum_for(:each_vulnerable_cpe) unless block_given?
  
  remaining = nodes.to_a.dup
  while (node = remaining.shift)
    if node['children']
      remaining.insert(0, *node['children'])
    else
      node['cpe_match'].each do |pattern|
        next unless pattern['vulnerable']
        cpe = pattern['cpe23Uri']
        if package_cpe_regexp =~ cpe
          yield cpe
        end
      end
    end
  end
end

#make_comparable(ver_str) ⇒ Object



234
235
236
# File 'lib/myprecious/cves.rb', line 234

def make_comparable(ver_str)
  ver_str.split('.').map {|p| p.to_i}
end

#nodesObject



130
131
132
# File 'lib/myprecious/cves.rb', line 130

def nodes
  self['nodes']
end

#package_cpe_regexpObject



173
174
175
# File 'lib/myprecious/cves.rb', line 173

def package_cpe_regexp
  /^cpe:2.3:a:[^:]*:#{package}(:|$)/
end

#package_nodes(node_list) ⇒ Object



146
147
148
149
150
151
152
# File 'lib/myprecious/cves.rb', line 146

def package_nodes(node_list)
  node_list.select do |node|
    node['children'] || node['cpe_match'].any? do |pattern|
      pattern['cpe23Uri'] =~ package_cpe_regexp
    end
  end
end

#vendorsObject



140
141
142
143
144
# File 'lib/myprecious/cves.rb', line 140

def vendors
  Set.new(each_vulnerable_cpe.map do |cpe|
    cpe.split(':')[3]
  end)
end

#version_compare(a, b) ⇒ Object

Return a <=> b for version strings a and b



230
231
232
# File 'lib/myprecious/cves.rb', line 230

def version_compare(a, b)
  make_comparable(a) <=> make_comparable(b)
end

#version_matches_node?(version, node) ⇒ Boolean

Returns:

  • (Boolean)


177
178
179
180
181
182
183
184
185
186
# File 'lib/myprecious/cves.rb', line 177

def version_matches_node?(version, node)
  test = (node['operator'] == 'AND') ? :all? : :any?
  if node['children']
    return node['children'].send(test) {|child| version_matches_node?(version, child)}
  end
  
  return node['cpe_match'].any? do |pattern|
    cpe_entry_indicates_vulnerable_version?(version, pattern)
  end
end