From df9a0460ef41cb5ecb4d327721b560f71faa4ab0 Mon Sep 17 00:00:00 2001 From: Kepler Boyce Date: Thu, 6 Jun 2024 13:58:36 -0700 Subject: [PATCH 1/2] Provide release URLs in vulnerabilities docs page --- docs/Vulnerabilities.md | 29 +------------------ tools/create_vulnerability_doc.py | 48 ++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/docs/Vulnerabilities.md b/docs/Vulnerabilities.md index e45453a79..f374aa5c2 100644 --- a/docs/Vulnerabilities.md +++ b/docs/Vulnerabilities.md @@ -1,30 +1,3 @@ # Package Vulnerabilities -## caddy - -
-caddy (Build 2215) - (STABLE) -- 1 medium vulnerability - -- **(MEDIUM severity) CVE-2022-29718**: Caddy v2.4 was discovered to contain an open redirect vulnerability. A remote unauthenticated attacker may exploit this vulnerability to redirect users to arbitrary web URLs by tricking the victim users to click on crafted links. - -
- -## logrotate - -
-logrotate (Build 2172) - (STABLE) -- 1 medium vulnerability - -- **(MEDIUM severity) CVE-2022-1348**: A vulnerability was found in logrotate in how the state file is created. The state file is used to prevent parallel executions of multiple instances of logrotate by acquiring and releasing a file lock. When the state file does not exist, it is created with world-readable permission, allowing an unprivileged user to lock the state file, stopping any rotation. This flaw affects logrotate versions before 3.20.0. - -
- -## grafana - -
-grafana (Build 2266) - (STABLE) -- 2 vulnerabilities (1 critical, 1 high) - -- **(CRITICAL severity) CVE-2018-15727**: Grafana 2.x, 3.x, and 4.x before 4.6.4 and 5.x before 5.2.3 allows authentication bypass because an attacker can generate a valid "remember me" cookie knowing only a username of an LDAP or OAuth user. -- **(HIGH severity) CVE-2020-13379**: The avatar feature in Grafana 3.0.1 through 7.0.1 has an SSRF Incorrect Access Control issue. This vulnerability allows any unauthenticated user/client to make Grafana send HTTP requests to any URL and return its result to the user/client. This can be used to gain information about the network that Grafana is running on. Furthermore, passing invalid URL objects could be used for DOS'ing Grafana via SegFault. - -
- +There are currently no known vulnerabilities in any packages. \ No newline at end of file diff --git a/tools/create_vulnerability_doc.py b/tools/create_vulnerability_doc.py index c535167ab..68845a641 100644 --- a/tools/create_vulnerability_doc.py +++ b/tools/create_vulnerability_doc.py @@ -58,17 +58,28 @@ def format_quantities(cves): s += ")" return s +def parse_release_url(url): + release = url.split('/')[-2] + prefix = url.split('/download/')[0] + return f"{prefix}/tag/{release}" + if __name__ == '__main__': parser = argparse.ArgumentParser(description='Generate markdown file for vulnerabilities in zopen packages') parser.add_argument('--output-file', '-o', dest='output_file', required=True, help='Output markdown file path') args = parser.parse_args() - url = 'https://raw.githubusercontent.com/ZOSOpenTools/meta/main/docs/api/zopen_vulnerability.json' - response = requests.get(url) - data = response.json() + vulns_url = 'https://raw.githubusercontent.com/ZOSOpenTools/meta/main/docs/api/zopen_vulnerability.json' + vulns_res = requests.get(vulns_url) + vulns_json = vulns_res.json() + releases_url = 'https://raw.githubusercontent.com/ZOSOpenTools/meta/main/docs/api/zopen_releases.json' + releases_res = requests.get(releases_url) + releases_json = releases_res.json() + latest_releases_url = 'https://raw.githubusercontent.com/ZOSOpenTools/meta/main/docs/api/zopen_releases_latest.json' + latest_releases_res = requests.get(latest_releases_url) + latest_releases_json = latest_releases_res.json() package_vulns = {} - for pkg, cves in data.items(): + for pkg, cves in vulns_json.items(): # TODO: Remove this check once gitdummy is removed from zopen_vulnerability.json if pkg == 'gitdummy': continue @@ -80,6 +91,22 @@ def format_quantities(cves): name = cve['name'] package_vulns[pkg][name].append(cve['CVEs']) + release_urls = {} + latest_release_info = {} + for vuln_pkg, vuln_releases in package_vulns.items(): + # Get release urls for all of the releases with vulnerabilities for this package + for release in releases_json['release_data'].get(vuln_pkg, []): + if release['name'] in vuln_releases: + release_urls[release['name']] = parse_release_url(release['assets'][0]['url']) + # Get information about latest release (name, url, CVE ids) + latest_release = latest_releases_json['release_data'].get(vuln_pkg)[0] + info = { + "name": latest_release['name'], + "url": parse_release_url(latest_release['assets'][0]['url']), + "cve_ids": set(cve['id'] for cve in vuln_releases.get(latest_release['name'], [])), + } + latest_release_info[vuln_pkg] = info + with open(args.output_file, 'w') as file: file.write("# Package Vulnerabilities\n\n") for pkg, releases in package_vulns.items(): @@ -88,9 +115,22 @@ def format_quantities(cves): for release, cves in releases.items(): # Dropdown for each release -- expand to show vulnerabilities file.write(f"
\n{release} -- {format_quantities(cves)}\n\n") + + # Url of release page and url of latest release (if this is not the latest release) + file.write(f"- Release URL: [{release}]({release_urls[release]})\n\n") + latest_release = latest_release_info[pkg] + if release == latest_release['name']: + file.write("- This is the latest release.\n\n") + else: + file.write(f"- Latest release: [{latest_release['name']}]({latest_release['url']})\n\n") + for cve in cves: # Bullet point for each vulnerability in this release file.write(f"- **({cve['severity']} severity) {cve['id']}**: {cve['details']}\n") + # Show if this vulnerability is resolved in the latest release + if (release != latest_release_info[pkg]['name'] and + cve['id'] not in latest_release_info[pkg]['cve_ids']): + file.write(" - **This vulnerability is resolved in the latest release.**\n") file.write("\n
\n\n") if len(package_vulns) == 0: From f6b6c75460791c625bf76a3b5f6908c535bf857f Mon Sep 17 00:00:00 2001 From: Kepler Boyce Date: Fri, 7 Jun 2024 11:17:06 -0700 Subject: [PATCH 2/2] Adjustments to format, list releases in order from newest to oldest --- tools/create_vulnerability_doc.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/create_vulnerability_doc.py b/tools/create_vulnerability_doc.py index 68845a641..a474d8122 100644 --- a/tools/create_vulnerability_doc.py +++ b/tools/create_vulnerability_doc.py @@ -112,25 +112,25 @@ def parse_release_url(url): for pkg, releases in package_vulns.items(): file.write(f"## {pkg}\n\n") # List of releases for this package - for release, cves in releases.items(): + for release, cves in reversed(releases.items()): # Dropdown for each release -- expand to show vulnerabilities file.write(f"
\n{release} -- {format_quantities(cves)}\n\n") # Url of release page and url of latest release (if this is not the latest release) - file.write(f"- Release URL: [{release}]({release_urls[release]})\n\n") + file.write(f"- Affected release URL: [{release}]({release_urls[release]})\n\n") latest_release = latest_release_info[pkg] - if release == latest_release['name']: - file.write("- This is the latest release.\n\n") - else: - file.write(f"- Latest release: [{latest_release['name']}]({latest_release['url']})\n\n") for cve in cves: # Bullet point for each vulnerability in this release file.write(f"- **({cve['severity']} severity) {cve['id']}**: {cve['details']}\n") # Show if this vulnerability is resolved in the latest release - if (release != latest_release_info[pkg]['name'] and - cve['id'] not in latest_release_info[pkg]['cve_ids']): - file.write(" - **This vulnerability is resolved in the latest release.**\n") + if release == latest_release_info[pkg]['name']: + file.write(" - **Currently no fix -- this is the latest release**.") + else: + if cve['id'] not in latest_release_info[pkg]['cve_ids']: + file.write(f" - **This vulnerability is resolved in the [latest release]({latest_release['url']})**.\n") + else: + file.write(f" - **Currently no fix -- still affects the [latest release]({latest_release['url']})**.\n") file.write("\n
\n\n") if len(package_vulns) == 0: