Class: Dawn::Kb::VersionCheck

Inherits:
Object
  • Object
show all
Includes:
BasicCheck
Defined in:
lib/dawn/kb/version_check.rb

Constant Summary

Constants included from BasicCheck

BasicCheck::ALLOWED_FAMILIES

Instance Attribute Summary collapse

Attributes included from BasicCheck

#applies, #aux_links, #check_family, #cve, #cvss, #cwe, #debug, #evidences, #fixes_version, #kind, #message, #mitigated, #name, #osvdb, #owasp, #priority, #release_date, #remediation, #ruby_version, #ruby_vulnerable_versions, #severity, #target_version, #title

Instance Method Summary collapse

Methods included from BasicCheck

#applies_to?, #cve_link, #cvss_score, families, #family, #family=, #lint, #mitigated?, #nvd_link, #osvdb_link, #rubysec_advisories_link

Methods included from Utils

#__debug_me_and_return, #debug_me, #debug_me_and_return_false, #debug_me_and_return_true

Constructor Details

#initialize(options = {}) ⇒ VersionCheck

Returns a new instance of VersionCheck.



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/dawn/kb/version_check.rb', line 16

def initialize(options={})
  super(options)
  @safe       ||= options[:safe]
  @deprecated ||= options[:deprecated]
  @excluded   ||= options[:excluded]
  @detected   ||= options[:detected]
  @save_minor ||= options[:save_minor]
  @save_major ||= options[:save_major]
  @debug      ||= options[:debug]
  @enable_warning ||= options[:enable_warning]
  debug_me "VersionCheck initialized"
end

Instance Attribute Details

#deprecatedObject

Returns the value of attribute deprecated.



7
8
9
# File 'lib/dawn/kb/version_check.rb', line 7

def deprecated
  @deprecated
end

#detectedObject

Returns the value of attribute detected.



9
10
11
# File 'lib/dawn/kb/version_check.rb', line 9

def detected
  @detected
end

#enable_warningObject

Returns the value of attribute enable_warning.



13
14
15
# File 'lib/dawn/kb/version_check.rb', line 13

def enable_warning
  @enable_warning
end

#excludedObject

Returns the value of attribute excluded.



8
9
10
# File 'lib/dawn/kb/version_check.rb', line 8

def excluded
  @excluded
end

#safeObject

Returns the value of attribute safe.



6
7
8
# File 'lib/dawn/kb/version_check.rb', line 6

def safe
  @safe
end

#save_majorObject

Returns the value of attribute save_major.



11
12
13
# File 'lib/dawn/kb/version_check.rb', line 11

def save_major
  @save_major
end

#save_minorObject

Returns the value of attribute save_minor.



10
11
12
# File 'lib/dawn/kb/version_check.rb', line 10

def save_minor
  @save_minor
end

#statusObject (readonly)

Returns the value of attribute status.



12
13
14
# File 'lib/dawn/kb/version_check.rb', line 12

def status
  @status
end

Instance Method Details

#is_beta_check?(safe_version_beta, detected_version_beta) ⇒ Boolean

Beta version handling

Returns:

  • (Boolean)


252
253
254
# File 'lib/dawn/kb/version_check.rb', line 252

def is_beta_check?(safe_version_beta, detected_version_beta)
  ( safe_version_beta != 0 || detected_version_beta != 0)
end

#is_deprecated?(detected_version) ⇒ Boolean

Returns:

  • (Boolean)


358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/dawn/kb/version_check.rb', line 358

def is_deprecated?(detected_version)
  return false if detected_version.nil?
  return false if @deprecated.nil?
  @deprecated.each do |dep|
    dep_v = version_string_to_array(dep)[:version]
    det_v = version_string_to_array(detected_version)[:version]
    return true if is_same_version?(dep_v, det_v)
    if dep_v[0] == 'x'
      # deprecation version is something like 'x.0.0'. This is a
      # nonsense since it means all versions are deprecated. However
      # I'll support also nonsense checks.

      $logger.warn "Setting the predicate #{dep} will mark all versions as deprecated" unless self.enable_warning.nil?
      debug_me "You kindly mark #{detected_version} as deprecated with this predicate #{dep}"
      return true
    end

    if dep_v[1] == 'x'
      # deprecation version is something like 1.x
      # detected version is deprecated if major == 1. If 0 not
      return true if det_v[0] == dep_v[0]
    end

    if dep_v[2] == 'x'
      # deprecation version is something like 1.2.x
      # detected version is deprecated if major == 1 and minor == 2.
      return true if det_v[0] == dep_v[0] && det_v[1] == dep_v[1]

    end
  end
  false
end

#is_detected_deprecated?Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/dawn/kb/version_check.rb', line 74

def is_detected_deprecated?
  return is_deprecated?(@detected)
end

#is_detected_excluded?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/dawn/kb/version_check.rb', line 77

def is_detected_excluded?
  return is_excluded?(@detected)
end

#is_detected_highest?Boolean

Returns:

  • (Boolean)


66
67
68
69
70
71
72
73
# File 'lib/dawn/kb/version_check.rb', line 66

def is_detected_highest?
  higher= @detected
  @safe.sort.each do |s|
    debug_me("higher is #{higher}")
    higher=s if is_higher?(s, higher)
  end
  return (higher == @detected)
end

#is_detected_in_safe?Boolean

Returns:

  • (Boolean)


59
60
61
62
63
64
# File 'lib/dawn/kb/version_check.rb', line 59

def is_detected_in_safe?
  @safe.each do |s|
    return true if @detected == s
  end
  return false
end

#is_excluded?(detected_version) ⇒ Boolean

Returns:

  • (Boolean)


348
349
350
351
352
353
354
355
356
357
# File 'lib/dawn/kb/version_check.rb', line 348

def is_excluded?(detected_version)
  return false if detected_version.nil?
  return false if @excluded.nil?
  @excluded.each do |exc|
    exc_v = version_string_to_array(exc)[:version]
    det_v = version_string_to_array(detected_version)[:version]
    return true if is_same_version?(exc_v, det_v)
  end
  return false
end

#is_good_parameter?(array) ⇒ Boolean

Returns:

  • (Boolean)


174
175
176
177
178
# File 'lib/dawn/kb/version_check.rb', line 174

def is_good_parameter?(array)
  return false if array.nil?
  return false if array.empty?
  return true
end

#is_higher?(a, b) ⇒ Boolean

Public: tells if a version is higher than another

e.g.

is_higher?('2.3.2', '2.4.2') => true
is_higher?('2.3.2', '2.3.2') => true

Returns:

  • (Boolean)


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/dawn/kb/version_check.rb', line 92

def is_higher?(a, b)
  aa = version_string_to_array(a)
  ba = version_string_to_array(b)

  ver = false
  beta = false
  rc = false
  same = false

  # Version arrays are just major.minor version. Let's assume
  # patchlevel is 0 for sake of comparison.
  aa[:version] << 0 if aa[:version].count == 2
  ba[:version] << 0 if ba[:version].count == 2
  ver = true if aa[:version][0] > ba[:version][0]
  ver = true if aa[:version][0] == ba[:version][0] && aa[:version][1] > ba[:version][1]
  ver = true if aa[:version].count == 3 && ba[:version].count == 3 && aa[:version][0] == ba[:version][0] && aa[:version][1] == ba[:version][1] && aa[:version][2] > ba[:version][2]
  ver = true if aa[:version].count == 4 && ba[:version].count == 4 && aa[:version][0] == ba[:version][0] && aa[:version][1] == ba[:version][1] && aa[:version][2] == ba[:version][2] && aa[:version][3] > ba[:version][3]
  ver = true if aa[:version].count == 4 && ba[:version].count == 4 && aa[:version][0] == ba[:version][0] && aa[:version][1] == ba[:version][1] && aa[:version][2] > ba[:version][2]
  same = is_same_version?(aa[:version], ba[:version])
  beta = true if aa[:beta] >= ba[:beta]
  rc = true if aa[:rc] >= ba[:rc]

  ret = false
  ret = ver && beta && rc unless same
  ret = beta && rc if same

  debug_me("is_higher? a=#{a}, b=#{b} VER=#{ver} - BETA=#{beta} - RC=#{rc} - SAME=#{same} - a>b? = (#{ret})")
  return ret
