Class: Pipeline::Snyk

Inherits:
BaseTask show all
Includes:
Util
Defined in:
lib/pipeline/tasks/snyk.rb

Instance Attribute Summary

Attributes inherited from BaseTask

#appname, #description, #findings, #labels, #name, #stage, #trigger, #warnings

Instance Method Summary collapse

Methods included from Util

#fingerprint, #relative_path, #runsystem, #strip_archive_path

Methods inherited from BaseTask

#directories_with?, #report, #severity, #warn

Constructor Details

#initialize(trigger, tracker) ⇒ Snyk

Returns a new instance of Snyk.



10
11
12
13
14
15
16
17
# File 'lib/pipeline/tasks/snyk.rb', line 10

def initialize(trigger, tracker)
  super(trigger, tracker)
  @name = "Snyk"
  @description = "Snyk.io JS dependency checker"
  @stage = :code
  @labels << "code" << "javascript"
  @results = []
end

Instance Method Details

#analyzeObject



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
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/pipeline/tasks/snyk.rb', line 30

def analyze
  begin
    markdown = Redcarpet::Markdown.new Redcarpet::Render::HTML.new(link_attributes: {target: "_blank"}), autolink: true, tables: true

    @results.each do |dir_result|
      # We build a single finding for each uniq result ID, adding the unique info (upgrade path and files) as a list
      dir_result.uniq {|r| r['id']}.each do |result|
        description = "#{result['name']}@#{result['version']} - #{result['title']}"

        # Use Redcarpet to render the Markdown details to something pretty for web display
        detail = markdown.render(result['description']).gsub('h2>','strong>').gsub('h3>', 'strong>')
        upgrade_paths = [ "Upgrade Path:\n" ]
        files = []

        # Pull the list of files and upgrade paths from all results matching this ID
        # This uses the same form as the retirejs task so it all looks nice together
        dir_result.select{|r| r['id'] == result['id']}.each do |res|
          res['upgradePath'].each_with_index do |upgrade, i|
            upgrade_paths << "#{res['from'][i]} -> #{upgrade}"
          end
          files << res['from'].join('->')
        end

        source = {
          :scanner => @name,
          :file => files.join('<br>'),
          :line => nil,
          :code => upgrade_paths.uniq.join("\n"),
        }
        sev = severity(result['severity'])
        fprint = fingerprint("#{description}#{detail}#{source}#{sev}")

        report description, detail, source, sev, fprint
      end
    end
  rescue Exception => e
    Pipeline.warn e.message
    Pipeline.warn e.backtrace
  end
end

#runObject



19
20
21
22
23
24
25
26
27
28
# File 'lib/pipeline/tasks/snyk.rb', line 19

def run
  exclude_dirs = ['node_modules','bower_components']
  exclude_dirs = exclude_dirs.concat(@tracker.options[:exclude_dirs]).uniq if @tracker.options[:exclude_dirs]
  directories_with?('package.json', exclude_dirs).each do |dir|
    Pipeline.notify "#{@name} scanning: #{dir}"
    Dir.chdir(dir) do
      @results << JSON.parse(runsystem(true, "snyk", "test", "--json"))["vulnerabilities"]
    end
  end
end

#supported?Boolean

Returns:

  • (Boolean)


71
72
73
74
75
76
77
78
79
# File 'lib/pipeline/tasks/snyk.rb', line 71

def supported?
  supported = find_executable0('snyk')
  unless supported
    Pipeline.notify "Install Snyk: 'npm install -g snyk'"
    return false
  else
    return true
  end
end