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..a474d8122 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,17 +91,46 @@ 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():
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"- Affected release URL: [{release}]({release_urls[release]})\n\n")
+ latest_release = latest_release_info[pkg]
+
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']:
+ 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: