From f84aa8255085c2ed805aa4e347d8d611ac1650f9 Mon Sep 17 00:00:00 2001 From: Maxime Robert Date: Thu, 30 May 2024 17:03:02 +0200 Subject: [PATCH] Enable JSON Schema strict validation Signed-off-by: Maxime Robert --- package-lock.json | 100 +++++++++++++++++++++++++++++++++++++++ package.json | 1 + types/validator.d.ts.map | 2 +- utils.test.js | 4 +- validator.js | 7 ++- 5 files changed, 109 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4af8e9a0..92529a445 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@npmcli/arborist": "7.5.2", "ajv": "^8.14.0", "ajv-formats": "^3.0.1", + "ajv-formats-draft2019": "^1.6.1", "cheerio": "^1.0.0-rc.12", "edn-data": "1.1.1", "find-up": "7.0.0", @@ -2374,6 +2375,20 @@ } } }, + "node_modules/ajv-formats-draft2019": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ajv-formats-draft2019/-/ajv-formats-draft2019-1.6.1.tgz", + "integrity": "sha512-JQPvavpkWDvIsBp2Z33UkYCtXCSpW4HD3tAZ+oL4iEFOk9obQZffx0yANwECt6vzr6ET+7HN5czRyqXbnq/u0Q==", + "dependencies": { + "punycode": "^2.1.1", + "schemes": "^1.4.0", + "smtp-address-parser": "^1.0.3", + "uri-js": "^4.4.1" + }, + "peerDependencies": { + "ajv": "*" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -3235,6 +3250,11 @@ "color-support": "bin.js" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "node_modules/common-ancestor-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", @@ -3681,6 +3701,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -3987,6 +4012,11 @@ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -7027,6 +7057,11 @@ "node": "*" } }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -7044,6 +7079,27 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -7910,6 +7966,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/raw-body": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", @@ -8083,6 +8156,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -8187,6 +8268,14 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" }, + "node_modules/schemes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/schemes/-/schemes-1.4.0.tgz", + "integrity": "sha512-ImFy9FbCsQlVgnE3TCWmLPCFnVzx0lHL/l+umHplDqAKd0dzFpnS6lFZIpagBlYhKwzVmlV36ec0Y1XTu8JBAQ==", + "dependencies": { + "extend": "^3.0.0" + } + }, "node_modules/semver": { "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", @@ -8516,6 +8605,17 @@ "npm": ">= 3.0.0" } }, + "node_modules/smtp-address-parser": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/smtp-address-parser/-/smtp-address-parser-1.0.10.tgz", + "integrity": "sha512-Osg9LmvGeAG/hyao4mldbflLOkkr3a+h4m1lwKCK5U8M6ZAr7tdXEz/+/vr752TSGE4MNUlUl9cIK2cB8cgzXg==", + "dependencies": { + "nearley": "^2.20.1" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/socks": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", diff --git a/package.json b/package.json index 95521abf0..ec0a38750 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "@npmcli/arborist": "7.5.2", "ajv": "^8.14.0", "ajv-formats": "^3.0.1", + "ajv-formats-draft2019": "^1.6.1", "cheerio": "^1.0.0-rc.12", "edn-data": "1.1.1", "find-up": "7.0.0", diff --git a/types/validator.d.ts.map b/types/validator.d.ts.map index 3afa096e5..2cc98315f 100644 --- a/types/validator.d.ts.map +++ b/types/validator.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../validator.js"],"names":[],"mappings":"AAmBO,qCAFI,MAAM,WA6ChB;AAOM,0CAFI,MAAM,WAiDhB;AAOM,uCAFI,MAAM,WAgEhB;AA6BM,sCAFI,MAAM,WA2ChB"} \ No newline at end of file +{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../validator.js"],"names":[],"mappings":"AAoBO,qCAFI,MAAM,WA+ChB;AAOM,0CAFI,MAAM,WAiDhB;AAOM,uCAFI,MAAM,WAgEhB;AA6BM,sCAFI,MAAM,WA2ChB"} \ No newline at end of file diff --git a/utils.test.js b/utils.test.js index e9785ffb8..994d2e6c0 100644 --- a/utils.test.js +++ b/utils.test.js @@ -2398,8 +2398,8 @@ test("parsePkgLock v3", async () => { projectName: "cdxgen", }); deps = parsedList.pkgList; - expect(deps.length).toEqual(848); - expect(parsedList.dependenciesList.length).toEqual(848); + expect(deps.length).toEqual(859); + expect(parsedList.dependenciesList.length).toEqual(859); }); test("parseBowerJson", async () => { diff --git a/validator.js b/validator.js index 994d4bb6b..96e84dadb 100644 --- a/validator.js +++ b/validator.js @@ -1,11 +1,12 @@ import { readFileSync } from "node:fs"; import { dirname, join } from "node:path"; +import { URL, fileURLToPath } from "node:url"; import Ajv from "ajv"; import addFormats from "ajv-formats"; +import addFormatsDraft2019 from "ajv-formats-draft2019"; import { PackageURL } from "packageurl-js"; import { DEBUG_MODE } from "./utils.js"; -import { URL, fileURLToPath } from "node:url"; let url = import.meta.url; if (!url.startsWith("file://")) { url = new URL(`file://${import.meta.url}`).toString(); @@ -35,7 +36,8 @@ export const validateBom = (bomJson) => { ); const ajv = new Ajv({ schemas: [schema, defsSchema, spdxSchema], - strict: false, + strict: true, + strictRequired: false, // Required as oneOf combined with required is not working well (see https://github.com/ajv-validator/ajv/issues/1571) logger: false, verbose: true, code: { @@ -45,6 +47,7 @@ export const validateBom = (bomJson) => { }, }); addFormats(ajv); + addFormatsDraft2019(ajv); const validate = ajv.getSchema( `http://cyclonedx.org/schema/bom-${bomJson.specVersion}.schema.json`, );