Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Pass/Fail Customization #777

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
62 changes: 62 additions & 0 deletions lib/salus/rules_evaluation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module Salus
class RulesEvaluation
RULE_TYPE_ID = "id".freeze
RULE_TYPE_SEVERITY = "severity".freeze
ID_FIELD_MAPPING = {
"GoOSV" => :ID,
"GradleOSV" => :ID,
"PythonOSV" => :ID,
"MavenOSV" => :ID,
"BundleAudit" => :cve
}.freeze

SEVERITY_FIELD_MAPPING = {
"GoOSV" => :Severity,
"GradleOSV" => :Severity,
"PythonOSV" => :Severity,
"MavenOSV" => :Severity
}.freeze

def self.evaluate_default(results)
return true if results.empty?

false
end

def self.evaluate_by_type(config, results, scanner)
case config["rule"]["type"]
when RULE_TYPE_ID
evaluate_by_id(config["rule"], results, scanner)
when RULE_TYPE_SEVERITY
evaluate_by_severit(config["rule"], results, scanner)
else
evaluate_default(results)
end
end

def self.evaluate_by_id(config, results, scanner)
matches = config["matches"]
keys = matches.map { |x| x["key"] }
ids = results.map { |x| x[ID_FIELD_MAPPING[scanner]] }

return true unless (keys & ids).length.positive? && ids.length.positive?

reutrn false
end

def self.evaluate_by_severity(config, results, _scanner)
matches = config["matches"]
keys = matches.map { |x| x["key"] }
ids = results.map { |x| x[SEVERITY_FIELD_MAPPING[scanner]] }
return true unless (keys & ids).length.positive? && ids.length.positive?

reutrn false
end

def self.evaluate_rules(config, results, scanner)
return evaluate_by_type(config, results, scanner) if config.key?('rule')

evaluate_default(results)
end
end
end
8 changes: 7 additions & 1 deletion lib/salus/scanners/bundle_audit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ module Salus::Scanners
class BundleAudit < Base
class UnvalidGemVulnError < StandardError; end

CLASS_NAME = self.class.name.split("::").last.freeze

def self.scanner_type
Salus::ScannerTypes::DEPENDENCY
end
Expand Down Expand Up @@ -75,7 +77,11 @@ def run
report_info(:ignored_cves, ignore)
report_info(:vulnerabilities, @vulns)

@vulns.empty? ? report_success : report_failure
if Salus::RulesEvaluation.evaluate_rules(@config, @vulns, CLASS_NAME)
report_success
else
report_failure
end
end

def run_scanner(scanner, ignore)
Expand Down
4 changes: 3 additions & 1 deletion lib/salus/scanners/osv/go_osv.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'salus/scanners/osv/base'
require 'salus/rules_evaluation'

module Salus::Scanners::OSV
class GoOSV < Base
Expand All @@ -9,6 +10,7 @@ class SemVersion < Gem::Version; end
DEFAULT_SEVERITY = "MODERATE".freeze
GITHUB_DATABASE_STRING = "Github Advisory Database".freeze
GO_OSV_ADVISORY_URL = "https://osv-vulnerabilities.storage.googleapis.com/Go/all.zip".freeze
CLASS_NAME = self.class.name.split("::").last.freeze

def should_run?
@repository.go_sum_present?
Expand Down Expand Up @@ -46,7 +48,7 @@ def run
# Match and Report scanner status
vulnerabilities_found = match_vulnerable_dependencies(dependencies)
results = group_vulnerable_dependencies(vulnerabilities_found)
return report_success if results.empty?
return report_success if Salus::RulesEvaluation.evaluate_rules(@config, results, CLASS_NAME)

report_failure
log(JSON.pretty_generate(results))
Expand Down
3 changes: 2 additions & 1 deletion lib/salus/scanners/osv/gradle_osv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SemVersion < Gem::Version; end
DEFAULT_SEVERITY = "MODERATE".freeze
GRADLE_OSV_ADVISORY_URL = "https://osv-vulnerabilities.storage.googleapis.com"\
"/Maven/all.zip".freeze
CLASS_NAME = self.class.name.split("::").last.freeze

def should_run?
@repository.build_gradle_present?
Expand Down Expand Up @@ -41,7 +42,7 @@ def run
# Match and Report scanner status
vulnerabilities_found = match_vulnerable_dependencies(dependencies)
results = group_vulnerable_dependencies(vulnerabilities_found)
return report_success if results.empty?
return report_success if Salus::RulesEvaluation.evaluate_rules(@config, results, CLASS_NAME)

report_failure
log(JSON.pretty_generate(results))
Expand Down
3 changes: 2 additions & 1 deletion lib/salus/scanners/osv/maven_osv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SemVersion < Gem::Version; end
GITHUB_DATABASE_STRING = "Github Advisory Database".freeze
MAVEN_OSV_ADVISORY_URL = "https://osv-vulnerabilities.storage.googleapis.com/"\
"Maven/all.zip".freeze
CLASS_NAME = self.class.name.split("::").last.freeze

def should_run?
@repository.pom_xml_present?
Expand Down Expand Up @@ -46,7 +47,7 @@ def run
# Match and Report scanner status
vulnerabilities_found = match_vulnerable_dependencies(parser.pom_xml_dependencies)
results = group_vulnerable_dependencies(vulnerabilities_found)
return report_success if results.empty?
return report_success if Salus::RulesEvaluation.evaluate_rules(@config, results, CLASS_NAME)

report_failure
log(JSON.pretty_generate(results))
Expand Down
3 changes: 2 additions & 1 deletion lib/salus/scanners/osv/python_osv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SemDependency < Gem::Dependency; end
GITHUB_DATABASE_STRING = "Github Advisory Database".freeze
PYTHON_OSV_ADVISORY_URL = "https://osv-vulnerabilities.storage.googleapis.com/"\
"PyPI/all.zip".freeze
CLASS_NAME = self.class.name.split("::").last.freeze

def should_run?
@repository.requirements_txt_present?
Expand Down Expand Up @@ -41,7 +42,7 @@ def run
# Match and Report scanner status
vulnerabilities_found = match_vulnerable_dependencies(dependencies)
results = group_vulnerable_dependencies(vulnerabilities_found)
return report_success if results.empty?
return report_success if Salus::RulesEvaluation.evaluate_rules(@config, results, CLASS_NAME)

report_failure
log(JSON.pretty_generate(results))
Expand Down
2 changes: 1 addition & 1 deletion spec/fixtures/processor/local_uri/expected_report.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@
"passed": true,
"running_time": 1.45,
"scanner_name": "Trufflehog",
"version": "3.19.0",
"version": "3.21.0",
"warn": {
}
}
Expand Down
2 changes: 1 addition & 1 deletion spec/fixtures/processor/remote_uri/expected_report.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@
"passed": true,
"running_time": 1.45,
"scanner_name": "Trufflehog",
"version": "3.19.0",
"version": "3.21.0",
"warn": {
}
}
Expand Down