end

#is_higher_major?(s, d) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
84
85
# File 'lib/dawn/kb/version_check.rb', line 81

def is_higher_major?(s,d)
  sa = version_string_to_array(s)[:version]
  da = version_string_to_array(d)[:version]
  return (sa[0] > da[0])
end

#is_pre_check?(safe_version_pre, detected_version_pre) ⇒ Boolean

pre version handling

Returns:

  • (Boolean)


296
297
298
# File 'lib/dawn/kb/version_check.rb', line 296

def is_pre_check?(safe_version_pre, detected_version_pre)
  ( safe_version_pre != 0 || detected_version_pre != 0)
end

#is_rc_check?(safe_version_rc, detected_version_rc) ⇒ Boolean

Rc version handling

Returns:

  • (Boolean)


273
274
275
# File 'lib/dawn/kb/version_check.rb', line 273

def is_rc_check?(safe_version_rc, detected_version_rc)
  ( safe_version_rc != 0 || detected_version_rc != 0)
end

#is_same_major?(array_a, array_b) ⇒ Boolean

It checks if the first digit of a version array is the same

e.g. has_same_major?(, [1,2,2]) #=> false has_same_major?(, [2,2,2]) #=> true

Returns:

  • (Boolean)


185
186
187
188
# File 'lib/dawn/kb/version_check.rb', line 185

def is_same_major?(array_a, array_b)
  return false if ! is_good_parameter?(array_a) || ! is_good_parameter?(array_b)
  return (array_a[0] == array_b[0])
end

#is_same_minor?(array_a, array_b) ⇒ Boolean

Returns:

  • (Boolean)


189
190
191
192
# File 'lib/dawn/kb/version_check.rb', line 189

def is_same_minor?(array_a, array_b)
  return false if ! is_good_parameter?(array_a) || ! is_good_parameter?(array_b)
  return (array_a[1] == array_b[1])
end

#is_same_patch?(array_a, array_b) ⇒ Boolean

Returns:

  • (Boolean)


193
194
195
196
# File 'lib/dawn/kb/version_check.rb', line 193

def is_same_patch?(array_a, array_b)
  return false if ! is_good_parameter?(array_a) || ! is_good_parameter?(array_b)
  return (array_a[2] == array_b[2])
end

#is_same_version?(safe_version_array, detected_version_array) ⇒ Boolean

Returns:

  • (Boolean)


235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/dawn/kb/version_check.rb', line 235

def is_same_version?(safe_version_array, detected_version_array)
  ret = false

  ret = true if (safe_version_array[0] == detected_version_array[0]) if (safe_version_array[1] == 'x')
  ret = true if (safe_version_array[0] == detected_version_array[0]) && (safe_version_array[1] == detected_version_array[1]) && (safe_version_array.count == 2) && (detected_version_array.count == 2)
  ret = true if (safe_version_array[0] == detected_version_array[0]) && (safe_version_array[1] == detected_version_array[1]) && (safe_version_array[2] == detected_version_array[2]) && (safe_version_array.count == 3) && (detected_version_array.count == 3)
  ret = true if (safe_version_array[0] == detected_version_array[0]) && (safe_version_array[1] == detected_version_array[1]) && (safe_version_array[2] == detected_version_array[2]) && (safe_version_array[3] == detected_version_array[3]) && (safe_version_array.count == 4) && (detected_version_array.count == 4)

  debug_me "is_same_version? SVA=#{safe_version_array} DVA=#{detected_version_array} RET=#{ret}"

  return ret
end

#is_there_an_higher_major_version?Boolean

checks in the array if there is another string with higher major version

Returns:

  • (Boolean)


123
124
125
126
127
128
129
130
131
# File 'lib/dawn/kb/version_check.rb', line 123

