Skip to content

Commit 08b7c60

Browse files
authored
fix: json validation allow arbitrary $schema value (#613)
fixes #612 --------- Signed-off-by: Jan Kowalleck <[email protected]>
1 parent 0d00496 commit 08b7c60

11 files changed

+61
-47
lines changed

cyclonedx/schema/_res/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@ changes:
3030
1. `https?://cyclonedx.org/schema/spdx` was replaced with `spdx.SNAPSHOT.xsd`
3131
2. `spdx.schema.json` was replaced with `spdx.SNAPSHOT.schema.json`
3232
3. `jsf-0.82.schema.json` was replaced with `jsf-0.82.SNAPSHOT.schema.json`
33-
4. `properties.$schema.enum` was fixed to match `$id`
33+
4. `properties.$schema.enum` was removed
3434
5. `required.version` removed, as it is actually optional with default value

cyclonedx/schema/_res/bom-1.2-strict.SNAPSHOT.schema.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
"additionalProperties": false,
1212
"properties": {
1313
"$schema": {
14-
"type": "string",
15-
"enum": [
16-
"http://cyclonedx.org/schema/bom-1.2b.schema.json"
17-
]
14+
"type": "string"
1815
},
1916
"bomFormat": {
2017
"$id": "#/properties/bomFormat",

cyclonedx/schema/_res/bom-1.3-strict.SNAPSHOT.schema.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
"additionalProperties": false,
1212
"properties": {
1313
"$schema": {
14-
"type": "string",
15-
"enum": [
16-
"http://cyclonedx.org/schema/bom-1.3a.schema.json"
17-
]
14+
"type": "string"
1815
},
1916
"bomFormat": {
2017
"$id": "#/properties/bomFormat",

cyclonedx/schema/_res/bom-1.4.SNAPSHOT.schema.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
"additionalProperties": false,
1212
"properties": {
1313
"$schema": {
14-
"type": "string",
15-
"enum": [
16-
"http://cyclonedx.org/schema/bom-1.4.schema.json"
17-
]
14+
"type": "string"
1815
},
1916
"bomFormat": {
2017
"type": "string",

cyclonedx/schema/_res/bom-1.5.SNAPSHOT.schema.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
"additionalProperties": false,
1212
"properties": {
1313
"$schema": {
14-
"type": "string",
15-
"enum": [
16-
"http://cyclonedx.org/schema/bom-1.5.schema.json"
17-
]
14+
"type": "string"
1815
},
1916
"bomFormat": {
2017
"type": "string",

tests/_data/own/json/1.2/bom_with_mixed_licenses.json

Lines changed: 7 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/_data/own/json/1.3/bom_with_mixed_licenses.json

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/test_deserialize_json.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ def test(ls: LicenseRepository) -> None:
6767
with open(json_file) as f:
6868
json = json_loads(f.read())
6969
bom: Bom = Bom.from_json(json)
70-
test(bom.metadata.licenses)
70+
if sv is not SchemaVersion.V1_2:
71+
test(bom.metadata.licenses)
7172
test(bom.metadata.component.licenses)
7273
test(list(bom.components)[0].licenses)
7374
test(list(bom.services)[0].licenses)

tests/test_validation_json.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# Copyright (c) OWASP Foundation. All Rights Reserved.
1717

1818
from glob import iglob
19+
from itertools import chain
1920
from os.path import join
2021
from typing import Generator
2122
from unittest import TestCase
@@ -25,18 +26,25 @@
2526
from cyclonedx.exception import MissingOptionalDependencyException
2627
from cyclonedx.schema import OutputFormat, SchemaVersion
2728
from cyclonedx.validation.json import JsonStrictValidator, JsonValidator
28-
from tests import SCHEMA_TESTDATA_DIRECTORY, DpTuple
29+
from tests import OWN_DATA_DIRECTORY, SCHEMA_TESTDATA_DIRECTORY, DpTuple
2930

3031
UNSUPPORTED_SCHEMA_VERSIONS = {SchemaVersion.V1_0, SchemaVersion.V1_1, }
3132

3233

33-
def _dp(prefix: str) -> Generator:
34+
def _dp_sv_tf(prefix: str) -> Generator:
3435
return (
3536
DpTuple((sv, tf)) for sv in SchemaVersion if sv not in UNSUPPORTED_SCHEMA_VERSIONS
3637
for tf in iglob(join(SCHEMA_TESTDATA_DIRECTORY, sv.to_version(), f'{prefix}-*.json'))
3738
)
3839

3940

41+
def _dp_sv_own() -> Generator:
42+
return (
43+
DpTuple((sv, tf)) for sv in SchemaVersion if sv not in UNSUPPORTED_SCHEMA_VERSIONS
44+
for tf in iglob(join(OWN_DATA_DIRECTORY, 'json', sv.to_version(), '*.json'))
45+
)
46+
47+
4048
@ddt
4149
class TestJsonValidator(TestCase):
4250

@@ -51,7 +59,10 @@ def test_throws_with_unsupported_schema_version(self, schema_version: SchemaVers
5159
with self.assertRaisesRegex(ValueError, 'Unsupported schema_version'):
5260
JsonValidator(schema_version)
5361

54-
@idata(_dp('valid'))
62+
@idata(chain(
63+
_dp_sv_tf('valid'),
64+
_dp_sv_own()
65+
))
5566
@unpack
5667
def test_validate_no_none(self, schema_version: SchemaVersion, test_data_file: str) -> None:
5768
validator = JsonValidator(schema_version)
@@ -63,7 +74,7 @@ def test_validate_no_none(self, schema_version: SchemaVersion, test_data_file: s
6374
self.skipTest('MissingOptionalDependencyException')
6475
self.assertIsNone(validation_error)
6576

66-
@idata(_dp('invalid'))
77+
@idata(_dp_sv_tf('invalid'))
6778
@unpack
6879
def test_validate_expected_error(self, schema_version: SchemaVersion, test_data_file: str) -> None:
6980
validator = JsonValidator(schema_version)
@@ -85,7 +96,10 @@ def test_throws_with_unsupported_schema_version(self, schema_version: SchemaVers
8596
with self.assertRaisesRegex(ValueError, 'Unsupported schema_version'):
8697
JsonStrictValidator(schema_version)
8798

88-
@idata(_dp('valid'))
99+
@idata(chain(
100+
_dp_sv_tf('valid'),
101+
_dp_sv_own()
102+
))
89103
@unpack
90104
def test_validate_no_none(self, schema_version: SchemaVersion, test_data_file: str) -> None:
91105
validator = JsonStrictValidator(schema_version)
@@ -97,7 +111,7 @@ def test_validate_no_none(self, schema_version: SchemaVersion, test_data_file: s
97111
self.skipTest('MissingOptionalDependencyException')
98112
self.assertIsNone(validation_error)
99113

100-
@idata(_dp('invalid'))
114+
@idata(_dp_sv_tf('invalid'))
101115
@unpack
102116
def test_validate_expected_error(self, schema_version: SchemaVersion, test_data_file: str) -> None:
103117
validator = JsonStrictValidator(schema_version)

tests/test_validation_xml.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# Copyright (c) OWASP Foundation. All Rights Reserved.
1717

1818
from glob import iglob
19+
from itertools import chain
1920
from os.path import join
2021
from typing import Generator
2122
from unittest import TestCase
@@ -25,18 +26,25 @@
2526
from cyclonedx.exception import MissingOptionalDependencyException
2627
from cyclonedx.schema import OutputFormat, SchemaVersion
2728
from cyclonedx.validation.xml import XmlValidator
28-
from tests import SCHEMA_TESTDATA_DIRECTORY, DpTuple
29+
from tests import OWN_DATA_DIRECTORY, SCHEMA_TESTDATA_DIRECTORY, DpTuple
2930

3031
UNSUPPORTED_SCHEMA_VERSIONS = set()
3132

3233

33-
def _dp(prefix: str) -> Generator:
34+
def _dp_sv_tf(prefix: str) -> Generator:
3435
return (
3536
DpTuple((sv, tf)) for sv in SchemaVersion if sv not in UNSUPPORTED_SCHEMA_VERSIONS
3637
for tf in iglob(join(SCHEMA_TESTDATA_DIRECTORY, sv.to_version(), f'{prefix}-*.xml'))
3738
)
3839

3940

41+
def _dp_sv_own() -> Generator:
42+
return (
43+
DpTuple((sv, tf)) for sv in SchemaVersion if sv not in UNSUPPORTED_SCHEMA_VERSIONS
44+
for tf in iglob(join(OWN_DATA_DIRECTORY, 'xml', sv.to_version(), '*.xml'))
45+
)
46+
47+
4048
@ddt
4149
class TestXmlValidator(TestCase):
4250

@@ -51,7 +59,10 @@ def test_throws_with_unsupported_schema_version(self, schema_version: SchemaVers
5159
with self.assertRaisesRegex(ValueError, f'unsupported schema_version: {schema_version}'):
5260
XmlValidator(schema_version)
5361

54-
@idata(_dp('valid'))
62+
@idata(chain(
63+
_dp_sv_tf('valid'),
64+
_dp_sv_own()
65+
))
5566
@unpack
5667
def test_validate_no_none(self, schema_version: SchemaVersion, test_data_file: str) -> None:
5768
validator = XmlValidator(schema_version)
@@ -63,7 +74,7 @@ def test_validate_no_none(self, schema_version: SchemaVersion, test_data_file: s
6374
self.skipTest('MissingOptionalDependencyException')
6475
self.assertIsNone(validation_error)
6576

66-
@idata(_dp('invalid'))
77+
@idata(_dp_sv_tf('invalid'))
6778
@unpack
6879
def test_validate_expected_error(self, schema_version: SchemaVersion, test_data_file: str) -> None:
6980
validator = XmlValidator(schema_version)

0 commit comments

Comments
 (0)