From 0a6f59d594e48d14c0b1ee84aeae05acc010d41b Mon Sep 17 00:00:00 2001 From: Postmodern Date: Wed, 5 Jul 2023 21:20:30 -0700 Subject: [PATCH 1/6] Attempt to automatically generate `unaffected_versions:`. * Generate `unaffected_versions` based on the inverse of the first `vulnerableVersionRange`, iff `vulnerableVersionRange` starts with `> ` or `>= `. --- lib/github_advisory_sync.rb | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/github_advisory_sync.rb b/lib/github_advisory_sync.rb index 04af518a98..59adb743db 100644 --- a/lib/github_advisory_sync.rb +++ b/lib/github_advisory_sync.rb @@ -337,6 +337,20 @@ def update(package) package.filename end + def unaffected_versions_for(package) + if (vulnerability = vulnerabilities.first) + vulnerable_version_range = vulnerabilities['vulnerableVersionRange'] + operator, version = vulnerable_version_range.split(' ',2) + + case operator + when '>' + ["<= #{version}"] + when '>=' + ["< #{version}"] + end + end + end + def first_patched_versions_for(package) first_patched_versions = [] @@ -371,10 +385,13 @@ def create(package) new_data = package.merge_data( "cvss_v3" => ("" unless cvss), - "cvss_v4" => "", - "unaffected_versions" => [""] + "cvss_v4" => "" ) + if (unaffected_versions = unaffected_versions_for(package)) + new_data['unaffected_versions'] = unaffected_versions + end + patched_versions = patched_versions_for(package) if !patched_versions.empty? From 8d03a0a4f91f75c51efe56d5b468c828817ce0f6 Mon Sep 17 00:00:00 2001 From: Postmodern Date: Thu, 6 Jul 2023 16:58:27 -0700 Subject: [PATCH 2/6] Ensure the first vulnerability is actually for the given package. --- lib/github_advisory_sync.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/github_advisory_sync.rb b/lib/github_advisory_sync.rb index 59adb743db..f7b381fc4c 100644 --- a/lib/github_advisory_sync.rb +++ b/lib/github_advisory_sync.rb @@ -337,8 +337,14 @@ def update(package) package.filename end + def first_vulnerability_for(package) + vulnerabilities.find do |v| + v['package']['name'] == package.name + end + end + def unaffected_versions_for(package) - if (vulnerability = vulnerabilities.first) + if (vulnerability = first_vulnerability_for(package)) vulnerable_version_range = vulnerabilities['vulnerableVersionRange'] operator, version = vulnerable_version_range.split(' ',2) From 2153ee03804c017910c99c602f967f03893d8d14 Mon Sep 17 00:00:00 2001 From: Postmodern Date: Thu, 6 Jul 2023 17:22:33 -0700 Subject: [PATCH 3/6] Fixed typo. --- lib/github_advisory_sync.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/github_advisory_sync.rb b/lib/github_advisory_sync.rb index f7b381fc4c..34a53d0e60 100644 --- a/lib/github_advisory_sync.rb +++ b/lib/github_advisory_sync.rb @@ -345,7 +345,7 @@ def first_vulnerability_for(package) def unaffected_versions_for(package) if (vulnerability = first_vulnerability_for(package)) - vulnerable_version_range = vulnerabilities['vulnerableVersionRange'] + vulnerable_version_range = vulnerability['vulnerableVersionRange'] operator, version = vulnerable_version_range.split(' ',2) case operator From 239353a04c533b6f11701ae25730e0ef28c84723 Mon Sep 17 00:00:00 2001 From: Postmodern Date: Thu, 6 Jul 2023 17:24:01 -0700 Subject: [PATCH 4/6] Support the edge-case where the first `vulnerableVersionRange` starts with `=`. --- lib/github_advisory_sync.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/github_advisory_sync.rb b/lib/github_advisory_sync.rb index 34a53d0e60..4347eca7bb 100644 --- a/lib/github_advisory_sync.rb +++ b/lib/github_advisory_sync.rb @@ -351,7 +351,7 @@ def unaffected_versions_for(package) case operator when '>' ["<= #{version}"] - when '>=' + when '>=', '=' ["< #{version}"] end end From ae07be898071c867da4653ce001bb0c47a8e6bfe Mon Sep 17 00:00:00 2001 From: Postmodern Date: Thu, 6 Jul 2023 17:29:22 -0700 Subject: [PATCH 5/6] Support parsing composite version ranges (ex: `>= 3.0.0, < 6.0.2`). --- lib/github_advisory_sync.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/github_advisory_sync.rb b/lib/github_advisory_sync.rb index 4347eca7bb..58c5812de3 100644 --- a/lib/github_advisory_sync.rb +++ b/lib/github_advisory_sync.rb @@ -346,7 +346,8 @@ def first_vulnerability_for(package) def unaffected_versions_for(package) if (vulnerability = first_vulnerability_for(package)) vulnerable_version_range = vulnerability['vulnerableVersionRange'] - operator, version = vulnerable_version_range.split(' ',2) + lower_version_range = vulnerable_version_range.split(', ',2).first + operator, version = lower_version_range.split(' ',2) case operator when '>' From 1df7c0cd7b364c350a770916e12ee0b7f4c70027 Mon Sep 17 00:00:00 2001 From: Postmodern Date: Sat, 8 Jul 2023 15:47:04 -0700 Subject: [PATCH 6/6] Added `vulnerable_version_ranges_for` which sorts the version ranges. --- lib/github_advisory_sync.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/github_advisory_sync.rb b/lib/github_advisory_sync.rb index 58c5812de3..6e02ec03b2 100644 --- a/lib/github_advisory_sync.rb +++ b/lib/github_advisory_sync.rb @@ -337,17 +337,22 @@ def update(package) package.filename end - def first_vulnerability_for(package) - vulnerabilities.find do |v| + def vulnerable_version_ranges_for(package) + vulnerabilities.select { |v| v['package']['name'] == package.name - end + }.map { |v| + v['vulnerableVersionRange'].split(', ',2).map do |version_range| + version_range.split(' ',2) + end + }.sort_by { |((lower_op,lower_version),(upper_op,upper_version))| + lower_version + } end def unaffected_versions_for(package) - if (vulnerability = first_vulnerability_for(package)) - vulnerable_version_range = vulnerability['vulnerableVersionRange'] - lower_version_range = vulnerable_version_range.split(', ',2).first - operator, version = lower_version_range.split(' ',2) + if (version_range = vulnerable_version_ranges_for(package).first) + lower_version_range = version_range[0] + operator, version = lower_version_range case operator when '>'