# # Standard libraries # require 'json' # # Third-party libraries # require 'rainbow' require 'rainbow/ext/string' module Hrw # # Format result and pretty print it # class Formatter # Class constructor # def initialize @count = 0 end # Filter result # # @param [Hash] result scan result # @return [Array] vulnerable or not def filter(result) deps = [] result['ancestry']['layers'].each do |layer| layer['detected_features'].each do |feature| @count += 1 deps << feature if feature.key?('vulnerabilities') end end deps end # Pretty print result # # @param [Hash] result scan result # @return [Boolean] true if has vulnerability def pretty_print(result) high = medium = low = unknown = 0 puts puts("scanning #{Dir.pwd} ...".foreground(:aliceblue)) puts deps = filter(result) deps.each do |dep| dep['vulnerabilities'].each do |vuln| patched_version = JSON.parse(vuln['fixed_by']) case vuln['severity'] when 'Defcon1', 'Critical', 'High' color = :red high += 1 when 'Medium' color = :yellow medium += 1 when 'Unknown' color = :magenta unknown += 1 else color = :aliceblue low += 1 end pkg = "#{dep['name']}@#{dep['version']}" puts "✗ #{vuln['severity']} severity vulnerability found in #{pkg.underline.bright}".foreground(color) puts 'Name:' puts " #{vuln['name']}" puts puts 'Description:' puts vuln['description'].gsub(/^/, ' ') puts puts 'Severity:' puts " #{vuln['severity']}" puts puts 'Link:' puts " #{vuln['link']}" puts puts 'Patched version:' puts " #{patched_version['spec'].join(', ')}" puts puts end end puts "Tested #{@count} dependencies for known vulnerabilities".foreground(:aliceblue) puts if deps.empty? puts '✓ no vulnerabilities found.'.foreground(:green) puts false else puts "✗ found #{high + medium + low + unknown} vulnerabilities:".foreground(:red) puts color = high > 0 ? :red : :aliceblue puts " high: #{high}".foreground(color) color = medium > 0 ? :yellow : :aliceblue puts " medium: #{medium}".foreground(color) puts " low: #{low}".foreground(:aliceblue) color = unknown > 0 ? :magenta : :aliceblue puts " unknown: #{unknown}".foreground(color) puts true end end end end