Commit 685ad038 authored by Thong Kuah's avatar Thong Kuah

Merge branch '12406-vulnerabilities-to-dependency-list' into 'master'

Merge vulnerabilities data to Dependency List report

See merge request gitlab-org/gitlab-ee!14706
parents e0109d40 ff581862
---
title: Merge vulnerabilities data into Dependency List report
merge_request: 14706
author:
type: added
...@@ -11,10 +11,12 @@ module Gitlab ...@@ -11,10 +11,12 @@ module Gitlab
def parse!(json_data, report) def parse!(json_data, report)
report_data = JSON.parse!(json_data) report_data = JSON.parse!(json_data)
report_data.fetch('dependency_files', []).each do |file| report_data.fetch('dependency_files', []).each do |file|
file['dependencies'].each do |dependency| file['dependencies'].each do |dependency|
report.add_dependency(formatter.format(dependency, file['package_manager'], file['path'])) report.add_dependency(formatter.format(dependency,
file['package_manager'],
file['path'],
report_data['vulnerabilities']))
end end
end end
end end
......
...@@ -10,7 +10,7 @@ module Gitlab ...@@ -10,7 +10,7 @@ module Gitlab
@commit_path = ::Gitlab::Routing.url_helpers.project_blob_path(project, sha) @commit_path = ::Gitlab::Routing.url_helpers.project_blob_path(project, sha)
end end
def format(dependency, package_manager, file_path) def format(dependency, package_manager, file_path, vulnerabilities = [])
{ {
name: dependency['package']['name'], name: dependency['package']['name'],
packager: packager(package_manager), packager: packager(package_manager),
...@@ -19,7 +19,8 @@ module Gitlab ...@@ -19,7 +19,8 @@ module Gitlab
blob_path: blob_path(file_path), blob_path: blob_path(file_path),
path: file_path path: file_path
}, },
version: dependency['version'] version: dependency['version'],
vulnerabilities: collect_vulnerabilities(vulnerabilities, dependency, file_path)
} }
end end
...@@ -31,6 +32,21 @@ module Gitlab ...@@ -31,6 +32,21 @@ module Gitlab
"#{commit_path}/#{file_path}" "#{commit_path}/#{file_path}"
end end
# Dependency List report is generated by dependency_scanning job.
# This is how the location is generated there
# https://gitlab.com/gitlab-org/security-products/analyzers/common/blob/a0a5074c49f34332aa3948cd9d6dc2c054cdf3a7/issue/issue.go#L169
def location(dependency, file_path)
{
"file" => file_path,
'dependency' => {
'package' => {
'name' => dependency['package']['name']
},
'version' => dependency['version']
}
}
end
def packager(package_manager) def packager(package_manager)
case package_manager case package_manager
when 'bundler' when 'bundler'
...@@ -49,6 +65,14 @@ module Gitlab ...@@ -49,6 +65,14 @@ module Gitlab
package_manager package_manager
end end
end end
def collect_vulnerabilities(vulnerabilities, dependency, file_path)
dependency_location = location(dependency, file_path)
vulnerabilities.select do |vulnerability|
vulnerability['location'] == dependency_location
end
end
end end
end end
end end
......
...@@ -30,6 +30,19 @@ describe Gitlab::Ci::Parsers::Security::DependencyList do ...@@ -30,6 +30,19 @@ describe Gitlab::Ci::Parsers::Security::DependencyList do
expect(report.dependencies[0][:location][:path]).to eq('rails/Gemfile.lock') expect(report.dependencies[0][:location][:path]).to eq('rails/Gemfile.lock')
expect(report.dependencies[12][:location][:blob_path]).to eq(blob_path) expect(report.dependencies[12][:location][:blob_path]).to eq(blob_path)
end end
it 'merge vulnerabilities data' do
vuln_nokogiri = report.dependencies[1][:vulnerabilities]
vuln_debug = report.dependencies[4][:vulnerabilities]
vuln_async = report.dependencies[3][:vulnerabilities]
expect(vuln_nokogiri.size).to eq(4)
expect(vuln_nokogiri[0]['name']).to eq('Vulnerabilities in libxml2')
expect(vuln_nokogiri[0]['severity']).to eq('Unknown')
expect(vuln_debug.size).to eq(1)
expect(vuln_debug[0]['name']).to eq('Regular Expression Denial of Service')
expect(vuln_async.size).to eq(0)
end
end end
context 'with old dependency scanning artifact' do context 'with old dependency scanning artifact' do
......
...@@ -19,17 +19,34 @@ describe Gitlab::Ci::Parsers::Security::Formatters::DependencyList do ...@@ -19,17 +19,34 @@ describe Gitlab::Ci::Parsers::Security::Formatters::DependencyList do
let(:dependency) { parsed_report['dependency_files'][0]['dependencies'][0] } let(:dependency) { parsed_report['dependency_files'][0]['dependencies'][0] }
let(:package_manager) { 'bundler' } let(:package_manager) { 'bundler' }
let(:file_path) { 'rails/Gemfile.lock' } let(:file_path) { 'rails/Gemfile.lock' }
let(:data) { formatter.format(dependency, package_manager, file_path, parsed_report['vulnerabilities']) }
let(:blob_path) { "/#{project.full_path}/blob/#{sha}/rails/Gemfile.lock" }
it 'format report into a right format' do context 'with secure dependency' do
data = formatter.format(dependency, package_manager, file_path) let(:dependency) { parsed_report['dependency_files'][0]['dependencies'][0] }
blob_path = "/#{project.full_path}/blob/#{sha}/rails/Gemfile.lock"
expect(data[:name]).to eq('mini_portile2') it 'format report into a right format' do
expect(data[:packager]).to eq('Ruby (Bundler)') expect(data[:name]).to eq('mini_portile2')
expect(data[:package_manager]).to eq('bundler') expect(data[:packager]).to eq('Ruby (Bundler)')
expect(data[:location][:blob_path]).to eq(blob_path) expect(data[:package_manager]).to eq('bundler')
expect(data[:location][:path]).to eq('rails/Gemfile.lock') expect(data[:location][:blob_path]).to eq(blob_path)
expect(data[:version]).to eq('2.2.0') expect(data[:location][:path]).to eq('rails/Gemfile.lock')
expect(data[:version]).to eq('2.2.0')
expect(data[:vulnerabilities]).to be_empty
end
end
context 'with vulnerable dependency' do
let(:dependency) { parsed_report['dependency_files'][0]['dependencies'][1] }
it 'merge vulnerabilities data' do
vulnerabilities = data[:vulnerabilities]
expect(vulnerabilities.size).to eq(4)
expect(vulnerabilities[0]['name']).to eq('Vulnerabilities in libxml2')
expect(vulnerabilities[3]['name']).to eq('Bypass of a protection mechanism in libxslt')
expect(vulnerabilities[0]['severity']).to eq('Unknown')
end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment