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

Bundler Audit Parser - Support for GHSA-Only Findings #9649

Merged
merged 6 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions dojo/tools/bundler_audit/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,19 @@ def get_findings(self, filename, test):
for warning in warnings:
if not warning.startswith("Name"):
continue
advisory_cve = None
advisory_id = None
gem_report_fields = warning.split("\n")
for field in gem_report_fields:
if field.startswith("Name"):
gem_name = field.replace("Name: ", "")
elif field.startswith("Version"):
gem_version = field.replace("Version: ", "")
elif field.startswith("Advisory"):
advisory_cve = field.replace("Advisory: ", "")
advisory_id = field.replace("Advisory: ", "")
elif field.startswith("CVE"):
advisory_cve = field.replace("CVE: ", "")
advisory_id = field.replace("CVE: ", "")
elif advisory_id is None and field.startswith("GHSA"):
advisory_id = field.replace("GHSA: ", "")
elif field.startswith("Criticality"):
criticality = field.replace("Criticality: ", "")
if criticality.lower() == "unknown":
Expand All @@ -58,19 +60,19 @@ def get_findings(self, filename, test):
+ ": "
+ advisory_title
+ " ["
+ advisory_cve
+ advisory_id
+ "]"
)
findingdetail = (
"Gem **" + gem_name + "** has known security issues:\n"
)
findingdetail += "**Name**: " + gem_name + "\n"
findingdetail += "**Version**: " + gem_version + "\n"
findingdetail += "**Advisory**: " + advisory_cve + "\n"
findingdetail += "**Advisory**: " + advisory_id + "\n"
mitigation = advisory_solution
references = advisory_url
fingerprint = (
"bundler-audit" + gem_name + gem_version + advisory_cve + sev
"bundler-audit" + gem_name + gem_version + advisory_id + sev
)
dupe_key = hashlib.md5(fingerprint.encode("utf-8")).hexdigest()
if dupe_key in dupes:
Expand All @@ -90,9 +92,10 @@ def get_findings(self, filename, test):
dynamic_finding=False,
component_name=gem_name,
component_version=gem_version,
cve=advisory_id,
)
if advisory_cve:
find.unsaved_vulnerability_ids = [advisory_cve]
if advisory_id:
find.unsaved_vulnerability_ids = [advisory_id]

dupes[dupe_key] = find

Expand Down
119 changes: 118 additions & 1 deletion unittests/scans/bundler_audit/version_9.0.json
Original file line number Diff line number Diff line change
@@ -1 +1,118 @@
{"version":"0.9.0.1","created_at":"2021-09-16 19:25:23 +0200","results":[{"type":"unpatched_gem","gem":{"name":"rack","version":"1.6.13"},"advisory":{"path":"/home/damien/.local/share/ruby-advisory-db/gems/rack/CVE-2020-8161.yml","id":"CVE-2020-8161","url":"https://groups.google.com/forum/#!topic/ruby-security-ann/T4ZIsfRf2eA","title":"Directory traversal in Rack::Directory app bundled with Rack","date":"2020-05-12","description":"There was a possible directory traversal vulnerability in the Rack::Directory app\nthat is bundled with Rack.\n\nVersions Affected: rack < 2.2.0\nNot affected: Applications that do not use Rack::Directory.\nFixed Versions: 2.1.3, >= 2.2.0\n\nImpact\n------\n\nIf certain directories exist in a director that is managed by\n`Rack::Directory`, an attacker could, using this vulnerability, read the\ncontents of files on the server that were outside of the root specified in the\nRack::Directory initializer.\n\nWorkarounds\n-----------\n\nUntil such time as the patch is applied or their Rack version is upgraded,\nwe recommend that developers do not use Rack::Directory in their\napplications.\n","cvss_v2":null,"cvss_v3":null,"cve":"2020-8161","osvdb":null,"ghsa":"5f9h-9pjv-v6j7","unaffected_versions":[],"patched_versions":["~> 2.1.3",">= 2.2.0"],"criticality":null}},{"type":"unpatched_gem","gem":{"name":"rack","version":"1.6.13"},"advisory":{"path":"/home/damien/.local/share/ruby-advisory-db/gems/rack/CVE-2020-8184.yml","id":"CVE-2020-8184","url":"https://groups.google.com/g/rubyonrails-security/c/OWtmozPH9Ak","title":"Percent-encoded cookies can be used to overwrite existing prefixed cookie names","date":"2020-06-15","description":"It is possible to forge a secure or host-only cookie prefix in Rack using\nan arbitrary cookie write by using URL encoding (percent-encoding) on the\nname of the cookie. This could result in an application that is dependent on\nthis prefix to determine if a cookie is safe to process being manipulated\ninto processing an insecure or cross-origin request.\nThis vulnerability has been assigned the CVE identifier CVE-2020-8184.\n\nVersions Affected: rack < 2.2.3, rack < 2.1.4\nNot affected: Applications which do not rely on __Host- and __Secure- prefixes to determine if a cookie is safe to process\nFixed Versions: rack >= 2.2.3, rack >= 2.1.4\n\nImpact\n------\n\nAn attacker may be able to trick a vulnerable application into processing an\ninsecure (non-SSL) or cross-origin request if they can gain the ability to write\narbitrary cookies that are sent to the application.\n\nWorkarounds\n-----------\n\nIf your application is impacted but you cannot upgrade to the released versions or apply\nthe provided patch, this issue can be temporarily addressed by adding the following workaround:\n\n```\nmodule Rack\n module Utils\n module_function def parse_cookies_header(header)\n return {} unless header\n header.split(/[;] */n).each_with_object({}) do |cookie, cookies|\n next if cookie.empty?\n key, value = cookie.split('=', 2)\n cookies[key] = (unescape(value) rescue value) unless cookies.key?(key)\n end\n end\n end\nend\n```\n","cvss_v2":null,"cvss_v3":null,"cve":"2020-8184","osvdb":null,"ghsa":"j6w9-fv6q-3q52","unaffected_versions":[],"patched_versions":["~> 2.1.4",">= 2.2.3"],"criticality":null}},{"type":"unpatched_gem","gem":{"name":"sprockets","version":"2.2.3"},"advisory":{"path":"/home/damien/.local/share/ruby-advisory-db/gems/sprockets/CVE-2018-3760.yml","id":"CVE-2018-3760","url":"https://groups.google.com/forum/#!topic/ruby-security-ann/2S9Pwz2i16k","title":"Path Traversal in Sprockets","date":"2018-06-19","description":"Specially crafted requests can be used to access files that exist on\nthe filesystem that is outside an application's root directory, when the\nSprockets server is used in production.\n\nAll users running an affected release should either upgrade or use one of the work arounds immediately.\n\nWorkaround:\nIn Rails applications, work around this issue, set `config.assets.compile = false` and\n`config.public_file_server.enabled = true` in an initializer and precompile the assets.\n\n This work around will not be possible in all hosting environments and upgrading is advised.\n","cvss_v2":null,"cvss_v3":null,"cve":"2018-3760","osvdb":null,"ghsa":"pr3h-jjhj-573x","unaffected_versions":[],"patched_versions":[">= 2.12.5, < 3.0.0",">= 3.7.2, < 4.0.0",">= 4.0.0.beta8"],"criticality":null}}]}
{
"version":"0.9.0.1",
"created_at":"2021-09-16 19:25:23 +0200",
"results":[
{
"type":"unpatched_gem",
"gem":{
"name":"rack",
"version":"1.6.13"
},
"advisory":{
"path":"/home/damien/.local/share/ruby-advisory-db/gems/rack/CVE-2020-8161.yml",
"id":"CVE-2020-8161",
"url":"https://groups.google.com/forum/#!topic/ruby-security-ann/T4ZIsfRf2eA",
"title":"Directory traversal in Rack::Directory app bundled with Rack",
"date":"2020-05-12",
"description":"There was a possible directory traversal vulnerability in the Rack::Directory app\nthat is bundled with Rack.\n\nVersions Affected: rack < 2.2.0\nNot affected: Applications that do not use Rack::Directory.\nFixed Versions: 2.1.3, >= 2.2.0\n\nImpact\n------\n\nIf certain directories exist in a director that is managed by\n`Rack::Directory`, an attacker could, using this vulnerability, read the\ncontents of files on the server that were outside of the root specified in the\nRack::Directory initializer.\n\nWorkarounds\n-----------\n\nUntil such time as the patch is applied or their Rack version is upgraded,\nwe recommend that developers do not use Rack::Directory in their\napplications.\n",
"cvss_v2":null,
"cvss_v3":null,
"cve":"2020-8161",
"osvdb":null,
"ghsa":"5f9h-9pjv-v6j7",
"unaffected_versions":[

],
"patched_versions":[
"~> 2.1.3",
">= 2.2.0"
],
"criticality":null
}
},
{
"type":"unpatched_gem",
"gem":{
"name":"rack",
"version":"1.6.13"
},
"advisory":{
"path":"/home/damien/.local/share/ruby-advisory-db/gems/rack/CVE-2020-8184.yml",
"id":"CVE-2020-8184",
"url":"https://groups.google.com/g/rubyonrails-security/c/OWtmozPH9Ak",
"title":"Percent-encoded cookies can be used to overwrite existing prefixed cookie names",
"date":"2020-06-15",
"description":"It is possible to forge a secure or host-only cookie prefix in Rack using\nan arbitrary cookie write by using URL encoding (percent-encoding) on the\nname of the cookie. This could result in an application that is dependent on\nthis prefix to determine if a cookie is safe to process being manipulated\ninto processing an insecure or cross-origin request.\nThis vulnerability has been assigned the CVE identifier CVE-2020-8184.\n\nVersions Affected: rack < 2.2.3, rack < 2.1.4\nNot affected: Applications which do not rely on __Host- and __Secure- prefixes to determine if a cookie is safe to process\nFixed Versions: rack >= 2.2.3, rack >= 2.1.4\n\nImpact\n------\n\nAn attacker may be able to trick a vulnerable application into processing an\ninsecure (non-SSL) or cross-origin request if they can gain the ability to write\narbitrary cookies that are sent to the application.\n\nWorkarounds\n-----------\n\nIf your application is impacted but you cannot upgrade to the released versions or apply\nthe provided patch, this issue can be temporarily addressed by adding the following workaround:\n\n```\nmodule Rack\n module Utils\n module_function def parse_cookies_header(header)\n return {} unless header\n header.split(/[;] */n).each_with_object({}) do |cookie, cookies|\n next if cookie.empty?\n key, value = cookie.split('=', 2)\n cookies[key] = (unescape(value) rescue value) unless cookies.key?(key)\n end\n end\n end\nend\n```\n",
"cvss_v2":null,
"cvss_v3":null,
"cve":"2020-8184",
"osvdb":null,
"ghsa":"j6w9-fv6q-3q52",
"unaffected_versions":[

],
"patched_versions":[
"~> 2.1.4",
">= 2.2.3"
],
"criticality":null
}
},
{
"type":"unpatched_gem",
"gem":{
"name":"sprockets",
"version":"2.2.3"
},
"advisory":{
"path":"/home/damien/.local/share/ruby-advisory-db/gems/sprockets/CVE-2018-3760.yml",
"id":"CVE-2018-3760",
"url":"https://groups.google.com/forum/#!topic/ruby-security-ann/2S9Pwz2i16k",
"title":"Path Traversal in Sprockets",
"date":"2018-06-19",
"description":"Specially crafted requests can be used to access files that exist on\nthe filesystem that is outside an application's root directory, when the\nSprockets server is used in production.\n\nAll users running an affected release should either upgrade or use one of the work arounds immediately.\n\nWorkaround:\nIn Rails applications, work around this issue, set `config.assets.compile = false` and\n`config.public_file_server.enabled = true` in an initializer and precompile the assets.\n\n This work around will not be possible in all hosting environments and upgrading is advised.\n",
"cvss_v2":null,
"cvss_v3":null,
"cve":"2018-3760",
"osvdb":null,
"ghsa":"pr3h-jjhj-573x",
"unaffected_versions":[

],
"patched_versions":[
">= 2.12.5, < 3.0.0",
">= 3.7.2, < 4.0.0",
">= 4.0.0.beta8"
],
"criticality":null
}
},
{
"type":"unpatched_gem",
"gem":{
"name":"nokogiri",
"version":"1.15.2"
},
"advisory":{
"path":"/home/damien/.local/share/ruby-advisory-db/gems/nokogiri/GHSA-xc9x-jj77-9p9j.yml",
"id":"GHSA-xc9x-jj77-9p9j",
"url":"https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-xc9x-jj77-9p9j",
"title":"Improper Handling of Unexpected Data Type in Nokogiri",
"date":"2024-02-04",
"description":"Nokogiri updates packaged libxml2 to v2.12.5 to resolve CVE-2024-25062.\n",
"cvss_v2":null,
"cvss_v3":null,
"cve":null,
"osvdb":null,
"ghsa":"GHSA-xc9x-jj77-9p9j",
"unaffected_versions":[

],
"patched_versions":[
">= 1.16.2"
],
"criticality":null
}
}
]
}
8 changes: 8 additions & 0 deletions unittests/scans/bundler_audit/version_9.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,12 @@ URL: https://groups.google.com/forum/#!topic/ruby-security-ann/2S9Pwz2i16k
Title: Path Traversal in Sprockets
Solution: upgrade to >= 2.12.5, < 3.0.0, >= 3.7.2, < 4.0.0, >= 4.0.0.beta8

