2020# VulnerableCode is a free software code scanning tool from nexB Inc. and others.
2121# Visit https://github.com/nexB/vulnerablecode/ for support and download.
2222
23+ import dataclasses
24+ import re
2325from typing import Set
26+ import xml .etree .ElementTree as ET
2427
2528from packageurl import PackageURL
2629import requests
27- import re
2830
2931from vulnerabilities .data_source import Advisory
3032from vulnerabilities .data_source import DataSource
3133from vulnerabilities .data_source import Reference
34+ from vulnerabilities .data_source import DataSourceConfiguration
3235
33- import xml .etree .ElementTree as ET
36+
37+ @dataclasses .dataclass
38+ class OpenSSLDataSourceConfiguration (DataSourceConfiguration ):
39+ etags : dict
3440
3541
3642class OpenSSLDataSource (DataSource ):
43+ CONFIG_CLASS = OpenSSLDataSourceConfiguration
44+
45+ url = "https://www.openssl.org/news/vulnerabilities.xml"
46+
3747 def updated_advisories (self ) -> Set [Advisory ]:
38- raw_data = self .fetch ()
39- advisories = self .to_advisories (raw_data )
40- return self .batch_advisories (advisories )
48+ # Etags are like hashes of web responses. We maintain
49+ # (url, etag) mappings in the DB. `create_etag` creates
50+ # (url, etag) pair. If a (url, etag) already exists then the code
51+ # skips processing the response further to avoid duplicate work
52+ if self .create_etag (self .url ):
53+ raw_data = self .fetch ()
54+ advisories = self .to_advisories (raw_data )
55+ return self .batch_advisories (advisories )
56+
57+ return []
58+
59+ def create_etag (self , url ):
60+ etag = requests .head (url ).headers .get ("ETag" )
61+ if not etag :
62+ # Kind of inaccurate to return True since etag is
63+ # not created
64+ return True
65+
66+ elif url in self .config .etags :
67+ if self .config .etags [url ] == etag :
68+ return False
69+
70+ self .config .etags [url ] = etag
71+ return True
4172
4273 def fetch (self ):
43- return requests .get ("https://www.openssl.org/news/vulnerabilities.xml" ).content
74+ return requests .get (self . url ).content
4475
4576 @staticmethod
4677 def to_advisories (xml_response : str ) -> Set [Advisory ]:
@@ -58,7 +89,11 @@ def to_advisories(xml_response: str) -> Set[Advisory]:
5889 for info in element :
5990
6091 if info .tag == "cve" :
61- cve_id = "CVE-" + info .attrib .get ("name" )
92+ if info .attrib .get ("name" ):
93+ cve_id = "CVE-" + info .attrib .get ("name" )
94+
95+ else :
96+ continue
6297
6398 if info .tag == "affects" :
6499 # Vulnerable package versions
0 commit comments