scripts/cve2osv.py (63 lines of code) (raw):
#!/usr/bin/env python3
# Script to convert CVEs as published for Apache projects
# from CVE JSON 5.0 format to OSV format.
import json
import sys
# TODO get from arg
cve = json.load(open(sys.argv[1]))
def mavenPackage(groupId, artifactId):
return {
'ecosystem': 'Maven',
'name': f"{groupId}:{artifactId}",
'purl': f"pkg:maven/{groupId}/{artifactId}"
}
def package(product):
if product == 'Apache Commons IO':
return mavenPackage('org.apache.commons', 'commons-io')
else:
# https://github.com/ossf/osv-schema/issues/94
return None
def range(versions):
if versions['status'] != 'affected':
raise "TODO support for explicitly 'unaffected' ranges"
if 'lessThan' in versions:
events = [{
'introduced': versions['version']
},{
'fixed': versions['lessThan']
}]
else:
events = [{
'introduced': versions['version']
},{
'last_affected': versions['version']
}]
return {
'type': 'SEMVER',
'events': events
}
def convert_affected(affected):
result = {}
p = package(affected['product'])
if p:
result['package'] = p
result['ranges'] = list(map(range, affected['versions']))
# TODO severity
return result
def reference(reference):
url = reference['url']
if 'jira' in url:
t = 'REPORT'
elif 'x_refsource_CONFIRM' in reference['tags']:
t = 'ADVISORY'
else:
t = 'WEB'
return {
'type': t,
'url': reference['url']
}
cna = cve['containers']['cna']
osv = {
'schema_version': '1.6.1',
'id': cve['cveMetadata']['cveId'],
'summary': cna['title'],
'details': cna['descriptions'][0]['value'],
# TODO 'severity'
'affected': list(map(convert_affected, cna['affected'])),
'references': list(map(reference, cna['references']))
# TODO 'credits'
}
with open(sys.argv[2], 'w', encoding='utf-8') as f:
json.dump(osv, f, ensure_ascii=False)