def is_there_an_higher_major_version?
  dva = version_string_to_array(@detected)[:version]
  @safe.sort.each do |s|
    sva = version_string_to_array(s)[:version]
    debug_me "is_there_an_higher_major_version? DVA=#{dva} - SVA=#{sva}"
    return debug_me_and_return_true("is_there_an_higher_major_version? is returning true for #{@detected}") if dva[0] < sva[0]
  end
  return debug_me_and_return_false("is_there_an_higher_major_version? is returning false")
end

#is_there_an_higher_minor_version?Boolean

checks in the array if there is another string with higher minor version but the same major as the parameter element)

Returns:

  • (Boolean)


134
135
136
137
138
139
140
141
# File 'lib/dawn/kb/version_check.rb', line 134

def is_there_an_higher_minor_version?
  dva = version_string_to_array(@detected)[:version]
  @safe.sort.each do |s|
    sva = version_string_to_array(s)[:version]
    return true if dva[0] == sva[0] && dva[1] < sva[1]
  end
  return false
end

#is_vulnerable_aux_patch?(safe_version, detected_version) ⇒ Boolean

Returns:

  • (Boolean)


206
207
208
209
# File 'lib/dawn/kb/version_check.rb', line 206

def is_vulnerable_aux_patch?(safe_version, detected_version)
  return false if safe_version[3].nil? || detected_version[3].nil?
  return (safe_version[3] > detected_version[3])
end

#is_vulnerable_beta?(safe_version_beta, detected_version_beta) ⇒ Boolean

Returns:

  • (Boolean)


256
257
258
259
260
261
262
263
264
265
266
# File 'lib/dawn/kb/version_check.rb', line 256

def is_vulnerable_beta?(safe_version_beta, detected_version_beta)
  # if the safe_version_beta is 0 then the detected_version_beta is
  # vulnerable by design, since the safe version is a stable and we
  # detected a beta.
  return true if safe_version_beta == 0 && detected_version_beta != 0
  return false if safe_version_beta <= detected_version_beta
  return true if safe_version_beta > detected_version_beta

  # fallback
  return false
end

#is_vulnerable_major?(safe_version, detected_version) ⇒ Boolean

Returns:

  • (Boolean)


198
199
200
# File 'lib/dawn/kb/version_check.rb', line 198

def is_vulnerable_major?(safe_version, detected_version)
  return (safe_version[0] > detected_version[0])
end

#is_vulnerable_minor?(safe_version, detected_version) ⇒ Boolean

Returns:

  • (Boolean)


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/dawn/kb/version_check.rb', line 212

def is_vulnerable_minor?(safe_version, detected_version)
  if safe_version.length < detected_version.length
    # safe version is just the major number e.g. 2
    # detected version is kinda more complex e.g. 2.3.2 or 1.2.3
    # we relay on major here
    return is_vulnerable_major?(safe_version, detected_version)
  end
  if safe_version.length > detected_version.length
    # detected version is just the major number e.g. 2
    # safe version is kinda more complex e.g. 2.3.2
    # in this case we return the version is vulnerable if the
    # detected_version major is less or equal the safe one.
    return (safe_version[0] <= detected_version[0])
  end

  # support for x as safe minor version
  return false if is_same_major?(safe_version, detected_version) && safe_version[1] == 'x'
  return false if safe_version[0] <= detected_version[0] && safe_version[1] == 'x'
  return true if safe_version[0] > detected_version[0] && safe_version[1] == 'x'
  return true if safe_version[1] > detected_version[1]
  return false if safe_version[1] <= detected_version[1]
end

#is_vulnerable_patch?(safe_version, detected_version) ⇒ Boolean

Returns:

  • (Boolean)


202
203
204
205
# File 'lib/dawn/kb/version_check.rb', line 202

def is_vulnerable_patch?(safe_version, detected_version)
  return false if safe_version[2].nil? || detected_version[2].nil?
  return (safe_version[2] > detected_version[2])
end

#is_vulnerable_pre?(safe_version_pre, detected_version_pre) ⇒ Boolean

Returns:

  • (Boolean)


300
301
302
303
304
305
306
307
308
309
310
# File 'lib/dawn/kb/version_check.rb', line 300

