From 3390fbf84c439546613d2b62ac21115f0322f9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Helmke?= Date: Tue, 26 Mar 2024 16:28:59 +0100 Subject: [PATCH] add schema validation workflow using ajv and provide wrapper script in new /_scripts folder --- .github/workflows/validate_schema.yml | 23 ++ .../contrib/schema/cve_item-v2.0.schema.json | 213 ++++++++++++++++++ _scripts/contrib/schema/cvss-v2.0.schema.json | 104 +++++++++ _scripts/contrib/schema/cvss-v3.0.schema.json | 143 ++++++++++++ _scripts/contrib/schema/cvss-v3.1.schema.json | 143 ++++++++++++ _scripts/contrib/schema/draft-07-schema.json | 172 ++++++++++++++ _scripts/validate_schema-v2.0.bash | 46 ++++ 7 files changed, 844 insertions(+) create mode 100644 .github/workflows/validate_schema.yml create mode 100644 _scripts/contrib/schema/cve_item-v2.0.schema.json create mode 100644 _scripts/contrib/schema/cvss-v2.0.schema.json create mode 100644 _scripts/contrib/schema/cvss-v3.0.schema.json create mode 100644 _scripts/contrib/schema/cvss-v3.1.schema.json create mode 100644 _scripts/contrib/schema/draft-07-schema.json create mode 100755 _scripts/validate_schema-v2.0.bash diff --git a/.github/workflows/validate_schema.yml b/.github/workflows/validate_schema.yml new file mode 100644 index 00000000000..4c0d4e79034 --- /dev/null +++ b/.github/workflows/validate_schema.yml @@ -0,0 +1,23 @@ +name: validate-schema +on: + push: + branches: + - "main" + workflow_dispatch: {} +jobs: + validate-schema: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPOSITORY: ${{ github.repository }} + BRANCH_NAME: ${{ github.ref_name }} + - name: Install dependencies + run: npm install -g ajv-cli && npm install -g ajv-formats + - name: Run json schema validation via ajv + run: bash _scripts/validate_schema-v2.0.bash + shell: bash diff --git a/_scripts/contrib/schema/cve_item-v2.0.schema.json b/_scripts/contrib/schema/cve_item-v2.0.schema.json new file mode 100644 index 00000000000..a8d1aa19960 --- /dev/null +++ b/_scripts/contrib/schema/cve_item-v2.0.schema.json @@ -0,0 +1,213 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "Modified JSON Schema for cve_items returned by the NVD Vulnerability Data API version 2.0", + "definitions": { + "cvss-v2": { + "properties": { + "source": { "type": "string" }, + "type": { "enum": ["Primary", "Secondary"] }, + "cvssData": { + "$ref": "cvss-v2.0.schema.json" + }, + "baseSeverity": { "type": "string" }, + "exploitabilityScore": { "$ref": "#/definitions/def_subscore" }, + "impactScore": { "$ref": "#/definitions/def_subscore" }, + "acInsufInfo": { "type": "boolean" }, + "obtainAllPrivilege": { "type": "boolean" }, + "obtainUserPrivilege": { "type": "boolean" }, + "obtainOtherPrivilege": { "type": "boolean" }, + "userInteractionRequired": { "type": "boolean" } + }, + "required": ["source", "type", "cvssData"], + "additionalProperties": false + }, + + "cvss-v30": { + "properties": { + "source": { "type": "string" }, + "type": { "enum": ["Primary", "Secondary"] }, + "cvssData": { + "$ref": "cvss-v3.0.schema.json" + }, + "exploitabilityScore": { "$ref": "#/definitions/def_subscore" }, + "impactScore": { "$ref": "#/definitions/def_subscore" } + }, + "required": ["source", "type", "cvssData"], + "additionalProperties": false + }, + + "cvss-v31": { + "properties": { + "source": { "type": "string" }, + "type": { "enum": ["Primary", "Secondary"] }, + "cvssData": { + "$ref": "cvss-v3.1.schema.json" + }, + "exploitabilityScore": { "$ref": "#/definitions/def_subscore" }, + "impactScore": { "$ref": "#/definitions/def_subscore" } + }, + "required": ["source", "type", "cvssData"], + "additionalProperties": false + }, + + "cve_id": { + "type": "string", + "pattern": "^CVE-[0-9]{4}-[0-9]{4,}$" + }, + "lang_string": { + "type": "object", + "properties": { + "lang": { "type": "string" }, + "value": { "type": "string", "maxLength": 4096 } + }, + "required": ["lang", "value"], + "additionalProperties": false + }, + "reference": { + "type": "object", + "properties": { + "url": { + "maxLength": 500, + "type": "string", + "pattern": "^(ftp|http)s?://\\S+$" + }, + "source": { "type": "string" }, + "tags": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": ["url"], + "additionalProperties": false + }, + "vendorComment": { + "type": "object", + "properties": { + "organization": { "type": "string" }, + "comment": { "type": "string" }, + "lastModified": { "type": "string", "format": "date-time" } + }, + "required": ["organization", "comment", "lastModified"], + "additionalProperties": false + }, + "weakness": { + "properties": { + "source": { "type": "string" }, + "type": { "type": "string" }, + "description": { + "type": "array", + "minItems": 0, + "items": { "$ref": "#/definitions/lang_string" } + } + }, + "required": ["source", "type", "description"], + "additionalProperties": false + }, + "config": { + "properties": { + "operator": { "type": "string", "enum": ["AND", "OR"] }, + "negate": { "type": "boolean" }, + "nodes": { "type": "array", "items": { "$ref": "#/definitions/node" } } + }, + "required": ["nodes"], + "additionalProperties": false + }, + "node": { + "description": "Defines a configuration node in an NVD applicability statement.", + "properties": { + "operator": { "type": "string", "enum": ["AND", "OR"] }, + "negate": { "type": "boolean" }, + "cpeMatch": { + "type": "array", + "items": { "$ref": "#/definitions/cpe_match" } + } + }, + "required": ["operator", "cpeMatch"], + "additionalProperties": false + }, + "cpe_match": { + "description": "CPE match string or range", + "type": "object", + "properties": { + "vulnerable": { "type": "boolean" }, + "criteria": { "type": "string" }, + "matchCriteriaId": { "type": "string", "format": "uuid" }, + "versionStartExcluding": { "type": "string" }, + "versionStartIncluding": { "type": "string" }, + "versionEndExcluding": { "type": "string" }, + "versionEndIncluding": { "type": "string" } + }, + "required": ["vulnerable", "criteria", "matchCriteriaId"], + "additionalProperties": false + }, + "def_subscore": { + "description": "CVSS subscore.", + "type": "number", + "minimum": 0, + "maximum": 10 + } + }, + + "type": "object", + "properties": { + "id": { "$ref": "#/definitions/cve_id" }, + "sourceIdentifier": { "type": "string" }, + "vulnStatus": { "type": "string" }, + "published": { "type": "string", "format": "date-time" }, + "lastModified": { "type": "string", "format": "date-time" }, + "evaluatorComment": { "type": "string" }, + "evaluatorSolution": { "type": "string" }, + "evaluatorImpact": { "type": "string" }, + "cisaExploitAdd": { "type": "string", "format": "date" }, + "cisaActionDue": { "type": "string", "format": "date" }, + "cisaRequiredAction": { "type": "string" }, + "cisaVulnerabilityName": { "type": "string" }, + "descriptions": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#/definitions/lang_string" } + }, + "references": { + "type": "array", + "items": { "$ref": "#/definitions/reference" }, + "maxItems": 500, + "minItems": 0 + }, + "metrics": { + "description": "Metric scores for a vulnerability as found on NVD.", + "type": "object", + "properties": { + "cvssMetricV31": { + "description": "CVSS V3.1 score.", + "type": "array", + "items": { "$ref": "#/definitions/cvss-v31" } + }, + "cvssMetricV30": { + "description": "CVSS V3.0 score.", + "type": "array", + "items": { "$ref": "#/definitions/cvss-v30" } + }, + "cvssMetricV2": { + "description": "CVSS V2.0 score.", + "type": "array", + "items": { "$ref": "#/definitions/cvss-v2" } + } + }, + "additionalProperties": false + }, + "weaknesses": { + "type": "array", + "items": { "$ref": "#/definitions/weakness" } + }, + "configurations": { + "type": "array", + "items": { "$ref": "#/definitions/config" } + }, + "vendorComments": { + "type": "array", + "items": { "$ref": "#/definitions/vendorComment" } + } + }, + "required": ["id", "published", "lastModified", "references", "descriptions"], + "additionalProperties": false +} diff --git a/_scripts/contrib/schema/cvss-v2.0.schema.json b/_scripts/contrib/schema/cvss-v2.0.schema.json new file mode 100644 index 00000000000..72c682129ed --- /dev/null +++ b/_scripts/contrib/schema/cvss-v2.0.schema.json @@ -0,0 +1,104 @@ +{ + "license": [ + "Copyright (c) 2017, FIRST.ORG, INC.", + "All rights reserved.", + "", + "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the ", + "following conditions are met:", + "1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following ", + " disclaimer.", + "2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the ", + " following disclaimer in the documentation and/or other materials provided with the distribution.", + "3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote ", + " products derived from this software without specific prior written permission.", + "", + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, ", + "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ", + "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ", + "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ", + "SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ", + "WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ", + "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ], + + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "cvss-v2.0.schema.json", + "title": "JSON Schema for Common Vulnerability Scoring System version 2.0", + "type": "object", + "definitions": { + "accessVectorType": { + "type": "string", + "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL" ] + }, + "accessComplexityType": { + "type": "string", + "enum": [ "HIGH", "MEDIUM", "LOW" ] + }, + "authenticationType": { + "type": "string", + "enum": [ "MULTIPLE", "SINGLE", "NONE" ] + }, + "ciaType": { + "type": "string", + "enum": [ "NONE", "PARTIAL", "COMPLETE" ] + }, + "exploitabilityType": { + "type": "string", + "enum": [ "UNPROVEN", "PROOF_OF_CONCEPT", "FUNCTIONAL", "HIGH", "NOT_DEFINED" ] + }, + "remediationLevelType": { + "type": "string", + "enum": [ "OFFICIAL_FIX", "TEMPORARY_FIX", "WORKAROUND", "UNAVAILABLE", "NOT_DEFINED" ] + }, + "reportConfidenceType": { + "type": "string", + "enum": [ "UNCONFIRMED", "UNCORROBORATED", "CONFIRMED", "NOT_DEFINED" ] + }, + "collateralDamagePotentialType": { + "type": "string", + "enum": [ "NONE", "LOW", "LOW_MEDIUM", "MEDIUM_HIGH", "HIGH", "NOT_DEFINED" ] + }, + "targetDistributionType": { + "type": "string", + "enum": [ "NONE", "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] + }, + "ciaRequirementType": { + "type": "string", + "enum": [ "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] + }, + "scoreType": { + "type": "number", + "minimum": 0, + "maximum": 10 + } + }, + "properties": { + "version": { + "description": "CVSS Version", + "type": "string", + "enum": [ "2.0" ] + }, + "vectorString": { + "type": "string", + "pattern": "^((AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))/)*(AV:[NAL]|AC:[LMH]|Au:[MSN]|[CIA]:[NPC]|E:(U|POC|F|H|ND)|RL:(OF|TF|W|U|ND)|RC:(UC|UR|C|ND)|CDP:(N|L|LM|MH|H|ND)|TD:(N|L|M|H|ND)|[CIA]R:(L|M|H|ND))$" + }, + "accessVector": { "$ref": "#/definitions/accessVectorType" }, + "accessComplexity": { "$ref": "#/definitions/accessComplexityType" }, + "authentication": { "$ref": "#/definitions/authenticationType" }, + "confidentialityImpact": { "$ref": "#/definitions/ciaType" }, + "integrityImpact": { "$ref": "#/definitions/ciaType" }, + "availabilityImpact": { "$ref": "#/definitions/ciaType" }, + "baseScore": { "$ref": "#/definitions/scoreType" }, + "exploitability": { "$ref": "#/definitions/exploitabilityType" }, + "remediationLevel": { "$ref": "#/definitions/remediationLevelType" }, + "reportConfidence": { "$ref": "#/definitions/reportConfidenceType" }, + "temporalScore": { "$ref": "#/definitions/scoreType" }, + "collateralDamagePotential": { "$ref": "#/definitions/collateralDamagePotentialType" }, + "targetDistribution": { "$ref": "#/definitions/targetDistributionType" }, + "confidentialityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "integrityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "availabilityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "environmentalScore": { "$ref": "#/definitions/scoreType" } + }, + "required": [ "version", "vectorString", "baseScore" ] +} \ No newline at end of file diff --git a/_scripts/contrib/schema/cvss-v3.0.schema.json b/_scripts/contrib/schema/cvss-v3.0.schema.json new file mode 100644 index 00000000000..1637036e6bb --- /dev/null +++ b/_scripts/contrib/schema/cvss-v3.0.schema.json @@ -0,0 +1,143 @@ +{ + "license": [ + "Copyright (c) 2017, FIRST.ORG, INC.", + "All rights reserved.", + "", + "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the ", + "following conditions are met:", + "1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following ", + " disclaimer.", + "2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the ", + " following disclaimer in the documentation and/or other materials provided with the distribution.", + "3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote ", + " products derived from this software without specific prior written permission.", + "", + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, ", + "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ", + "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ", + "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ", + "SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ", + "WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ", + "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ], + + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "cvss-v3.0.schema.json", + "title": "JSON Schema for Common Vulnerability Scoring System version 3.0", + "type": "object", + "definitions": { + "attackVectorType": { + "type": "string", + "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL", "PHYSICAL" ] + }, + "modifiedAttackVectorType": { + "type": "string", + "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL", "PHYSICAL", "NOT_DEFINED" ] + }, + "attackComplexityType": { + "type": "string", + "enum": [ "HIGH", "LOW" ] + }, + "modifiedAttackComplexityType": { + "type": "string", + "enum": [ "HIGH", "LOW", "NOT_DEFINED" ] + }, + "privilegesRequiredType": { + "type": "string", + "enum": [ "HIGH", "LOW", "NONE" ] + }, + "modifiedPrivilegesRequiredType": { + "type": "string", + "enum": [ "HIGH", "LOW", "NONE", "NOT_DEFINED" ] + }, + "userInteractionType": { + "type": "string", + "enum": [ "NONE", "REQUIRED" ] + }, + "modifiedUserInteractionType": { + "type": "string", + "enum": [ "NONE", "REQUIRED", "NOT_DEFINED" ] + }, + "scopeType": { + "type": "string", + "enum": [ "UNCHANGED", "CHANGED" ] + }, + "modifiedScopeType": { + "type": "string", + "enum": [ "UNCHANGED", "CHANGED", "NOT_DEFINED" ] + }, + "ciaType": { + "type": "string", + "enum": [ "NONE", "LOW", "HIGH" ] + }, + "modifiedCiaType": { + "type": "string", + "enum": [ "NONE", "LOW", "HIGH", "NOT_DEFINED" ] + }, + "exploitCodeMaturityType": { + "type": "string", + "enum": [ "UNPROVEN", "PROOF_OF_CONCEPT", "FUNCTIONAL", "HIGH", "NOT_DEFINED" ] + }, + "remediationLevelType": { + "type": "string", + "enum": [ "OFFICIAL_FIX", "TEMPORARY_FIX", "WORKAROUND", "UNAVAILABLE", "NOT_DEFINED" ] + }, + "confidenceType": { + "type": "string", + "enum": [ "UNKNOWN", "REASONABLE", "CONFIRMED", "NOT_DEFINED" ] + }, + "ciaRequirementType": { + "type": "string", + "enum": [ "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] + }, + "scoreType": { + "type": "number", + "minimum": 0, + "maximum": 10 + }, + "severityType": { + "type": "string", + "enum": [ "NONE", "LOW", "MEDIUM", "HIGH", "CRITICAL" ] + } + }, + "properties": { + "version": { + "description": "CVSS Version", + "type": "string", + "enum": [ "3.0" ] + }, + "vectorString": { + "type": "string", + "pattern": "^CVSS:3[.]0/((AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[UNLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XUNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$" + }, + "attackVector": { "$ref": "#/definitions/attackVectorType" }, + "attackComplexity": { "$ref": "#/definitions/attackComplexityType" }, + "privilegesRequired": { "$ref": "#/definitions/privilegesRequiredType" }, + "userInteraction": { "$ref": "#/definitions/userInteractionType" }, + "scope": { "$ref": "#/definitions/scopeType" }, + "confidentialityImpact": { "$ref": "#/definitions/ciaType" }, + "integrityImpact": { "$ref": "#/definitions/ciaType" }, + "availabilityImpact": { "$ref": "#/definitions/ciaType" }, + "baseScore": { "$ref": "#/definitions/scoreType" }, + "baseSeverity": { "$ref": "#/definitions/severityType" }, + "exploitCodeMaturity": { "$ref": "#/definitions/exploitCodeMaturityType" }, + "remediationLevel": { "$ref": "#/definitions/remediationLevelType" }, + "reportConfidence": { "$ref": "#/definitions/confidenceType" }, + "temporalScore": { "$ref": "#/definitions/scoreType" }, + "temporalSeverity": { "$ref": "#/definitions/severityType" }, + "confidentialityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "integrityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "availabilityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "modifiedAttackVector": { "$ref": "#/definitions/modifiedAttackVectorType" }, + "modifiedAttackComplexity": { "$ref": "#/definitions/modifiedAttackComplexityType" }, + "modifiedPrivilegesRequired": { "$ref": "#/definitions/modifiedPrivilegesRequiredType" }, + "modifiedUserInteraction": { "$ref": "#/definitions/modifiedUserInteractionType" }, + "modifiedScope": { "$ref": "#/definitions/modifiedScopeType" }, + "modifiedConfidentialityImpact": { "$ref": "#/definitions/modifiedCiaType" }, + "modifiedIntegrityImpact": { "$ref": "#/definitions/modifiedCiaType" }, + "modifiedAvailabilityImpact": { "$ref": "#/definitions/modifiedCiaType" }, + "environmentalScore": { "$ref": "#/definitions/scoreType" }, + "environmentalSeverity": { "$ref": "#/definitions/severityType" } + }, + "required": [ "version", "vectorString", "baseScore", "baseSeverity" ] +} \ No newline at end of file diff --git a/_scripts/contrib/schema/cvss-v3.1.schema.json b/_scripts/contrib/schema/cvss-v3.1.schema.json new file mode 100644 index 00000000000..07d233005ce --- /dev/null +++ b/_scripts/contrib/schema/cvss-v3.1.schema.json @@ -0,0 +1,143 @@ +{ + "license": [ + "Copyright (c) 2021, FIRST.ORG, INC.", + "All rights reserved.", + "", + "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the ", + "following conditions are met:", + "1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following ", + " disclaimer.", + "2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the ", + " following disclaimer in the documentation and/or other materials provided with the distribution.", + "3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote ", + " products derived from this software without specific prior written permission.", + "", + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, ", + "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ", + "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ", + "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ", + "SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ", + "WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ", + "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ], + + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "cvss-v3.1.schema.json", + "title": "JSON Schema for Common Vulnerability Scoring System version 3.1", + "type": "object", + "definitions": { + "attackVectorType": { + "type": "string", + "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL", "PHYSICAL" ] + }, + "modifiedAttackVectorType": { + "type": "string", + "enum": [ "NETWORK", "ADJACENT_NETWORK", "LOCAL", "PHYSICAL", "NOT_DEFINED" ] + }, + "attackComplexityType": { + "type": "string", + "enum": [ "HIGH", "LOW" ] + }, + "modifiedAttackComplexityType": { + "type": "string", + "enum": [ "HIGH", "LOW", "NOT_DEFINED" ] + }, + "privilegesRequiredType": { + "type": "string", + "enum": [ "HIGH", "LOW", "NONE" ] + }, + "modifiedPrivilegesRequiredType": { + "type": "string", + "enum": [ "HIGH", "LOW", "NONE", "NOT_DEFINED" ] + }, + "userInteractionType": { + "type": "string", + "enum": [ "NONE", "REQUIRED" ] + }, + "modifiedUserInteractionType": { + "type": "string", + "enum": [ "NONE", "REQUIRED", "NOT_DEFINED" ] + }, + "scopeType": { + "type": "string", + "enum": [ "UNCHANGED", "CHANGED" ] + }, + "modifiedScopeType": { + "type": "string", + "enum": [ "UNCHANGED", "CHANGED", "NOT_DEFINED" ] + }, + "ciaType": { + "type": "string", + "enum": [ "NONE", "LOW", "HIGH" ] + }, + "modifiedCiaType": { + "type": "string", + "enum": [ "NONE", "LOW", "HIGH", "NOT_DEFINED" ] + }, + "exploitCodeMaturityType": { + "type": "string", + "enum": [ "UNPROVEN", "PROOF_OF_CONCEPT", "FUNCTIONAL", "HIGH", "NOT_DEFINED" ] + }, + "remediationLevelType": { + "type": "string", + "enum": [ "OFFICIAL_FIX", "TEMPORARY_FIX", "WORKAROUND", "UNAVAILABLE", "NOT_DEFINED" ] + }, + "confidenceType": { + "type": "string", + "enum": [ "UNKNOWN", "REASONABLE", "CONFIRMED", "NOT_DEFINED" ] + }, + "ciaRequirementType": { + "type": "string", + "enum": [ "LOW", "MEDIUM", "HIGH", "NOT_DEFINED" ] + }, + "scoreType": { + "type": "number", + "minimum": 0, + "maximum": 10 + }, + "severityType": { + "type": "string", + "enum": [ "NONE", "LOW", "MEDIUM", "HIGH", "CRITICAL" ] + } + }, + "properties": { + "version": { + "description": "CVSS Version", + "type": "string", + "enum": [ "3.1" ] + }, + "vectorString": { + "type": "string", + "pattern": "^CVSS:3[.]1/((AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])/)*(AV:[NALP]|AC:[LH]|PR:[NLH]|UI:[NR]|S:[UC]|[CIA]:[NLH]|E:[XUPFH]|RL:[XOTWU]|RC:[XURC]|[CIA]R:[XLMH]|MAV:[XNALP]|MAC:[XLH]|MPR:[XNLH]|MUI:[XNR]|MS:[XUC]|M[CIA]:[XNLH])$" + }, + "attackVector": { "$ref": "#/definitions/attackVectorType" }, + "attackComplexity": { "$ref": "#/definitions/attackComplexityType" }, + "privilegesRequired": { "$ref": "#/definitions/privilegesRequiredType" }, + "userInteraction": { "$ref": "#/definitions/userInteractionType" }, + "scope": { "$ref": "#/definitions/scopeType" }, + "confidentialityImpact": { "$ref": "#/definitions/ciaType" }, + "integrityImpact": { "$ref": "#/definitions/ciaType" }, + "availabilityImpact": { "$ref": "#/definitions/ciaType" }, + "baseScore": { "$ref": "#/definitions/scoreType" }, + "baseSeverity": { "$ref": "#/definitions/severityType" }, + "exploitCodeMaturity": { "$ref": "#/definitions/exploitCodeMaturityType" }, + "remediationLevel": { "$ref": "#/definitions/remediationLevelType" }, + "reportConfidence": { "$ref": "#/definitions/confidenceType" }, + "temporalScore": { "$ref": "#/definitions/scoreType" }, + "temporalSeverity": { "$ref": "#/definitions/severityType" }, + "confidentialityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "integrityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "availabilityRequirement": { "$ref": "#/definitions/ciaRequirementType" }, + "modifiedAttackVector": { "$ref": "#/definitions/modifiedAttackVectorType" }, + "modifiedAttackComplexity": { "$ref": "#/definitions/modifiedAttackComplexityType" }, + "modifiedPrivilegesRequired": { "$ref": "#/definitions/modifiedPrivilegesRequiredType" }, + "modifiedUserInteraction": { "$ref": "#/definitions/modifiedUserInteractionType" }, + "modifiedScope": { "$ref": "#/definitions/modifiedScopeType" }, + "modifiedConfidentialityImpact": { "$ref": "#/definitions/modifiedCiaType" }, + "modifiedIntegrityImpact": { "$ref": "#/definitions/modifiedCiaType" }, + "modifiedAvailabilityImpact": { "$ref": "#/definitions/modifiedCiaType" }, + "environmentalScore": { "$ref": "#/definitions/scoreType" }, + "environmentalSeverity": { "$ref": "#/definitions/severityType" } + }, + "required": [ "version", "vectorString", "baseScore", "baseSeverity" ] +} \ No newline at end of file diff --git a/_scripts/contrib/schema/draft-07-schema.json b/_scripts/contrib/schema/draft-07-schema.json new file mode 100644 index 00000000000..fb92c7f756b --- /dev/null +++ b/_scripts/contrib/schema/draft-07-schema.json @@ -0,0 +1,172 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://json-schema.org/draft-07/schema#", + "title": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { "$ref": "#/definitions/nonNegativeInteger" }, + { "default": 0 } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "$comment": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "readOnly": { + "type": "boolean", + "default": false + }, + "writeOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, + "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { "$ref": "#" }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": true + }, + "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, + "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { "$ref": "#" }, + "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, + "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { "$ref": "#" }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "propertyNames": { "$ref": "#" }, + "const": true, + "enum": { + "type": "array", + "items": true, + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "contentMediaType": { "type": "string" }, + "contentEncoding": { "type": "string" }, + "if": { "$ref": "#" }, + "then": { "$ref": "#" }, + "else": { "$ref": "#" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "default": true +} diff --git a/_scripts/validate_schema-v2.0.bash b/_scripts/validate_schema-v2.0.bash new file mode 100755 index 00000000000..6860c460ece --- /dev/null +++ b/_scripts/validate_schema-v2.0.bash @@ -0,0 +1,46 @@ +#!/bin/bash + +script_parent=$( (cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P) || exit 1 ) +schema_path="$script_parent/contrib/schema" +cve_path="$script_parent/../" + + +print_dependency_error_and_exit() { + echo "[error] $1 not installed." + echo "this script uses ajv to validate the json files in this repository." + echo "please ensure that npm and the required packages are installed." + echo " - npm install -g ajv-cli" + echo " - npm install -g ajv-formats" + echo "[note] the above commands install the ajv packages globally." + exit 2 +} + + +if ! command -v npm &> /dev/null; then + print_dependency_error_and_exit "npm" +fi + +npm list -g ajv &> /dev/null +status=$? +if [ $status -ne 0 ]; then + print_dependency_error_and_exit "ajv-cli" +fi + +npm list -g ajv-formats &> /dev/null +status=$? +if [ $status -ne 0 ]; then + print_dependency_error_and_exit "ajv-formats" +fi + +set -euxo pipefail + +ajv validate -s "$schema_path/cve_item-v2.0.schema.json" \ + -d "$cve_path/CVE-*/**/*.json" \ + --strict=false \ + -r "$schema_path/cvss-v3.1.schema.json" \ + -r "$schema_path/cvss-v3.0.schema.json" \ + -r "$schema_path/cvss-v2.0.schema.json" \ + --all-errors \ + --errors=json \ + -c ajv-formats > /dev/null +