csaf-tools / cvrf-csaf-converter Goto Github PK
View Code? Open in Web Editor NEWA CVRF CSAF Converter, taking care about OASIS specification.
Home Page: https://www.telekom.com/security
License: MIT License
A CVRF CSAF Converter, taking care about OASIS specification.
Home Page: https://www.telekom.com/security
License: MIT License
output-dir
Suggest for spring cleaning to handle the finding
flake8 → cvrf2csaf/section_handlers/document_leaf_elements.py:1:1: F401 'logging' imported but unused
Just remove line 1 stating:
import logging
Maybe perform this patch or something alike (there may well be other places where a parser is setup with the default resolve_entities=True
setting that I did not spot)?
--- cvrf2csaf/cvrf2csaf.py 2022-03-12 15:13:48.000000000 +0100
+++ ../cvrf2csaf.py 2022-03-12 15:10:35.000000000 +0100
@@ -24,6 +24,7 @@
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(module)s - %(levelname)s - %(message)s')
+unresolving_parser = objectify.makeparser(resolve_entities=False)
class DocumentHandler:
"""
@@ -162,7 +163,7 @@
@classmethod
def _open_and_validate_file(cls, file_path):
try:
- xml_objectified = objectify.parse(file_path)
+ xml_objectified = objectify.parse(file_path, parser=unresolving_parser)
except Exception as e:
critical_exit(f'Failed to open input file {file_path}: {e}.')
Aggregate some of the top-level elements to a single class.
This reduces the boilerplate code around section handlers
The new class ToplevelLeafElements takes care about all the top-level elements that do not have children elements, these are:
Also, the class handles the leaf (mandatory) elements of the CSAF 'document' JSON, which are not present in the input CVRF, these are (is):
BSI has a standard template.
From EPIC #10
References:
Special to mention here is E.1 and E.2 here, which states:
/vulnerabilities[]/involvements[]/date
: Holds the date and time of the involvement entry./vulnerabilities[]/product_status/under_investigation
: It is not known yet whether these versions are or are not affected by the vulnerability. However, it is still under investigation - the result will be provided in a later release of the document./vulnerabilities[]/remediations[]/restart_required
: Provides information on category of restart is required by this remediation to become effective./vulnerabilities[]/scores[]
: Specifies information about (at least one) score of the vulnerability and for which products the given value applies. Previously, products where directly tied to the vuln:ScoreSetV2
or vuln:ScoreSetV3
./vulnerabilities[]/scores[]/cvss_v2/*
: Additional elements were introduced through the use of the FIRST CVSSv2 schema./vulnerabilities[]/scores[]/cvss_v3/*
: Additional elements were introduced through the use of the FIRST CVSSv3 schemas.| /vulnerabilities
| /cvrf:cvrfdoc/vuln:Vulnerability
| |
| /vulnerabilities[i]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]
| |
| /vulnerabilities[i]/acknowledgments
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Acknowledgments
| |
| /vulnerabilities[i]/acknowledgments[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Acknowledgments/vuln:Acknowledgment[j+1]
| |
| /vulnerabilities[i]/acknowledgments[j]/names
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Acknowledgments/vuln:Acknowledgment[j+1]/vuln:Name
| |
| /vulnerabilities[i]/acknowledgments[j]/names[k]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Acknowledgments/vuln:Acknowledgment[j+1]/vuln:Name[k+1]/text()
| |
| /vulnerabilities[i]/acknowledgments[j]/organization
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Acknowledgments/vuln:Acknowledgment[j+1]/vuln:Organization[1]/text()
| see E.2 |
| /vulnerabilities[i]/acknowledgments[j]/summary
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Acknowledgments/vuln:Acknowledgment[j+1]/vuln:Description/text()
| |
| /vulnerabilities[i]/acknowledgments[j]/urls
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Acknowledgments/vuln:Acknowledgment[j+1]/vuln:URL
| |
| /vulnerabilities[i]/acknowledgments[j]/urls[k]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Acknowledgments/vuln:Acknowledgment[j+1]/vuln:URL[k+1]/text()
| |
| /vulnerabilities[i]/cve
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVE/text()
| |
| /vulnerabilities[i]/cwe
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CWE
| |
| /vulnerabilities[i]/cwe/id
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CWE/@ID
| |
| /vulnerabilities[i]/cwe/name
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CWE/text()
| |
| /vulnerabilities[i]/discovery_date
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:DiscoveryDate/text()
| |
| /vulnerabilities[i]/id
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ID
| |
| /vulnerabilities[i]/id/system_name
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ID/@SystemName
| |
| /vulnerabilities[i]/id/text
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ID/text()
| |
| /vulnerabilities[i]/involvements
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Involvements
| |
| /vulnerabilities[i]/involvements[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Involvements/vuln:Involvement[j+1]
| |
| /vulnerabilities[i]/involvements[j]/date
| | see E.1 |
| /vulnerabilities[i]/involvements[j]/party
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Involvements/vuln:Involvement[j+1]/@Party
| |
| /vulnerabilities[i]/involvements[j]/status
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Involvements/vuln:Involvement[j+1]/@Status
| |
| /vulnerabilities[i]/involvements[j]/summary
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Involvements/vuln:Involvement[j+1]/vuln:Description/text()
| |
| /vulnerabilities[i]/notes
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Notes
| |
| /vulnerabilities[i]/notes[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Notes/vuln:Note[j+1]
| |
| /vulnerabilities[i]/notes[j]/audience
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Notes/vuln:Note[j+1]/@Audience
| |
| /vulnerabilities[i]/notes[j]/category
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Notes/vuln:Note[j+1]/@Type
| |
| /vulnerabilities[i]/notes[j]/text
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Notes/vuln:Note[j+1]/text()
| |
| /vulnerabilities[i]/notes[j]/title
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Notes/vuln:Note[j+1]/@Title
| |
| /vulnerabilities[i]/product_status
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses
| |
| /vulnerabilities[i]/product_status/first_affected
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="First Affected"]
| |
| /vulnerabilities[i]/product_status/first_affected[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="First Affected"]/vuln:ProductID[j+1]
| |
| /vulnerabilities[i]/product_status/first_fixed
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="First Fixed"]
| |
| /vulnerabilities[i]/product_status/first_fixed[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="First Fixed"]/vuln:ProductID[j+1]
| |
| /vulnerabilities[i]/product_status/fixed
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Fixed"]
| |
| /vulnerabilities[i]/product_status/fixed[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Fixed"]/vuln:ProductID[j+1]
| |
| /vulnerabilities[i]/product_status/known_affected
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Known Affected"]
| |
| /vulnerabilities[i]/product_status/known_affected[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Known Affected"]/vuln:ProductID[j+1]
| |
| /vulnerabilities[i]/product_status/known_not_affected
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Known Not Affected"]
| |
| /vulnerabilities[i]/product_status/known_not_affected[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Known Not Affected"]/vuln:ProductID[j+1]
| |
| /vulnerabilities[i]/product_status/last_affected
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Last Affected"]
| |
| /vulnerabilities[i]/product_status/last_affected[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Last Affected"]/vuln:ProductID[j+1]
| |
| /vulnerabilities[i]/product_status/recommended
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Recommended"]
| |
| /vulnerabilities[i]/product_status/recommended[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ProductStatuses/vuln:Status[@Type="Recommended"]/vuln:ProductID[j+1]
| |
| /vulnerabilities[i]/product_status/under_investigation
| | see E.1 |
| /vulnerabilities[i]/product_status/under_investigation[]
| | see E.1 |
| /vulnerabilities[i]/references
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:References
| |
| /vulnerabilities[i]/references[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:References/vuln:Reference[j+1]
| |
| /vulnerabilities[i]/references[j]/category
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:References/vuln:Reference[j+1]/@Type
| |
| /vulnerabilities[i]/references[j]/summary
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:References/vuln:Reference[j+1]/vuln:Description/text()
| |
| /vulnerabilities[i]/references[j]/url
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:References/vuln:Reference[j+1]/vuln:URL/text()
| |
| /vulnerabilities[i]/release_date
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:ReleaseDate/text()
| |
| /vulnerabilities[i]/remediations
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations
| |
| /vulnerabilities[i]/remediations[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]
| |
| /vulnerabilities[i]/remediations[j]/category
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/@Type
| |
| /vulnerabilities[i]/remediations[j]/date
| | /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/@Date
|
| /vulnerabilities[i]/remediations[j]/details
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/vuln:Description/text()
| |
| /vulnerabilities[i]/remediations[j]/entitlements
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/vuln:Entitlement
| |
| /vulnerabilities[i]/remediations[j]/entitlements[]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/vuln:Entitlement[k+1]/text()
| |
| /vulnerabilities[i]/remediations[j]/group_ids
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/vuln:GroupID
| |
| /vulnerabilities[i]/remediations[j]/group_ids[k]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/vuln:GroupID[k+1]/text()
| |
| /vulnerabilities[i]/remediations[j]/product_ids
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/vuln:ProductID
| |
| /vulnerabilities[i]/remediations[j]/product_ids[k]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/vuln:ProductID[k+1]/text()
| |
| /vulnerabilities[i]/remediations[j]/restart_required
| | see E.1 |
| /vulnerabilities[i]/remediations[j]/restart_required/category
| | see parent |
| /vulnerabilities[i]/remediations[j]/restart_required/details
| | see parent |
| /vulnerabilities[i]/remediations[]/url
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Remediations/vuln:Remediation[j+1]/vuln:URL/text()
| |
| /vulnerabilities[i]/scores
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets
| |
| /vulnerabilities[i]/scores[]
| | see E.1, E.2 |
| /vulnerabilities[i]/scores[n]/cvss_v2
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV2[k]
| see E.2 |
| /vulnerabilities[i]/scores[n]/cvss_v2/version
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/vectorString
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV2[j]/vuln:VectorV2/text()
| |
| /vulnerabilities[i]/scores[n]/cvss_v2/accessVector
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/accessComplexity
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/authentication
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/confidentialityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/integrityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/availabilityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/baseScore
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV2[j]/vuln:BaseScoreV2/text()
| |
| /vulnerabilities[i]/scores[n]/cvss_v2/exploitability
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/remediationLevel
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/reportConfidence
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/temporalScore
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV2[j]/vuln:TemporalScoreV2/text()
| |
| /vulnerabilities[i]/scores[n]/cvss_v2/collateralDamagePotential
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/targetDistribution
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/confidentialityRequirement
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/integrityRequirement
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/availabilityRequirement
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v2/environmentalScore
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV2[j]/vuln:EnvironmentalScoreV2/text()
| see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV3[k]
| see E.2 |
| /vulnerabilities[i]/scores[n]/cvss_v3/version
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/vectorString
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV3[k]/vuln:VectorV3/text()
| |
| /vulnerabilities[i]/scores[n]/cvss_v3/attackVector
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/attackComplexity
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/privilegesRequired
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/userInteraction
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/scope
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/confidentialityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/integrityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/availabilityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/baseScore
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV3[k]/vuln:BaseScoreV3/text()
| |
| /vulnerabilities[i]/scores[n]/cvss_v3/baseSeverity
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/exploitCodeMaturity
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/remediationLevel
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/reportConfidence
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/temporalScore
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV3[k]/vuln:TemporalScoreV3/text()
| |
| /vulnerabilities[i]/scores[n]/cvss_v3/temporalSeverity
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/confidentialityRequirement
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/integrityRequirement
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/availabilityRequirement
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/modifiedAttackVector
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/modifiedAttackComplexity
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/modifiedPrivilegesRequired
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/modifiedUserInteraction
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/modifiedScope
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/modifiedConfidentialityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/modifiedIntegrityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/modifiedAvailabilityImpact
| | see E.1 |
| /vulnerabilities[i]/scores[n]/cvss_v3/environmentalScore
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV3[k]/vuln:EnvironmentalScoreV3/text()
| |
| /vulnerabilities[i]/scores[n]/cvss_v3/environmentalSeverity
| | see E.1 |
| /vulnerabilities[i]/scores[n]/products
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV2[j]/vuln:ProductID
or /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV3[k]/vuln:ProductID
| see E.2 |
| /vulnerabilities[i]/scores[n]/products[l]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV2[j]/vuln:ProductID[l+1]/text()
or /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:CVSSScoreSets/vuln:ScoreSetV3[k]/vuln:ProductID[l+1]/text()
| see E.2 |
| /vulnerabilities[i]/threats
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats
| |
| /vulnerabilities[i]/threats[j]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats/vuln:Threat[j+1]
| |
| /vulnerabilities[i]/threats[j]/category
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats/vuln:Threat[j+1]/@Type
| |
| /vulnerabilities[i]/threats[j]/date
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats/vuln:Threat[j+1]/@Date
| |
| /vulnerabilities[i]/threats[j]/details
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats/vuln:Threat[j+1]/vuln:Description/text()
| |
| /vulnerabilities[i]/threats[j]/group_ids
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats/vuln:Threat[j+1]/vuln:GroupID
| |
| /vulnerabilities[i]/threats[j]/group_ids[k]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats/vuln:Threat[j+1]/vuln:GroupID[k+1]/text()
| |
| /vulnerabilities[i]/threats[j]/product_ids
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats/vuln:Threat[j+1]/vuln:ProductID
| |
| /vulnerabilities[i]/threats[j]/product_ids[k]
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Threats/vuln:Threat[j+1]/vuln:ProductID[k+1]/text()
| |
| /vulnerabilities[i]/title
| /cvrf:cvrfdoc/vuln:Vulnerability[i+1]/vuln:Title/text()
| |
The official conformance target states the following requirements:
Secondly, the program fulfills the following for all items of:
/$defs/version_t
: If any element doesn't match the semantic versioning, replace the all elements of type /$defs/version_t
with the corresponding integer version. For that, CVRF CSAF converter sorts the items of /document/tracking/revision_history
by number
ascending according to the rules of CVRF. Then, it replaces the value of number
with the index number in the array (starting with 1). The value of /document/tracking/version
is replaced by value of number
of the corresponding revision item. The match must be calculated by the original values used in the CVRF document./document/acknowledgments[]/organization
and /vulnerabilities[]/acknowledgments[]/organization
: If more than one cvrf:Organization
instance is given, the CVRF CSAF converter converts the first one into the organization
. In addition the converter outputs a warning that information might be lost during conversion of document or vulnerability acknowledgment./document/publisher/name
and /document/publisher/namespace
: Sets the value as given in the configuration of the program or the corresponding argument the program was invoked with. If values from both sources are present, the program should prefer the latter one. The program SHALL NOT use hard-coded values./vulnerabilities[]/scores[]
: If no product_id
is given, the CVRF CSAF converter appends all Product IDs which are listed under ../product_status
in the arrays known_affected
, first_affected
and last_affected
./vulnerabilities[]/scores[]
: If there are CVSS v3.0 and CVSS v3.1 Vectors available for the same product, the CVRF CSAF converter discards the CVSS v3.0 information and provide in CSAF only the CVSS v3.1 information./product_tree/relationships[]
: If more than one prod:FullProductName
instance is given, the CVRF CSAF converter converts the first one into the full_product_name
. In addition, the converter outputs a warning that information might be lost during conversion of product relationships.To ensure code quality, #89 suggests to integrate pyLint as GitHub Action. However, some results must be addressed before doing that.
As discussed today with @pixelkunst-net, the following outputs can be ignored (through adding exemptions to the code):
cvrf2csaf/common/utils.py:39:9: W0511: TODO: Workaround for now, config file placement is to be discussed (fixme)
C0103: Variable name "e" doesn't conform to snake_case naming style (invalid-name)
The package is currently on PyPI. The ownership should be transferred or new maintainers from the project should be added.
While this is not part of the offer, we would like to also run some basic input validation on XML level.
Are you aware of a good tool to run?
Or should we go into validating the XML schema of CVRF 1.2 (e.g. using lxml)?
In the end, the XML schema validator will help us to reject invalid files as a pre-step.
Pre: #10
Please also add CLI arg to skip mandatory tests, because the user could also fix the input in Secvisogram.
Only the relevant parts are written in the specification, the full examples are written here. They are failing (at least) for the specific cases.
The naming of the examples is encoded like this:
OASIS_CSAF_TC-CSAF_2_0-2021-6-1-05-01.json
6.1.05 here means, that this is a test file for Mandatory test 6.1.5
--> All mandatory tests have already been implemented by secvisogram already. More detailed here
Try out pip-licenses.
For compliance reasons, everything which is != MIT licence needs to be added to License.MD
. Generating a short skript to automatically generate this file ensures licence compliant coding.
Special explanation for 6.1.26 Prohibited Document Category Name
:
Document Category can be one of the five given definitions, or any other value.
The 6.1.26 checks that the Document Category value should not be similar to one of these values, otherwise the profiles from chapter 4 are taken.
Informational Advisory
security-incident-response
Security Advisory
veX
We implement this by
Part of EPIC #10
/document/acknowledgments[]/organization
and/vulnerabilities[]/acknowledgments[]/organization
: If more than one cvrf:Organization instance is given, the CVRF CSAF converter converts the first one into the organization. In addition the converter outputs a warning that information might be lost during conversion of document or vulnerability acknowledgment.
-- no entries
*/acknowledgments[]/organization
: See conversion rule in section 9.1.5 of CSAF specification.
(9.1.5 is a copy/paste with changed 1.2 -> 2.0 spec - so nothing in addition)
The package turvallisuusneuvonta
was renamed into csaf
and is available on PyPI. We should adopt that in the converter.
Suggest for spring cleaning to handle the finding
flake8 → cvrf2csaf/cvrf2csaf.py:170:27: F541 f-string is missing placeholders
Just replace:
critical_exit(f'Input document not valid, reason(s).')
with:
critical_exit('Input document not valid, reason(s).')
We should add a GitHub Action to check and maintain the code quality.
A/C
Create a test script, which
Part of EPIC #10.
Oasis v1.2 -> 4.9 Document References
Field Definition 3.1.10 References Type
-- no new elements
| /document/references
| /cvrf:cvrfdoc/cvrf:DocumentReferences
| |
| /document/references[i]
| /cvrf:cvrfdoc/cvrf:DocumentReferences/cvrf:Reference[i+1]
| |
| /document/references[i]/category
| /cvrf:cvrfdoc/cvrf:DocumentReferences/cvrf:Reference[i+1]/@Type
| |
| /document/references[i]/summary
| /cvrf:cvrfdoc/cvrf:DocumentReferences/cvrf:Reference[i+1]/cvrf:Description/text()
| |
| /document/references[]/url
| /cvrf:cvrfdoc/cvrf:DocumentReferences/cvrf:Reference[i+1]/cvrf:URL/text()
| |
A valid CPE, according to CPE Naming Format 2.3, can't be used in a CVRF-Document. Regex is to strict / not correct.
Attribute CPE
The (Common Platform Enumeration) CPE attribute refers to a method for naming platforms external to CSAF CVRF.
« The CPE attribute if present MUST have a value, that is a valid cpe-lang:namePattern as defined in the external specification [CPE23_N] and related schemas. » [CSAF-5.1.2-2]
Example CPE: cpe:2.3:a:gemalto:sentinel_ldk_rte:3.0:*:*:*:*:*:*:*
Log:
2022-02-17 08:56:31,011 - utils - CRITICAL - Input document not valid: Element '{http://docs.oasis-open.org/csaf/ns/csaf-cvrf/v1.2/prod}FullProductName', attribute 'CPE': [facet 'pattern'] The value 'cpe:2.3:a:gemalto:sentinel_ldk_rte:3.0:*:*:*:*:*:*:*'
is not accepted by the pattern '[c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\._\-~%]*){0,6}'
. (, line 0).
As discussed here:
Integrate the mandatory tests into cvrf2csaf.py:
While working on Vulnerabilities section I noticed the following discrepancy in CVRF:
In the specification of CVRF 1.2 is stated that CWE element MUST be present zero or one time, while in xsd scheme of CVRF 1.2 the occurrence is not bounded <xs:element name="CWE" minOccurs="0" maxOccurs="unbounded">
.
The second related discrepancy in CSAF:
vulnerabilities
property in this specification does not have any property marked as mandatory (not even CWE), while here it says It must be tested that the CWE is given.
These two discrepancies raises questions how to approach this in the implementation:
EPIC: #10
[Oasis v1.2 -> Aggregate Severity]http://docs.oasis-open.org/csaf/csaf-cvrf/v1.2/cs01/csaf-cvrf-v1.2-cs01.html#_Toc493508891)
Field Definiition 4.8 Aggregate Severity
Simple mapping
The class is correctly named Acknowledgments
but the filename is still document_acknowledgments.py
. That should be corrected.
Each of the producer mostly has the same format or/and errors in validation, thus I pick just some examples
This was a manual testing with commit 867578e. Just to see if we have some conversion errors. Could be automated in the future.
Used producer files:
https://github.com/csaf-tools/CVRF-CSAF-Converter/tree/testing/examples
And this helper script:
https://github.com/csaf-tools/CVRF-CSAF-Converter/blob/testing/tests/test_producers.sh
Invalid cvrf2doc namespace
INPUT FILE: examples/examples_redhat/RHSA-2021:2040.xml
2022-02-18 15:04:29,499 - utils - CRITICAL - Input document not valid: Element '{http://www.icasi.org/CVRF/schema/cvrf/1.1}cvrfdoc': No matching global declaration available for the validation root. (<string>, line 0).
Missing mandatory fields
INPUT FILE: examples/examples_fortiguard/FG-IR-21-192.xml
2022-02-18 15:06:34,935 - utils - CRITICAL - Input document not valid: Element '{http://docs.oasis-open.org/csaf/ns/csaf-cvrf/v1.2/cvrf}CurrentReleaseDate': This element is not expected. Expected is ( {http://docs.oasis-open.org/csaf/ns/csaf-cvrf/v1.2/cvrf}Status ). (<string>, line 0).
28 examples OK
INPUT FILE: examples/examples_suse/1.2/cvrf-opensuse-su-2015%3A1968-1.xml
2022-02-18 15:46:25,227 - cvrf2csaf - INFO - CSAF schema validation OK
210 examples with ERRORs (not conversion errors, but input errors)
2022-02-18 15:30:20,600 - vulnerability - ERROR - No product_id entry for CVSS score set.
2022-02-18 15:30:20,856 - cvrf2csaf - ERROR - CSAF schema validation error. Path: $.vulnerabilities[0].scores[0].products. Message: [] is too short.
282 examples with CRITICAL
e.g. missing ProductID in Vulnerabilities
2022-02-18 15:49:27,111 - utils - CRITICAL - Input document not valid: Element '{http://docs.oasis-open.org/csaf/ns/csaf-cvrf/v1.2/vuln}Status': Missing child element(s). Expected is ( {http://docs.oasis-open.org/csaf/ns/csaf-cvrf/v1.2/vuln}ProductID ). (<string>, line 0).
100 examples OK - took first 100 files from the batch and all of them were valid, no errors.
5 examples OK - Haven't found any "browsing" page for Siemens CVRFs, managed to google a few examples, all of them valid, no errors.
3 examples with CRITICAL - wrong cvrfdoc namespace used
2022-02-28 17:13:30,646 - cvrf2csaf - ERROR - Errors during input validation occurred, reason(s): [git/CVRF-CSAF-Converter/examples/examples_oracle/cpujan2022cvrf.xml:4:0:ERROR:SCHEMASV:SCHEMAV_CVC_ELT_1: Element '{http://www.icasi.org/CVRF/schema/cvrf/1.1}cvrfdoc': No matching global declaration available for the validation root.].
2022-02-28 17:13:30,646 - utils - CRITICAL - Input document not valid, reason(s).
Just to have a clear logging scheme, I propose these log-level meanings:
@tschmidtb51 would you agree? Do you have an idea for use-case for Errors?
A "first-level" validation for validating the output is verifying that it's compliant with the CSAF JSON schema.
The validation comes right before saving the output to a file, and:
Valid -> logging INFO
Invalid -> logging ERROR (writing into a file depends on the --force
option, this will be implemented when handling --force
in general)
Create a Python package (setup.py, setup.cfg) for installation/distribution
EPIC: #10
[Oasis v1.2 -> 4.6 Document Notes]http://docs.oasis-open.org/csaf/csaf-cvrf/v1.2/cs01/csaf-cvrf-v1.2-cs01.html#_Toc493508888)
Field Definition 3.1.5 Notes Type
-- no new elements
-- no changed elements
| /document/notes
| /cvrf:cvrfdoc/cvrf:DocumentNotes
| |
| /document/notes[i]
| /cvrf:cvrfdoc/cvrf:DocumentNotes/cvrf:Note[i+1]
| |
| /document/notes[i]/audience
| /cvrf:cvrfdoc/cvrf:DocumentNotes/cvrf:Note[i+1]/@Audience
| |
| /document/notes[i]/category
| /cvrf:cvrfdoc/cvrf:DocumentNotes/cvrf:Note[i+1]/@Type
| |
| /document/notes[i]/text
| /cvrf:cvrfdoc/cvrf:DocumentNotes/cvrf:Note[i+1]/text()
| |
| /document/notes[]/title
| /cvrf:cvrfdoc/cvrf:DocumentNotes/cvrf:Note[i+1]/@Title
| |
- CSAF producers SHOULD NOT emit messages that contain HTML, even though all variants of Markdown permit it. To include HTML, source code, or any other content that may be interpreted or executed by a CSAF consumer, e.g. to provide a proof-of-concept, the issuing party SHALL use Markdown's fenced code blocks or inline code option.
Source: Safety, Security, and Data Protection Considerations
A/C:
As a very first test, we would like to convert Document Publisher
alone from CVRF 1.2 to CSAF, by establishing a general read / write workflow.
cvrf2csaf.py
(argparse
)Document Publisher
)Suggest for spring cleaning to handle the finding
flake8 →
cvrf2csaf/cvrf2csaf.py:40:92: W605 invalid escape sequence '\.'
cvrf2csaf/cvrf2csaf.py:40:95: W605 invalid escape sequence '\-'
cvrf2csaf/cvrf2csaf.py:73:35: W605 invalid escape sequence '\.'
cvrf2csaf/section_handlers/vulnerability.py:162:35: W605 invalid escape sequence '\.'
cvrf2csaf/section_handlers/vulnerability.py:170:29: W605 invalid escape sequence '\.'
Just prefixing the string literals with an r
should work
Adding a second backslash \
→ \\
(making the combination a valid backslash escape) works also, but who would want to do that 😉 ...?
As part of #3, we already integrated a 1-to-1 mapping between a flat XML element (DocumentPublisher
).
Here, we would go into the first recursive conversion: DocumentTracking
This will provide us the code basis to go over other recursive sections in the further project one by one.
Smelling copy-pasta-search-replace (CPSR) with a failed R step 😉
def handle_boolean_config_values(key, val):
try:
if isinstance(val, bool):
return val
if val.strip().lower() in {'true', 'yes', '1', 'y'}:
return True
if val.strip().lower() in {'false', 'no', '0', 'n'}:
return False
critical_exit(f"Reading config.yaml failed. "
f"Invalid value for config key {key}: {val}. {e}.")
except Exception as e:
critical_exit(f"Reading config.yaml failed. "
f"Invalid value for config key {key}: {val} {e}.")
Problem:
>>> import cvrf2csaf.common.utils as bomb
>>> bomb.handle_boolean_config_values('whatever', 'bomb')
2022-03-12 02:14:48,332 - utils - CRITICAL - Reading config.yaml failed. Invalid value for config key whatever: bomb local variable 'e' referenced before assignment.
Suggest to handle the finding
flake8 → cvrf2csaf/common/utils.py:29:69: F821 undefined name 'e'
Minimal fix:
f"Invalid value for config key {key}: {val}. {e}."
with:
f"Invalid value for config key {key}: {val}."
Real (assuming here) fix would be to not care if a type was wrong (where the .strip()
would cause an exception) but simply raise a subsequently handled exception after the if-elif-elif dispatch for any "survivors" and reuse the logging call in the exception handler.
Example implementation:
Narrowing the Exception
down to an AttributeError
and injecting a ValueError
if we fall off the normal handling in a soft way should just work fine. So what about:
def handle_boolean_config_values(key, val):
"""Translate boolean like values to boolean or initiate exit."""
try:
if isinstance(val, bool):
return val
if val.strip().lower() in {'true', 'yes', '1', 'y'}:
return True
if val.strip().lower() in {'false', 'no', '0', 'n'}:
return False
raise ValueError("unexpected value")
except (AttributeError, ValueError) as err:
critical_exit(f"Reading config.yaml failed. Invalid value for config key {key}: {val} {err}.")
Short test:
>>> import spike # Sorry, the above function as is in spike.py plus critical_exit = print
>>> spike.handle_boolean_config_values(42, "12")
Reading config.yaml failed. Invalid value for config key 42: 12 unexpected value.
As there was some confusion in #21 (unfortunately caused by a misunderstanding), I try to sketch the expected behavior as a new issue:
fix_current_version_not_in_revision_history
(feel free to choose a different name) has the default value false
. When it is set to true
, the converter adds the current version in the revision history if it is missing (independently whether the previous version exists) and adds a warning that the current version was not in the revision history and was added and that this might impact the revision history's integrity.This requires the following changes:
--force-update-revision-history
as it is not intuitive. When I read --force-update-revision-history
I would expect that this option updates any revision history (independently whether valid before or invalid as e.g. A, B, C) to a valid integer versioning.quick-fixes
for recommended actions if one of the tests from section 6 fails. That's why I came up with fix_current_version_not_in_revision_history
. However, I'm also happy with a --force~
if it conveys that it adds only the current version if it is missing.CVRF-CSAF-Converter/cvrf2csaf/section_handlers/document_tracking.py
Lines 79 to 91 in 3fef149
if fix_current_version_not_in_revision_history is True:
logging.warning('Forcing update of the revision history and adding the current version. '
'This may lead to inconsistent history.')
else:
logging.error('Current version is missing in revision history. '
'This can be fixed by using --fix_current_version_not_in_revision_history')
return
Points to discuss :
1) How to distribute the config file? For now it's inside the package, shall we put it inside /etc/
, /usr/local/share
or some other path?
2) Usage through CLI command is now possible, shall it be also possible to use it as a python module? (e.g. import cvrf2csaf; cvrf2csaf.convert(...))
Originally posted by @sustefil in #23 (comment)
Suggest to replace
Assure that you have Python 3 installed.
in README.md with the presumably intended
Ensure that you have Python 3 installed.
I am guessing here, but:
Assure:
removing doubt (or attempting to) from someone’s mind
Ensure:
to make sure, certain, or safe.
Part of EPIC #10. From bigger recursive section #26.
Sub Issues:
branches
-> #31full_product_name
-> OPENproduct_groups
-> OPENrelationships
-> OPEN(yes - recursion!)
Oasis v1.2 -> 2.2.3 Product Branch Type Model
Oasis v1.2 -> Integration into higher level ProductTree leaf-> 5.1.1 Product Tree – Branch
Field definitions 3.1.2 Branches Type
-- no new elements
| `/product_tree/branches` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch` | |
| `/product_tree/branches[i]` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]` | |
| `/product_tree/branches[i]/branches` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch` | |
| `/product_tree/branches[i]/branches[j]` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]` | |
| `/product_tree/branches[i]/branches[j]/branches` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch` | |
| `/product_tree/branches[i]/branches[j]/branches[k]` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/branches` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/prod:Branch` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/branches[l]` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/prod:Branch[l+1]` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/branches[l]/category` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/prod:Branch[l+1]/@Type` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/branches[l]/name` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/prod:Branch[l+1]/@Name` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/category` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/@Type` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/name` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/@Name` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/product` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/prod:FullProductName` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/name` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/prod:FullProductName/text()` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_id` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/prod:FullProductName/@ProductID` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_identification_helper` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_identification_helper/cpe` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:Branch[k+1]/prod:FullProductName/@CPE` | |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_identification_helper/hashes` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_identification_helper/purl` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_identification_helper/sbom_urls` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_identification_helper/serial_numbers` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_identification_helper/skus` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/branches[k]/product/product_identification_helper/x_generic_uris` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/category` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/@Type` | |
| `/product_tree/branches[i]/branches[j]/name` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/@Name` | |
| `/product_tree/branches[i]/branches[j]/product` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:FullProductName` | |
| `/product_tree/branches[i]/branches[j]/product/name` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:FullProductName/text()` | |
| `/product_tree/branches[i]/branches[j]/product/product_id` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:FullProductName/@ProductID` | |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/cpe` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:Branch[j+1]/prod:FullProductName/@CPE` | |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/hashes` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/hashes[]` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/hashes[]/file_hashes` | | see parent |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/hashes[]/filename` | | see parent |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/purl` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/sbom_urls` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/sbom_urls[]` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/serial_numbers` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/serial_numbers[]` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/skus` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/skus[]` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/x_generic_uris` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/x_generic_uris[]` | | see E.1 |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/x_generic_uris[]/namespace` | | see parent |
| `/product_tree/branches[i]/branches[j]/product/product_identification_helper/x_generic_uris[]/uri` | | see parent |
| `/product_tree/branches[i]/category` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/@Type` | |
| `/product_tree/branches[i]/name` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/@Name` | |
| `/product_tree/branches[i]/product` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:FullProductName` | |
| `/product_tree/branches[i]/product/name` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:FullProductName/text()` | |
| `/product_tree/branches[i]/product/product_id` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:FullProductName/@ProductID` | |
| `/product_tree/branches[i]/product/product_identification_helper` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/cpe` | `/cvrf:cvrfdoc/prod:ProductTree/prod:Branch[i+1]/prod:FullProductName/@CPE` | |
| `/product_tree/branches[i]/product/product_identification_helper/hashes` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/hashes[]` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/hashes[]/file_hashes` | | see parent |
| `/product_tree/branches[i]/product/product_identification_helper/hashes[]/file_hashes[]` | | see parent |
| `/product_tree/branches[i]/product/product_identification_helper/hashes[]/file_hashes[]/algorithm` | | see parent |
| `/product_tree/branches[i]/product/product_identification_helper/hashes[]/file_hashes[]/value` | | see parent |
| `/product_tree/branches[i]/product/product_identification_helper/hashes[]/filename` | | see parent |
| `/product_tree/branches[i]/product/product_identification_helper/purl` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/sbom_urls` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/sbom_urls[]` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/serial_numbers` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/serial_numbers[]` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/skus` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/skus[]` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/x_generic_uris` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/x_generic_uris[]` | | see E.1 |
| `/product_tree/branches[i]/product/product_identification_helper/x_generic_uris[]/namespace` | | see parent |
| `/product_tree/branches[i]/product/product_identification_helper/x_generic_uris[]/uri` | | see parent |
Suggest for spring cleaning to handle the finding
flake8 → cvrf2csaf/cvrf2csaf.py:153:9: F841 local variable 'e' is assigned to but never used
Just replace:
except etree.DocumentInvalid as e:
with:
except etree.DocumentInvalid:
The conformance clause 5: CVRF CSAF converter states the conversion rule for the document language:
/document/lang
: If one or more CVRF element containing anxml:lang
attribute exist and contain the exact same value, the CVRF CSAF converter converts this value intolang
. If the values ofxml:lang
attributes are not equal, the CVRF CSAF converter outputs a warning that the language could not be determined and possibly a document with multiple languages was produced. In addition, it SHOULD also present all values ofxml:lang
attributes as a set in the warning.
This must be implemented in the CVRF-CSAF converter to be conformant.
The xs:date type in Secvisogram looks like this:
"date": "2021-12-10T08:28:32.996Z"
Python doesn't have support for military time-zones (Z at the end, indicating UTC), so we can either:
Use native Python function, producing this format:
datetime.now(timezone.utc).isoformat(timespec='milliseconds')
'2021-12-10T09:05:47.966+00:00'
Use the same function, but also replace the string +00:00 with Z
The README currently lacks the sections Developer Guide, Architecture and Technical Design and Security Considerations. Those should be added.
Researching for a complete changelog between CVRF 1.2 and CSAF 2.0, we could not find a complete list.
Therefore, we asked in Oasis TCS CSAF project for it and sthagen reported back, that currently there is no such complete change log. However, there is a prelimary mapping which will slightly change over time (CS01), but looks to be the best changelog publicy available.
As this is a moving target, we will check back later if we covered all changes during the converter implementation.
Part of EPIC #10
/product_tree/*/product/product_identification_helper
: Provides at least one method which aids in identifying the product in an asset database. It was introduced to group different ways to identify a product//product_tree/*/product/product_identification_helper/hashes
: Contains a list of cryptographic hashes usable to identify files./product_tree/*/product/product_identification_helper/purl
: The package URL (purl) attribute refers to a method for reliably identifying and locating software packages external to this specification./product_tree/*/product/product_identification_helper/sbom_urls
: Contains a list of URLs where SBOMs for this product can be retrieved./product_tree/*/product/product_identification_helper/serial_numbers
: Contains a list of parts, or full serial numbers./product_tree/*/product/product_identification_helper/skus
: Contains a list of parts, or full stock keeping units./product_tree/*/product/product_identification_helper/x_generic_uris
: Contains a list of identifiers which are either vendor-specific or derived from a standard not yet supported.Around 130 element changes are documented --> /cvrf:cvrfdoc/prod:ProductTree
/product_tree/relationships[]
: If more than one prod:FullProductName
instance is given, the CVRF CSAF converter converts the first one into the full_product_name. In addition, the converter outputs a warning that information might be lost during conversion of product relationships. quoted here
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.