Commit e7d4f2d3 authored by mo khan's avatar mo khan Committed by Lin Jen-Shin

Reproduce sentry errors

* Add case insensitive match for severity

```text
NoMethodError: undefined method `each' for nil:NilClass
  from gitlab/ci/parsers/security/common.rb:14:in `parse!'
  from ee/ci/build.rb:118:in `parse_security_artifact_blob'
  from ee/ci/build.rb:57:in `block (2 levels) in collect_security_report
  from ee/ci/build.rb:54:in `tap'
  from ee/ci/build.rb:54:in `block in collect_security_reports!'
  from ci/build.rb:828:in `block (2 levels) in each_report'
  from gitlab/ci/build/artifacts/adapters/raw_stream.rb:22:in `each_blob
  from ci/job_artifact.rb:183:in `block in each_blob'
  from gitlab_uploader.rb:96:in `open'
```
https://sentry.gitlab.net/gitlab/gitlabcom/issues/991284/events/20532078

```text
NoMethodError: undefined method `[]' for nil:NilClass
  from gitlab/ci/parsers/security/dependency_scanning.rb:16:in `create_
  from gitlab/ci/parsers/security/common.rb:53:in `create_vulnerability
  from gitlab/ci/parsers/security/common.rb:15:in `block in parse!'
  from gitlab/ci/parsers/security/common.rb:14:in `each'
  from gitlab/ci/parsers/security/common.rb:14:in `parse!'
  from ee/ci/build.rb:116:in `parse_security_artifact_blob'
  from ee/ci/build.rb:55:in `block (2 levels) in collect_security_report
  from ee/ci/build.rb:52:in `tap'
  from ee/ci/build.rb:52:in `block in collect_security_reports!'
  from ci/build.rb:828:in `block (2 levels) in each_report'
```
https://sentry.gitlab.net/gitlab/gitlabcom/issues/972642/events/20413167

```text
TypeError: no implicit conversion of nil into String
  from gitlab/ci/reports/security/occurrence.rb:78:in `digest'
  from gitlab/ci/reports/security/occurrence.rb:78:in `hexdigest'
  from gitlab/ci/reports/security/occurrence.rb:78:in `generate_project_
  from gitlab/ci/reports/security/occurrence.rb:37:in `initialize'
  from gitlab/ci/parsers/security/common.rb:48:in `new'
  from gitlab/ci/parsers/security/common.rb:48:in `create_vulnerability'
  from gitlab/ci/parsers/security/common.rb:15:in `block in parse!'
  from gitlab/ci/parsers/security/common.rb:14:in `each'
  from gitlab/ci/parsers/security/common.rb:14:in `parse!'
  from ee/ci/build.rb:113:in `parse_security_artifact_blob'
  from ee/ci/build.rb:64:in `block (2 levels) in collect_security_report
  from ee/ci/build.rb:61:in `tap'
  from ee/ci/build.rb:61:in `block in collect_security_reports!'
  from ci/build.rb:821:in `block (2 levels) in each_report'