def is_vulnerable_pre?(safe_version_pre, detected_version_pre)
  # if the safe_version_pre is 0 then the detected_version_pre is
  # vulnerable by design, since the safe version is a stable and we
  # detected a pre.
  return true if safe_version_pre == 0 && detected_version_pre != 0
  return false if safe_version_pre <= detected_version_pre
  return true if safe_version_pre > detected_version_pre

  # fallback
  return false
end

#is_vulnerable_rc?(safe_version_rc, detected_version_rc) ⇒ Boolean

Returns:

  • (Boolean)


277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/dawn/kb/version_check.rb', line 277

def is_vulnerable_rc?(safe_version_rc, detected_version_rc)
  # if the safe_version_rc is 0 then the detected_version_rc is
  # vulnerable by design, since the safe version is a stable and we
  # detected a rc.
  debug_me "entering is_vulnerable_rc?: s=#{safe_version_rc}, d=#{detected_version_rc}"
  return true if safe_version_rc == 0 && detected_version_rc != 0
  return false if safe_version_rc != 0 && detected_version_rc == 0
  return false if safe_version_rc <= detected_version_rc
  return true if safe_version_rc > detected_version_rc

  # fallback
  return false
end

#is_vulnerable_version?(safe_version, detected_version) ⇒ Boolean

Returns:

  • (Boolean)


312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/dawn/kb/version_check.rb', line 312

def is_vulnerable_version?(safe_version, detected_version)
  sva = version_string_to_array(safe_version)
  dva = version_string_to_array(detected_version)
  safe_version_array = sva[:version]
  detected_version_array = dva[:version]

  safe_version_array << 0 if safe_version_array.count == 2
  detected_version_array << 0 if detected_version_array.count == 2

  major = is_vulnerable_major?(safe_version_array, detected_version_array)
  minor = is_vulnerable_minor?(safe_version_array, detected_version_array)
  patch = is_vulnerable_patch?(safe_version_array, detected_version_array)
  aux_patch = is_vulnerable_aux_patch?(safe_version_array, detected_version_array)

  debug_me "is_vulnerable_version? S=#{safe_version},D=#{detected_version} -> MAJOR=#{major} MINOR=#{minor} PATCH=#{patch} AUX_PATCH=#{aux_patch} SAVE_MINOR=#{@save_minor_fix} SAVE_MAJOR=#{@save_major_fix}"

  return is_vulnerable_beta?(sva[:beta], dva[:beta]) if is_same_version?(safe_version_array, detected_version_array) && is_beta_check?(sva[:beta], dva[:beta])
  return is_vulnerable_rc?(sva[:rc], dva[:rc]) if is_same_version?(safe_version_array, detected_version_array) && is_rc_check?(sva[:rc], dva[:rc])
  return is_vulnerable_pre?(sva[:pre], dva[:pre]) if is_same_version?(safe_version_array, detected_version_array) && is_pre_check?(sva[:pre], dva[:pre])

  # we have a non vulnerable major, but the minor is and there is an higher version in array
  # eg. we detected v1.3.2, safe version is 1.3.3 and there is also a safe 2.x.x
  return debug_me_and_return_false("#{detected_version} has a major version vulnerable but honoring save_major_fix") if major && @save_major_fix
  return debug_me_and_return_false("#{detected_version} has a minor version vulnerable but honoring save_minor_fix") if minor && @save_minor_fix
  return true if major && minor
  return true if ! major && minor && patch && ! @save_major_fix && ! @save_minor_fix
  return true if major && !@save_major_fix
  return true if !major && minor && @save_major_fix
  return patch if is_same_major?(safe_version_array, detected_version_array) && is_same_minor?(safe_version_array, detected_version_array) && !aux_patch
  return aux_patch if is_same_major?(safe_version_array, detected_version_array) && is_same_minor?(safe_version_array, detected_version_array) && is_same_patch?(safe_version_array, detected_version_array)
  return true if is_same_major?(safe_version_array, detected_version_array) && is_same_minor?(safe_version_array, detected_version_array) && patch && aux_patch
  return true if is_same_major?(safe_version_array, detected_version_array) && minor

  return false
end

#save_major_fixObject



143
144
145
146
# File 'lib/dawn/kb/version_check.rb', line 143