Name: nokogiri
Version: 1.15.2
GHSA: GHSA-xc9x-jj77-9p9j
Criticality: Unknown
URL: https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-xc9x-jj77-9p9j
Title: Improper Handling of Unexpected Data Type in Nokogiri
Solution: upgrade to '>= 1.16.2'

Vulnerabilities found!
14 changes: 13 additions & 1 deletion unittests/tools/test_bundler_audit_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ def test_get_findings_version9(self):
with open(path.join(path.dirname(__file__), "../scans/bundler_audit/version_9.0.txt")) as testfile:
parser = BundlerAuditParser()
findings = parser.get_findings(testfile, Test())
self.assertEqual(3, len(findings))
self.assertEqual(4, len(findings))
with self.subTest(i=0):
finding = findings[0]
self.assertEqual("Gem rack: Directory traversal in Rack::Directory app bundled with Rack [CVE-2020-8161]", finding.title)
self.assertEqual("Medium", finding.severity)
self.assertEqual(1, len(finding.unsaved_vulnerability_ids))
self.assertEqual("CVE-2020-8161", finding.unsaved_vulnerability_ids[0])
self.assertEqual("CVE-2020-8161", finding.cve)
self.assertEqual("rack", finding.component_name)
self.assertEqual("1.6.13", finding.component_version)
with self.subTest(i=1):
Expand All @@ -46,6 +47,7 @@ def test_get_findings_version9(self):
self.assertEqual("Medium", finding.severity)
self.assertEqual(1, len(finding.unsaved_vulnerability_ids))
self.assertEqual("CVE-2020-8184", finding.unsaved_vulnerability_ids[0])
self.assertEqual("CVE-2020-8184", finding.cve)
self.assertEqual("rack", finding.component_name)
self.assertEqual("1.6.13", finding.component_version)
with self.subTest(i=2):
Expand All @@ -54,5 +56,15 @@ def test_get_findings_version9(self):
self.assertEqual("Medium", finding.severity)
self.assertEqual(1, len(finding.unsaved_vulnerability_ids))
self.assertEqual("CVE-2018-3760", finding.unsaved_vulnerability_ids[0])
self.assertEqual("CVE-2018-3760", finding.cve)
self.assertEqual("sprockets", finding.component_name)
self.assertEqual("2.2.3", finding.component_version)
with self.subTest(i=3):
finding = findings[3]
self.assertEqual("Gem nokogiri: Improper Handling of Unexpected Data Type in Nokogiri [GHSA-xc9x-jj77-9p9j]", finding.title)
self.assertEqual("Medium", finding.severity)
self.assertEqual(1, len(finding.unsaved_vulnerability_ids))
self.assertEqual("GHSA-xc9x-jj77-9p9j", finding.unsaved_vulnerability_ids[0])
self.assertEqual("GHSA-xc9x-jj77-9p9j", finding.cve)
self.assertEqual("nokogiri", finding.component_name)
self.assertEqual("1.15.2", finding.component_version)
Loading