mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 18:15:42 +01:00
Merge pull request #7 from csaf-poc/validate-csaf-schema-alt
Validate csaf schema
This commit is contained in:
commit
75bf445c71
10 changed files with 1873 additions and 1 deletions
|
|
@ -27,6 +27,7 @@ type config struct {
|
|||
OpenPGPURL string `toml:"openpgp_url"`
|
||||
Domain string `toml:"domain"`
|
||||
NoPassphrase bool `toml:"no_passphrase"`
|
||||
NoValidation bool `toml:"no_validation"`
|
||||
DynamicProviderMetaData bool `toml:"dynamic_provider_metadata"`
|
||||
Publisher *csaf.Publisher `toml:"publisher"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,14 @@ func (c *controller) render(rw http.ResponseWriter, tmpl string, arg interface{}
|
|||
}
|
||||
|
||||
func (c *controller) failed(rw http.ResponseWriter, tmpl string, err error) {
|
||||
rw.Header().Set("Content-type", "text/html; charset=utf-8")
|
||||
result := map[string]interface{}{"Error": []error{err}}
|
||||
if err := c.tmpl.ExecuteTemplate(rw, tmpl, result); err != nil {
|
||||
log.Printf("warn: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *controller) multiFailed(rw http.ResponseWriter, tmpl string, err interface{}) {
|
||||
rw.Header().Set("Content-type", "text/html; charset=utf-8")
|
||||
result := map[string]interface{}{"Error": err}
|
||||
if err := c.tmpl.ExecuteTemplate(rw, tmpl, result); err != nil {
|
||||
|
|
@ -188,6 +196,20 @@ func (c *controller) upload(rw http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// Validate againt JSON schema.
|
||||
if !c.cfg.NoValidation {
|
||||
validationErrors, err := csaf.ValidateCSAF(content)
|
||||
if err != nil {
|
||||
c.failed(rw, "upload.html", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(validationErrors) > 0 {
|
||||
c.multiFailed(rw, "upload.html", validationErrors)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ex, err := newExtraction(content)
|
||||
if err != nil {
|
||||
c.failed(rw, "upload.html", err)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,18 @@
|
|||
<body>
|
||||
<h1>CSAF-Provider - CSAF uploaded</h1>
|
||||
{{ if .Error }}
|
||||
<strong>Error: <tt>{{ .Error }}.</tt></strong>
|
||||
{{ if eq (len .Error) 1 }}
|
||||
<strong>Error: <tt>{{ index .Error 0 }}.</tt></strong>
|
||||
{{ else }}
|
||||
<p>
|
||||
Errors:
|
||||
<ul>
|
||||
{{ range .Error }}
|
||||
<li>{{ . }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
<p>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<table>
|
||||
<tr><td>CSAF file:</td><td><tt>{{ .Name }}</tt></td></tr>
|
||||
|
|
|
|||
1343
csaf/schema/csaf_json_schema.json
Normal file
1343
csaf/schema/csaf_json_schema.json
Normal file
File diff suppressed because it is too large
Load diff
104
csaf/schema/cvss-v2.0.json
Normal file
104
csaf/schema/cvss-v2.0.json
Normal file
|
|
@ -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-04/schema#",
|
||||
"title": "JSON Schema for Common Vulnerability Scoring System version 2.0",
|
||||
"id": "https://www.first.org/cvss/cvss-v2.0.json?20170531",
|
||||
"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" ]
|
||||
}
|
||||
143
csaf/schema/cvss-v3.0.json
Normal file
143
csaf/schema/cvss-v3.0.json
Normal file
|
|
@ -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-04/schema#",
|
||||
"title": "JSON Schema for Common Vulnerability Scoring System version 3.0",
|
||||
"id": "https://www.first.org/cvss/cvss-v3.0.json?20170531",
|
||||
"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" ]
|
||||
}
|
||||
143
csaf/schema/cvss-v3.1.json
Normal file
143
csaf/schema/cvss-v3.1.json
Normal file
|
|
@ -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#",
|
||||
"title": "JSON Schema for Common Vulnerability Scoring System version 3.1",
|
||||
"$id": "https://www.first.org/cvss/cvss-v3.1.json?20211103",
|
||||
"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" ]
|
||||
}
|
||||
102
csaf/validation.go
Normal file
102
csaf/validation.go
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
package csaf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed" // Used for embedding.
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/santhosh-tekuri/jsonschema/v5"
|
||||
)
|
||||
|
||||
//go:embed schema/csaf_json_schema.json
|
||||
var csafSchema []byte
|
||||
|
||||
//go:embed schema/cvss-v2.0.json
|
||||
var cvss20 []byte
|
||||
|
||||
//go:embed schema/cvss-v3.0.json
|
||||
var cvss30 []byte
|
||||
|
||||
//go:embed schema/cvss-v3.1.json
|
||||
var cvss31 []byte
|
||||
|
||||
var (
|
||||
compileSchemaOnce sync.Once
|
||||
compileError error
|
||||
compiledSchema *jsonschema.Schema
|
||||
)
|
||||
|
||||
func compileSchema() {
|
||||
c := jsonschema.NewCompiler()
|
||||
|
||||
for _, s := range []struct {
|
||||
url string
|
||||
data []byte
|
||||
}{
|
||||
{"https://docs.oasis-open.org/csaf/csaf/v2.0/csaf_json_schema.json", csafSchema},
|
||||
{"https://www.first.org/cvss/cvss-v2.0.json", cvss20},
|
||||
{"https://www.first.org/cvss/cvss-v3.0.json", cvss30},
|
||||
{"https://www.first.org/cvss/cvss-v3.1.json", cvss31},
|
||||
} {
|
||||
if compileError = c.AddResource(s.url, bytes.NewReader(s.data)); compileError != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
compiledSchema, compileError = c.Compile(
|
||||
"https://docs.oasis-open.org/csaf/csaf/v2.0/csaf_json_schema.json")
|
||||
}
|
||||
|
||||
// ValidateCSAF validates the document data against the JSON schema
|
||||
// of CSAF.
|
||||
func ValidateCSAF(doc interface{}) ([]string, error) {
|
||||
|
||||
compileSchemaOnce.Do(compileSchema)
|
||||
if compileError != nil {
|
||||
return nil, compileError
|
||||
}
|
||||
|
||||
err := compiledSchema.Validate(doc)
|
||||
if err == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
valErr, ok := err.(*jsonschema.ValidationError)
|
||||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
basic := valErr.BasicOutput()
|
||||
if basic.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
errs := basic.Errors
|
||||
|
||||
sort.Slice(errs, func(i, j int) bool {
|
||||
pi := errs[i].InstanceLocation
|
||||
pj := errs[j].InstanceLocation
|
||||
if strings.HasPrefix(pj, pi) {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(pi, pj) {
|
||||
return false
|
||||
}
|
||||
if pi != pj {
|
||||
return pi < pj
|
||||
}
|
||||
return errs[i].Error < errs[j].Error
|
||||
})
|
||||
|
||||
res := make([]string, 0, len(errs))
|
||||
|
||||
for i := range errs {
|
||||
if e := &errs[i]; e.InstanceLocation != "" && e.Error != "" {
|
||||
res = append(res, e.InstanceLocation+": "+e.Error)
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
1
go.mod
1
go.mod
|
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/PaesslerAG/gval v1.1.2
|
||||
github.com/PaesslerAG/jsonpath v0.1.1
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.3.0
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -22,6 +22,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 h1:TToq11gyfNlrMFZiYujSekIsPd9AmsA2Bj/iv+s4JHE=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue