Skip to content

Commit

Permalink
Add kwarg to sort CVSS JSON dict before returning it (RedHatProductSe…
Browse files Browse the repository at this point in the history
…curity#32)

* Add kwarg to sort CVSS JSON before returning it

* Add tests for CVSS dict ordering

* Return OrderedDict to support older Python versions
  • Loading branch information
juspence authored Feb 22, 2022
1 parent 645ad58 commit 7d5030d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
10 changes: 8 additions & 2 deletions cvss/cvss2.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from decimal import Decimal as D, ROUND_HALF_UP

from .constants2 import METRICS_ABBREVIATIONS, METRICS_MANDATORY, METRICS_VALUES, \
METRICS_VALUE_NAMES
METRICS_VALUE_NAMES, OrderedDict
from .exceptions import CVSS2MalformedError, CVSS2MandatoryError, CVSS2RHMalformedError, \
CVSS2RHScoreDoesNotMatch

Expand Down Expand Up @@ -295,7 +295,7 @@ def __eq__(self, o):
def __hash__(self):
return hash(self.clean_vector())

def as_json(self):
def as_json(self, sort=False):
"""
Returns a dictionary formatted with attribute names and values defined by the official
CVSS JSON schema:
Expand All @@ -306,6 +306,10 @@ def as_json(self):
json.dumps(cvss2.as_json())
Or get sorted JSON in an OrderedDict with:
json.dumps(cvss2.as_json(sort=True))
Returns:
(dict): JSON schema-compatible CVSS representation
"""
Expand Down Expand Up @@ -340,5 +344,7 @@ def us(text):
data['temporalScore'] = float(self.temporal_score)
if self.environmental_score:
data['environmentalScore'] = float(self.environmental_score)
if sort:
data = OrderedDict(sorted(data.items()))

return data
14 changes: 11 additions & 3 deletions cvss/cvss3.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from decimal import Decimal as D, ROUND_CEILING

from .constants3 import METRICS_ABBREVIATIONS, METRICS_MANDATORY, METRICS_VALUES, \
METRICS_VALUE_NAMES
METRICS_VALUE_NAMES, OrderedDict
from .exceptions import CVSS3MalformedError, CVSS3MandatoryError, CVSS3RHMalformedError, \
CVSS3RHScoreDoesNotMatch

Expand Down Expand Up @@ -409,7 +409,7 @@ def __eq__(self, o):
def __hash__(self):
return hash(self.clean_vector())

def as_json(self):
def as_json(self, sort=False):
"""
Returns a dictionary formatted with attribute names and values defined by the official
CVSS JSON schema:
Expand All @@ -421,6 +421,10 @@ def as_json(self):
json.dumps(cvss.as_json())
Or get sorted JSON in an OrderedDict with:
json.dumps(cvss.as_json(sort=True))
Returns:
(dict): JSON schema-compatible CVSS representation
"""
Expand All @@ -433,7 +437,7 @@ def us(text):
return text.upper().replace('-', '_').replace(' ', '_')

base_severity, temporal_severity, environmental_everity = self.severities()
return {
data = {
# Meta
'version': '3.' + str(self.minor_version),
# Vector
Expand Down Expand Up @@ -470,3 +474,7 @@ def us(text):
'environmentalSeverity': us(temporal_severity),
'temporalSeverity': us(environmental_everity),
}

if sort:
data = OrderedDict(sorted(data.items()))
return data
11 changes: 11 additions & 0 deletions tests/test_cvss2.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,17 @@ def test_parse_from_text_multiple_vectors_same_cvss(self):
i = 'Title: {0}\nThis is an overview of {0} problem.\nLinks: {0}'.format(v)
self.assertEqual(parser.parse_cvss_from_text(i), e)

def test_json_ordering(self):
with open(path.join(WD, 'vectors_random2')) as f:
for line in f:
vector, _ = line.split(' - ')
cvss = CVSS2(vector).as_json(sort=True)
old_key = ''
for key in cvss:
if key < old_key:
self.fail('dict ordering was not preserved: key {} less than previous key {} for CVSS object {}'.format(key, old_key, cvss))
old_key = key

def test_json_schema_repr(self):
try:
import jsonschema
Expand Down
16 changes: 16 additions & 0 deletions tests/test_cvss3.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,22 @@ def test_parse_from_text_multiple_vectors_same_cvss(self):
i = 'Title: {0}\nThis is an overview of {0} problem.\nLinks: {0}'.format(v)
self.assertEqual(parser.parse_cvss_from_text(i), e)

def test_json_ordering(self):
vectors_to_schema = {
'vectors_random3': 'schemas/cvss-v3.0.json',
'vectors_random31': 'schemas/cvss-v3.1.json',
}
for vectors_file_path, schema_file_path in vectors_to_schema.items():
with open(path.join(WD, vectors_file_path)) as f:
for line in f:
vector, _ = line.split(' - ')
cvss = CVSS3(vector).as_json(sort=True)
old_key = ''
for key in cvss:
if key < old_key:
self.fail('dict ordering was not preserved: key {} less than previous key {} for CVSS object {}'.format(key, old_key, cvss))
old_key = key

def test_json_schema_repr(self):
try:
import jsonschema
Expand Down

0 comments on commit 7d5030d

Please sign in to comment.