def save_major_fix
  return false unless @save_major
  return is_there_an_higher_major_version?
end

#save_minor_fixObject

This functions handles an hack to save a detected version even if a safe version with an higher minor version number has been found.

This is mostly used in rails where there are different versions and if a 3.2.12 is safe it should not marked as vulnerable just because you can either use 3.3.x that is a different branch.

It returns true when the detected version must be saved, false otherwise.



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/dawn/kb/version_check.rb', line 156

def save_minor_fix
  return false unless @save_minor
  hm = is_there_an_higher_minor_version?

  # This is the save minor version workaround.
  # fixes is something like ['2.2.2', '3.1.1', '3.2.2']
  # target is '3.1.1' and save_minor_fixes is true
  # I don't want that check for 3.2.2 marks this as vulnerable, so I will save it
  dva = version_string_to_array(@detected)[:version]
  @safe.sort.each do |s|
    sva = version_string_to_array(s)[:version]
    debug_me("#SVA=#{sva};DVA=#{dva};SM=#{is_same_major?(sva, dva)};sm=#{is_same_minor?(sva, dva)}; ( dva[2] >= sva[2] )=#{(dva[2] >= sva[2])}")
    return true if is_same_major?(sva, dva) && is_same_minor?(sva, dva) && dva[2] >= sva[2] && hm
    return true if is_same_major?(sva, dva) && hm
  end
  return false
end

#version_string_to_array(string) ⇒ Object

It takes a string representing a version and it splits it in an Hash.

e.g. version_string_to_array(“3.2.3”) #=> href="3,2,3">version=>, :beta=>0, :rc=>0 version_string_to_array(“3.2.2.beta1”) #=> href="3,2,2">version=>, :beta=>1, :rc=>0



398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
# File 'lib/dawn/kb/version_check.rb', line 398

def version_string_to_array(string)
  # I can't use this nice onliner... stays here until I finish writing new code.
  # return string.split(".").map! { |n| (n=='x')? n : n.to_i }
  ver   = []
  beta  = 0
  rc    = 0
  pre   = 0

  string.split(".").each do |x|
    ver << x.to_i unless x == 'x' || x.start_with?('beta') || x.start_with?('rc') || x.start_with?('pre')
    ver << x if x == 'x'

    beta = x.split("beta")[1].to_i if x.class == String && x.start_with?('beta') && beta == 0
    rc = x.split("rc")[1].to_i if x.class == String && x.start_with?('rc') && rc == 0
    pre = x.split("pre")[1].to_i if x.class == String && x.start_with?('pre') && pre == 0

  end
  {:version=>ver, :beta=>beta, :rc=>rc, :pre=>pre}
end

#vuln?Boolean

Returns:

  • (Boolean)


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/dawn/kb/version_check.rb', line 29

def vuln?
  debug_me "Detected version is #{@detected}"
  debug_me "Safe versions array is #{@safe}"
  debug_me "Deprecated versions array is #{@deprecated}. I'll mark them as vulnerable" unless @deprecated.nil?
  debug_me "Excluded versions array is #{@excluded}. I'll mark them as not vulnerable" unless @excluded.nil?
  debug_me "SAVE_MINOR FLAG = #{@save_minor}"
  debug_me "SAVE_MAJOR FLAG = #{@save_major}"

  @status = :deprecated if is_detected_deprecated?
  return debug_me_and_return_false("detected version #{detected} is marked to be excluded for vulnerable ones")   if is_detected_excluded?

  # is the detected version in the safe array?
  return debug_me_and_return_false("detected version #{@detected} found as is in safe array")      if is_detected_in_safe?
  return debug_me_and_return_false("detected version #{@detected} is higher than all version marked safe")  if is_detected_highest?

  @safe.sort.each do |s|

    @save_minor_fix   = save_minor_fix
    @save_major_fix   = save_major_fix


    vuln  = is_vulnerable_version?(s, @detected)

    debug_me "VULN=#{vuln} SAVE_MINOR=#{@save_minor_fix} SAVE_MAJOR=#{@save_major_fix}"
    return true if vuln
  end

  return false
end