Skip to content

Commit 4f578ad

Browse files
Improve JSON validation (#317)
Improve JSON validation, in particular if you don't specify the specification version. This helps to address #221. On the given example, it will result in: ``` cyclonedx.exe validate --input-file badType_log4j_2.17.2_cyclonedx_1.3_sbom.json Validation failed: Value is "boolean" but should be "string" #/properties/dependencies/items/$ref/properties/ref/type On instance: #/dependencies/0/ref: True Unable to validate against any JSON schemas. BOM is not valid. ``` Signed-off-by: andreas hilti <[email protected]> Co-authored-by: Michael Tsfoni <[email protected]>
1 parent 91cf6c6 commit 4f578ad

File tree

3 files changed

+189
-15
lines changed

3 files changed

+189
-15
lines changed

src/cyclonedx/Commands/ValidateCommand.cs

+8-15
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using System.CommandLine.Invocation;
2121
using System.Diagnostics.Contracts;
2222
using System.IO;
23+
using System.Linq;
2324
using System.Text;
2425
using System.Threading.Tasks;
2526
using CycloneDX.Models;
@@ -106,25 +107,17 @@ public static async Task<int> Validate(ValidateCommandOptions options)
106107
}
107108
else if (options.InputFormat == ValidationBomFormat.json)
108109
{
109-
validationResult = Json.Validator.Validate(inputBom, SpecificationVersion.v1_5);
110-
if (!validationResult.Valid)
111-
{
112-
validationResult = Json.Validator.Validate(inputBom, SpecificationVersion.v1_4);
113-
}
114-
if (!validationResult.Valid)
115-
{
116-
validationResult = Json.Validator.Validate(inputBom, SpecificationVersion.v1_3);
117-
}
118-
if (!validationResult.Valid)
119-
{
120-
validationResult = Json.Validator.Validate(inputBom, SpecificationVersion.v1_2);
121-
}
110+
validationResult = Json.Validator.Validate(inputBom);
111+
122112
if (!validationResult.Valid)
123113
{
124-
validationResult.Messages = new List<string>
114+
if (validationResult.Messages == null)
125115
{
116+
validationResult.Messages = new List<string>();
117+
}
118+
validationResult.Messages = validationResult.Messages.Append(
126119
"Unable to validate against any JSON schemas."
127-
};
120+
);
128121
}
129122
}
130123

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
{
2+
"bomFormat": "CycloneDX",
3+
"specVersion": "1.4",
4+
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
5+
"version": 1,
6+
"invalidAttribute": 2,
7+
"metadata": {
8+
"timestamp": "2020-04-13T20:20:39+00:00",
9+
"tools": [
10+
{
11+
"vendor": "Awesome Vendor",
12+
"name": "Awesome Tool",
13+
"version": "9.1.2",
14+
"hashes": [
15+
{
16+
"alg": "SHA-1",
17+
"content": "25ed8e31b995bb927966616df2a42b979a2717f0"
18+
},
19+
{
20+
"alg": "SHA-256",
21+
"content": "a74f733635a19aefb1f73e5947cef59cd7440c6952ef0f03d09d974274cbd6df"
22+
}
23+
]
24+
}
25+
],
26+
"authors": [
27+
{
28+
"name": "Samantha Wright",
29+
"email": "[email protected]",
30+
"phone": "800-555-1212"
31+
}
32+
],
33+
"component": {
34+
"type": "application",
35+
"author": "Acme Super Heros",
36+
"name": "Acme Application",
37+
"version": "9.1.1",
38+
"swid": {
39+
"tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1",
40+
"name": "Acme Application",
41+
"version": "9.1.1",
42+
"text": {
43+
"contentType": "text/xml",
44+
"encoding": "base64",
45+
"content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg=="
46+
}
47+
}
48+
},
49+
"manufacture": {
50+
"name": "Acme, Inc.",
51+
"url": [
52+
"https://example.com"
53+
],
54+
"contact": [
55+
{
56+
"name": "Acme Professional Services",
57+
"email": "[email protected]"
58+
}
59+
]
60+
},
61+
"supplier": {
62+
"name": "Acme, Inc.",
63+
"url": [
64+
"https://example.com"
65+
],
66+
"contact": [
67+
{
68+
"name": "Acme Distribution",
69+
"email": "[email protected]"
70+
}
71+
]
72+
}
73+
},
74+
"components": [
75+
{
76+
"bom-ref": "pkg:npm/acme/[email protected]",
77+
"type": "library",
78+
"publisher": "Acme Inc",
79+
"group": "com.acme",
80+
"name": "tomcat-catalina",
81+
"version": "9.0.14",
82+
"hashes": [
83+
{
84+
"alg": "MD5",
85+
"content": "3942447fac867ae5cdb3229b658f4d48"
86+
},
87+
{
88+
"alg": "SHA-1",
89+
"content": "e6b1000b94e835ffd37f4c6dcbdad43f4b48a02a"
90+
},
91+
{
92+
"alg": "SHA-256",
93+
"content": "f498a8ff2dd007e29c2074f5e4b01a9a01775c3ff3aeaf6906ea503bc5791b7b"
94+
},
95+
{
96+
"alg": "SHA-512",
97+
"content": "e8f33e424f3f4ed6db76a482fde1a5298970e442c531729119e37991884bdffab4f9426b7ee11fccd074eeda0634d71697d6f88a460dce0ac8d627a29f7d1282"
98+
}
99+
],
100+
"licenses": [
101+
{
102+
"license": {
103+
"id": "Apache-2.0",
104+
"text": {
105+
"contentType": "text/plain",
106+
"encoding": "base64",
107+
"content": "License text here"
108+
},
109+
"url": "https://www.apache.org/licenses/LICENSE-2.0.txt"
110+
}
111+
}
112+
],
113+
"purl": "pkg:npm/acme/[email protected]",
114+
"pedigree": {
115+
"ancestors": [
116+
{
117+
"type": "library",
118+
"publisher": "Acme Inc",
119+
"group": "com.acme",
120+
"name": "tomcat-catalina",
121+
"version": "9.0.14"
122+
},
123+
{
124+
"type": "library",
125+
"publisher": "Acme Inc",
126+
"group": "com.acme",
127+
"name": "tomcat-catalina",
128+
"version": "9.0.14"
129+
}
130+
],
131+
"commits": [
132+
{
133+
"uid": "123",
134+
"url": "",
135+
"author": {
136+
"timestamp": "2018-11-13T20:20:39+00:00",
137+
"name": "",
138+
"email": "[email protected]"
139+
}
140+
}
141+
]
142+
}
143+
},
144+
{
145+
"type": "library",
146+
"supplier": {
147+
"name": "Example, Inc.",
148+
"url": [
149+
"https://example.com",
150+
"https://example.net"
151+
],
152+
"contact": [
153+
{
154+
"name": "Example Support AMER Distribution",
155+
"email": "[email protected]",
156+
"phone": "800-555-1212"
157+
},
158+
{
159+
"name": "Example Support APAC",
160+
"email": "[email protected]"
161+
}
162+
]
163+
},
164+
"author": "Example Super Heros",
165+
"group": "org.example",
166+
"name": "mylibrary",
167+
"version": "1.0.0"
168+
}
169+
],
170+
"dependencies": [
171+
{
172+
"ref": "pkg:npm/acme/[email protected]",
173+
"dependsOn": [
174+
"pkg:npm/acme/[email protected]"
175+
]
176+
}
177+
]
178+
}

tests/cyclonedx.tests/ValidateTests.cs

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ public class ValidateTests
5858

5959
[InlineData("bom-1.4.json", ValidationBomFormat.autodetect, null, true)]
6060
[InlineData("bom-1.4.json", ValidationBomFormat.json, SpecificationVersion.v1_4, true)]
61+
62+
[InlineData("bom-1.4-invalid.json", ValidationBomFormat.autodetect, null, false)]
63+
[InlineData("bom-1.4-invalid.json", ValidationBomFormat.json, SpecificationVersion.v1_4, false)]
6164

6265
[InlineData("bom-1.5.json", ValidationBomFormat.autodetect, null, true)]
6366
[InlineData("bom-1.5.json", ValidationBomFormat.json, SpecificationVersion.v1_5, true)]

0 commit comments

Comments
 (0)