```

https://sentry.gitlab.net/gitlab/gitlabcom/issues/903549/events/18937780
parent e1dc0db2
......@@ -37,12 +37,11 @@ module Security
end
def sync_vulnerability_rules
reports = pipeline.security_reports.reports
safe = reports.any? && reports.none? do |_report_type, report|
report.unsafe_severity?
end
reports = pipeline.security_reports
return if reports.empty? && !pipeline.complete?
return if reports.violates_default_policy?
remove_required_approvals_for(ApprovalMergeRequestRule.security_report) if safe
remove_required_approvals_for(ApprovalMergeRequestRule.security_report)
end
def remove_required_approvals_for(rules)
......
---
title: Prevent parser errors from approving the License-Check rule
merge_request: 18423
author:
type: fixed
......@@ -29,7 +29,7 @@ module Gitlab
# map remediations to relevant vulnerabilities
def collate_remediations(report_data)
return report_data["vulnerabilities"] unless report_data["remediations"]
return report_data["vulnerabilities"] || [] unless report_data["remediations"]
report_data["vulnerabilities"].map do |vulnerability|
# Grab the first available remediation.
......@@ -49,8 +49,8 @@ module Gitlab
uuid: SecureRandom.uuid,
report_type: report.type,
name: data['message'],
compare_key: data['cve'],
location: create_location(data['location']),
compare_key: data['cve'] || '',
location: create_location(data['location'] || {}),
severity: parse_level(data['severity']),
confidence: parse_level(data['confidence']),
scanner: scanner,
......
......@@ -54,7 +54,12 @@ module Gitlab
end
def unsafe_severity?
occurrences.any? { |occurrence| UNSAFE_SEVERITIES.include?(occurrence.severity) }
!safe?
end
def safe?
severities = occurrences.map(&:severity).compact.map(&:downcase)
(severities & UNSAFE_SEVERITIES).size.zero?
end
end
end
......
......@@ -7,6 +7,8 @@ module Gitlab
class Reports
attr_reader :reports, :commit_sha
delegate :empty?, to: :reports
def initialize(commit_sha)
@reports = {}
@commit_sha = commit_sha
......@@ -15,6 +17,12 @@ module Gitlab
def get_report(report_type)
reports[report_type] ||= Report.new(report_type, commit_sha)
end
def violates_default_policy?
reports.values.any? do |report|
report.unsafe_severity?
end
end
end
end
end
......
......@@ -49,6 +49,26 @@ describe Gitlab::Ci::Parsers::Security::DependencyScanning do
end
end
context "when parsing a vulnerability with a missing location" do
let(:report_hash) { JSON.parse(fixture_file('security_reports/master/gl-sast-report.json', dir: 'ee'), symbolize_names: true) }
before do
report_hash[:vulnerabilities][0][:location] = nil
end
it { expect { parser.parse!(report_hash.to_json, report) }.not_to raise_error }
end
context "when parsing a vulnerability with a missing cve" do
let(:report_hash) { JSON.parse(fixture_file('security_reports/master/gl-sast-report.json', dir: 'ee'), symbolize_names: true) }
before do
report_hash[:vulnerabilities][0][:cve] = nil
end
it { expect { parser.parse!(report_hash.to_json, report) }.not_to raise_error }
end
context "when vulnerabilities have remediations" do
let(:artifact) { create(:ee_ci_job_artifact, :dependency_scanning_remediation) }
......
......@@ -4,14 +4,15 @@ require 'spec_helper'
describe Gitlab::Ci::Parsers::Security::Sast do
describe '#parse!' do
let(:project) { artifact.project }
let(:pipeline) { artifact.job.pipeline }
let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline.sha) }
let(:parser) { described_class.new }
subject(:parser) { described_class.new }
let(:commit_sha) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
context "when parsing valid reports" do
where(report_format: %i(sast sast_deprecated))
with_them do
let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, commit_sha) }
let(:artifact) { create(:ee_ci_job_artifact, report_format) }
before do
......@@ -44,4 +45,12 @@ describe Gitlab::Ci::Parsers::Security::Sast do
end
end
end
context "when parsing an empty report" do
let(:report) { Gitlab::Ci::Reports::Security::Report.new('sast', commit_sha) }
let(:blob) { JSON.generate({}) }
it { expect(parser.parse!(blob, report)).to be_empty }
end
end
end
......@@ -119,4 +119,63 @@ describe Gitlab::Ci::Reports::Security::Report do
expect(report).to have_received(:replace_with!).with(merged_report)
end
end
describe "#safe?" do
subject { described_class.new('sast', commit_sha) }
let(:commit_sha) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
%w[unknown Unknown high High critical Critical].each do |severity|
context "when the sast report has a #{severity} severity vulnerability" do
let(:occurrence) { build(:ci_reports_security_occurrence, severity: severity) }
before do
subject.add_occurrence(occurrence)
end
it { expect(subject.unsafe_severity?).to be(true) }
it { expect(subject.safe?).to be(false) }
end
end
%w[medium Medium low Low].each do |severity|
context "when the sast report has a #{severity} severity vulnerability" do
let(:occurrence) { build(:ci_reports_security_occurrence, severity: severity) }
before do
subject.add_occurrence(occurrence)
end
it { expect(subject.unsafe_severity?).to be(false) }
it { expect(subject.safe?).to be(true) }
end
end
context "when the sast report has a vulnerability with a `nil` severity" do
let(:occurrence) { build(:ci_reports_security_occurrence, severity: nil) }
before do
subject.add_occurrence(occurrence)
end
it { expect(subject.unsafe_severity?).to be(false) }
it { expect(subject.safe?).to be(true) }
end
context "when the sast report has a vulnerability with a blank severity" do
let(:occurrence) { build(:ci_reports_security_occurrence, severity: '') }
before do
subject.add_occurrence(occurrence)
end
it { expect(subject.unsafe_severity?).to be(false) }
it { expect(subject.safe?).to be(true) }
end
context "when the sast report has zero vulnerabilities" do
it { expect(subject.unsafe_severity?).to be(false) }
it { expect(subject.safe?).to be(true) }
end
end
end
......@@ -35,4 +35,30 @@ describe Gitlab::Ci::Reports::Security::Reports do
end
end
end
describe "#violates_default_policy?" do
subject { described_class.new(commit_sha) }
let(:commit_sha) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
let(:low_severity) { build(:ci_reports_security_occurrence, severity: 'low') }
let(:high_severity) { build(:ci_reports_security_occurrence, severity: 'high') }
context "when a report has a high severity vulnerability" do
before do
subject.get_report('sast').add_occurrence(high_severity)
subject.get_report('dependency_scanning').add_occurrence(low_severity)
end
it { expect(subject.violates_default_policy?).to be(true) }
end
context "when none of the reports have a high severity vulnerability" do
before do
subject.get_report('sast').add_occurrence(low_severity)
subject.get_report('dependency_scanning').add_occurrence(low_severity)
end
it { expect(subject.violates_default_policy?).to be(false) }
end
end
end
......@@ -131,13 +131,14 @@ describe Security::SyncReportsToApprovalRulesService, '#execute' do
end
context 'without reports' do
let(:pipeline) { create(:ci_pipeline, :running, project: project, merge_requests_as_head_pipeline: [merge_request]) }
it "won't change approvals_required count" do
expect { subject }
.not_to change { report_approver_rule.reload.approvals_required }
end
context "license compliance policy" do
let(:pipeline) { create(:ee_ci_pipeline, :running, project: project, merge_requests_as_head_pipeline: [merge_request]) }
let!(:software_license_policy) { create(:software_license_policy, :blacklist, project: project, software_license: blacklisted_license) }
let!(:license_compliance_rule) { create(:report_approver_rule, :license_management, merge_request: merge_request, approvals_required: 1) }
let!(:blacklisted_license) { create(:software_license) }
......
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