From a1ea10baf9bb2325781383aa34c9f16ae1abbfd3 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Fri, 1 Sep 2023 20:14:18 +0200 Subject: [PATCH 01/24] feat: added model for a CSAF advisory --- csaf/advisory.go | 1038 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1038 insertions(+) create mode 100644 csaf/advisory.go diff --git a/csaf/advisory.go b/csaf/advisory.go new file mode 100644 index 0000000..dc73902 --- /dev/null +++ b/csaf/advisory.go @@ -0,0 +1,1038 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) +// Software-Engineering: 2023 Intevation GmbH + +package csaf + +import ( + "encoding/json" + "io" + "os" +) + +// Acknowledgement reflects the 'acknowledgement' object in the list of acknowledgements. +// It must at least have one property. +type Acknowledgement struct { + Names []*string `json:"names,omitempty"` + Organization *string `json:"organization,omitempty"` + Summary *string `json:"summary,omitempty"` + URLs []*string `json:"urls,omitempty"` +} + +// BranchCategory is the category of a branch. +type BranchCategory string + +const ( + // CSAFBranchCategoryArchitecture is the "architecture" category. + CSAFBranchCategoryArchitecture BranchCategory = "architecture" + // CSAFBranchCategoryHostName is the "host_name" category. + CSAFBranchCategoryHostName BranchCategory = "host_name" + // CSAFBranchCategoryLanguage is the "language" category. + CSAFBranchCategoryLanguage BranchCategory = "language" + // CSAFBranchCategoryLegacy is the "legacy" category. + CSAFBranchCategoryLegacy BranchCategory = "legacy" + // CSAFBranchCategoryPatchLevel is the "patch_level" category. + CSAFBranchCategoryPatchLevel BranchCategory = "patch_level" + // CSAFBranchCategoryProductFamily is the "product_family" category. + CSAFBranchCategoryProductFamily BranchCategory = "product_family" + // CSAFBranchCategoryProductName is the "product_name" category. + CSAFBranchCategoryProductName BranchCategory = "product_name" + // CSAFBranchCategoryProductVersion is the "product_version" category. + CSAFBranchCategoryProductVersion BranchCategory = "product_version" + // CSAFBranchCategoryProductVersionRange is the "product_version_range" category. + CSAFBranchCategoryProductVersionRange BranchCategory = "product_version_range" + // CSAFBranchCategoryServicePack is the "service_pack" category. + CSAFBranchCategoryServicePack BranchCategory = "service_pack" + // CSAFBranchCategorySpecification is the "specification" category. + CSAFBranchCategorySpecification BranchCategory = "specification" + // CSAFBranchCategoryVendor is the "vendor" category. + CSAFBranchCategoryVendor BranchCategory = "vendor" +) + +var csafBranchCategoryPattern = alternativesUnmarshal( + string(CSAFBranchCategoryArchitecture), + string(CSAFBranchCategoryHostName), + string(CSAFBranchCategoryLanguage), + string(CSAFBranchCategoryLegacy), + string(CSAFBranchCategoryPatchLevel), + string(CSAFBranchCategoryProductFamily), + string(CSAFBranchCategoryProductName), + string(CSAFBranchCategoryProductVersion), + string(CSAFBranchCategoryProductVersionRange), + string(CSAFBranchCategoryServicePack), + string(CSAFBranchCategorySpecification), + string(CSAFBranchCategoryVendor)) + +// ProductID is a reference token for product instances. There is no predefined or +// required format for it as long as it uniquely identifies a product in the context +// of the current document. +type ProductID string + +// Products is a list of one or more unique ProductID elements. +type Products []ProductID + +// FileHashValue represents the value of a hash. +type FileHashValue string + +var FileHashValuePattern = patternUnmarshal(`^[0-9a-fA-F]{32,}$`) + +// FileHash is checksum hash. +// Values for 'algorithm' are derived from the currently supported digests OpenSSL. Leading dashes were removed. +type FileHash struct { + Algorithm string `json:"algorithm"` // required, default: sha256 + Value string `json:"value"` // required +} + +// Hashes is a list of hashes. +type Hashes struct { + FileHashes []FileHash `json:"file_hashes"` // required + FileName string `json:"filename"` // required +} + +// CPE represents a Common Platform Enumeration in an advisory. +type CPE string + +var CPEPattern = patternUnmarshal("^(cpe:2\\.3:[aho\\*\\-](:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#\\$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|\\}~]))+(\\?*|\\*?))|[\\*\\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\\*\\-]))(:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#\\$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|\\}~]))+(\\?*|\\*?))|[\\*\\-])){4})|([c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6})$") + +// PURL represents a package URL in an advisory. +type PURL string + +var PURLPattern = patternUnmarshal(`^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*/.+`) + +// XGenericURI represents an identifier for a product. +type XGenericURI struct { + Namespace string `json:"namespace"` // required + URI string `json:"uri"` // required +} + +// ProductIdentificationHelper bundles product identifier information. +// Supported formats for SBOMs are SPDX, CycloneDX, and SWID +type ProductIdentificationHelper struct { + CPE *CPE `json:"cpe,omitempty"` + Hashes *Hashes `json:"hashes,omitempty"` + ModelNumbers []*string `json:"model_numbers,omitempty"` // unique elements + PURL *PURL `json:"purl,omitempty"` + SBOMURLs []*string `json:"sbom_urls,omitempty"` + SerialNumbers []*string `json:"serial_numbers,omitempty"` // unique elements + SKUs []*string `json:"skus,omitempty"` + XGenericURIs []*XGenericURI `json:"x_generic_uris,omitempty"` +} + +// FullProductName is the full name of a product. +type FullProductName struct { + Name string `json:"name"` // required + ProductID ProductID `json:"product_id"` // required + ProductIdentificationHelper *ProductIdentificationHelper `json:"product_identification_helper,omitempty"` +} + +// Branch reflects the 'branch' object in the list of branches. +// It may contain either the property Branches OR Product. +// If the category is 'product_version' the name MUST NOT contain +// version ranges of any kind. +// If the category is 'product_version_range' the name MUST contain +// version ranges. +type Branch struct { + Branches []*Branch `json:"branches,omitempty"` + Category BranchCategory `json:"category"` // required + Name string `json:"name"` // required + Product *FullProductName `json:"product,omitempty"` +} + +// NoteCategory is the category of a note. +type NoteCategory string + +const ( + // CSAFNoteCategoryDescription is the "description" category. + CSAFNoteCategoryDescription NoteCategory = "description" + // CSAFNoteCategoryDetails is the "details" category. + CSAFNoteCategoryDetails NoteCategory = "details" + // CSAFNoteCategoryFaq is the "faq" category. + CSAFNoteCategoryFaq NoteCategory = "faq" + // CSAFNoteCategoryGeneral is the "general" category. + CSAFNoteCategoryGeneral NoteCategory = "general" + // CSAFNoteCategoryLegalDisclaimer is the "legal_disclaimer" category. + CSAFNoteCategoryLegalDisclaimer NoteCategory = "legal_disclaimer" + // CSAFNoteCategoryOther is the "other" category. + CSAFNoteCategoryOther NoteCategory = "other" + // CSAFNoteCategorySummary is the "summary" category. + CSAFNoteCategorySummary NoteCategory = "summary" +) + +var csafNoteCategoryPattern = alternativesUnmarshal( + string(CSAFNoteCategoryDescription), + string(CSAFNoteCategoryDetails), + string(CSAFNoteCategoryFaq), + string(CSAFNoteCategoryGeneral), + string(CSAFNoteCategoryLegalDisclaimer), + string(CSAFNoteCategoryOther), + string(CSAFNoteCategorySummary)) + +// Note reflects the 'Note' object of an advisory. +type Note struct { + Audience string `json:"audience,omitempty"` + NoteCategory *NoteCategory `json:"category"` // required + Text *string `json:"text"` // required + Title string `json:"title,omitempty"` +} + +// ReferenceCategory is the category of a note. +type ReferenceCategory string + +const ( + // CSAFReferenceCategoryExternal is the "external" category. + CSAFReferenceCategoryExternal ReferenceCategory = "external" + // CSAFReferenceCategorySelf is the "self" category. + CSAFReferenceCategorySelf ReferenceCategory = "self" +) + +var csafReferenceCategoryPattern = alternativesUnmarshal( + string(CSAFReferenceCategoryExternal), + string(CSAFReferenceCategorySelf)) + +// Reference holding any reference to conferences, papers, advisories, and other +// resources that are related and considered related to either a surrounding part of +// or the entire document and to be of value to the document consumer. +type Reference struct { + ReferenceCategory *string `json:"category"` // optional, default: external + Summary string `json:"summary"` // required + URL string `json:"url"` // required +} + +// AggregateSeverity stands for the urgency with which the vulnerabilities of an advisory +// (not a specific one) should be addressed. +type AggregateSeverity struct { + Namespace *string `json:"namespace,omitempty"` + Text string `json:"text"` // required +} + +// DocumentCategory represents a category of a document. +type DocumentCategory string + +var DocumentCategoryPattern = patternUnmarshal(`^[^\\s\\-_\\.](.*[^\\s\\-_\\.])?$`) + +// CSAFVersion is the version of a document. +type CSAFVersion string + +// CSAFVersion is the current version of CSAF. +const CSAFVersion20 CSAFVersion = "2.0" + +var CSAFVersionPattern = alternativesUnmarshal(string(CSAFVersion20)) + +// DocumentTLPLabel is the label of a TLP. +type DocumentTLPLabel string + +const ( + // DocumentTLPLabelAmber is the "AMBER" label. + DocumentTLPLabelAmber DocumentTLPLabel = "AMBER" + // DocumentTLPLabelGreen is the "GREEN" label. + DocumentTLPLabelGreen DocumentTLPLabel = "GREEN" + // DocumentTLPLabelRed is the "RED" label. + DocumentTLPLabelRed DocumentTLPLabel = "RED" + // DocumentTLPLabelWhite is the "WHITE" label. + DocumentTLPLabelWhite DocumentTLPLabel = "WHITE" +) + +var csafDocumentTLPLabelPattern = alternativesUnmarshal( + string(DocumentTLPLabelAmber), + string(DocumentTLPLabelGreen), + string(DocumentTLPLabelRed), + string(DocumentTLPLabelWhite)) + +// TLP provides details about the TLP classification of the document. +type TLP struct { + DocumentTLPLabel DocumentTLPLabel `json:"label"` // required + URL *string `json:"url,omitempty"` +} + +// DocumentDistribution describes rules for sharing a document. +type DocumentDistribution struct { + Text *string `json:"text,omitempty"` + TLP *TLP `json:"tlp,omitempty"` +} + +// PublisherCategory is the category of a publisher. +type PublisherCategory string + +const ( + // CSAFPublisherCategoryCoordinator is the "coordinator" category. + CSAFPublisherCategoryCoordinator PublisherCategory = "coordinator" + // CSAFPublisherCategoryDiscoverer is the "discoverer" category. + CSAFPublisherCategoryDiscoverer PublisherCategory = "discoverer" + // CSAFPublisherCategoryOther is the "other" category. + CSAFPublisherCategoryOther PublisherCategory = "other" + // CSAFPublisherCategoryTranslator is the "translator" category. + CSAFPublisherCategoryTranslator PublisherCategory = "translator" + // CSAFPublisherCategoryUser is the "user" category. + CSAFPublisherCategoryUser PublisherCategory = "user" + // CSAFPublisherCategoryVendor is the "vendor" category. + CSAFPublisherCategoryVendor PublisherCategory = "vendor" +) + +var csafPublisherCategoryPattern = alternativesUnmarshal( + string(CSAFPublisherCategoryCoordinator), + string(CSAFPublisherCategoryDiscoverer), + string(CSAFPublisherCategoryOther), + string(CSAFPublisherCategoryTranslator), + string(CSAFPublisherCategoryUser), + string(CSAFPublisherCategoryVendor)) + +// DocumentPublisher provides information about the publishing entity. +type DocumentPublisher struct { + Category PublisherCategory `json:"category"` // required + ContactDetails *string `json:"contact_details,omitempty"` + IssuingAuthority *string `json:"issuing_authority,omitempty"` + Name string `json:"name"` // required + Namespace string `json:"namespace"` // required +} + +// The version specifies a version string to denote clearly the evolution of the content of the document. +type Version string + +var VersionPattern = patternUnmarshal(`^(0|[1-9][0-9]*)$|^((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*) + (?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)$`) + +// Engine contains information about the engine that generated the CSAF document. +type Engine struct { + Name string `json:"name"` // required + Version *string `json:"version,omitempty"` +} + +// Generator holds elements related to the generation of the document. +// These items will reference when the document was actually created, +// including the date it was generated and the entity that generated it. +type Generator struct { + Date *string `json:"date,omitempty"` + Engine Engine `json:"engine"` // required +} + +// TrackingID is a unique identifier for the document. +type TrackingID string + +var TrackingIDPattern = patternUnmarshal("^[\\S](.*[\\S])?$") + +// Revision contains information about one revision of the document. +type Revision struct { + Date string `json:"date"` // required + LegacyVersion *string `json:"legacy_version,omitempty"` + Number Version `json:"number"` // required + Summary string `json:"summary"` // required +} + +// TrackingStatus is the category of a publisher. +type TrackingStatus string + +const ( + // CSAFTrackingStatusDraft is the "draft" category. + CSAFTrackingStatusDraft TrackingStatus = "draft" + // CSAFTrackingStatusFinal is the "final" category. + CSAFTrackingStatusFinal TrackingStatus = "final" + // CSAFTrackingStatusInterim is the "interim" category. + CSAFTrackingStatusInterim TrackingStatus = "interim" +) + +var csafTrackingStatusPattern = alternativesUnmarshal( + string(CSAFTrackingStatusDraft), + string(CSAFTrackingStatusFinal), + string(CSAFTrackingStatusInterim)) + +// Tracking holds information that is necessary to track a CSAF document. +type Tracking struct { + Aliases []*string `json:"aliases,omitempty"` // unique elements + CurrentReleaseDate string `json:"current_release_date"` // required + Generator *Generator `json:"generator"` + ID TrackingID `json:"id"` // required + InitialReleaseDate string `json:"initial_release_date"` // required + RevisionHistory []Revision `json:"revision_history"` // required + Status TrackingStatus `json:"status"` // required + Version Version `json:"version"` // required +} + +// Lang is a language identifier, corresponding to IETF BCP 47 / RFC 5646. +type Lang string + +var LangPattern = patternUnmarshal("^(([A-Za-z]{2,3}(-[A-Za-z]{3}(-[A-Za-z]{3}){0,2})?|[A-Za-z]{4,8})(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-[A-WY-Za-wy-z0-9](-[A-Za-z0-9]{2,8})+)*(-[Xx](-[A-Za-z0-9]{1,8})+)?|[Xx](-[A-Za-z0-9]{1,8})+|[Ii]-[Dd][Ee][Ff][Aa][Uu][Ll][Tt]|[Ii]-[Mm][Ii][Nn][Gg][Oo])$") + +// Document contains meta-data about an advisory. +type Document struct { + Acknowledgements []Acknowledgement `json:"acknowledgements,omitempty"` + AggregateSeverity *AggregateSeverity `json:"aggregate_severity,omitempty"` + Category DocumentCategory `json:"category"` // required + CSAFVersion CSAFVersion `json:"csaf_version"` // required + Distribution *DocumentDistribution `json:"distribution,omitempty"` + Lang *Lang `json:"lang,omitempty"` + Notes []*Note `json:"notes,omitempty"` + Publisher DocumentPublisher `json:"publisher"` // required + References []*Reference `json:"references,omitempty"` + SourceLang *Lang `json:"source_lang,omitempty"` + Title string `json:"title"` // required + Tracking Tracking `json:"tracking"` // required +} + +// ProductGroupID is a reference token for product group instances. +type ProductGroupID string + +// ProductGroup is a group of products in the document that belong to one group. +type ProductGroup struct { + GroupID string `json:"group_id"` // required + ProductIDs Products `json:"product_ids"` // required, two or more unique elements + Summary *string `json:"summary,omitempty"` +} + +// ProductGroups is a list of ProductGroupIDs +type ProductGroups struct { + ProductGroupIDs []ProductGroupID `json:"product_group_ids"` // unique elements +} + +// RelationshipCategory is the category of a relationship. +type RelationshipCategory string + +const ( + // CSAFRelationshipCategoryDefaultComponentOf is the "default_component_of" category. + CSAFRelationshipCategoryDefaultComponentOf RelationshipCategory = "default_component_of" + // CSAFRelationshipCategoryExternalComponentOf is the "external_component_of" category. + CSAFRelationshipCategoryExternalComponentOf RelationshipCategory = "external_component_of" + // CSAFRelationshipCategoryInstalledOn is the "installed_on" category. + CSAFRelationshipCategoryInstalledOn RelationshipCategory = "installed_on" + // CSAFRelationshipCategoryInstalledWith is the "installed_with" category. + CSAFRelationshipCategoryInstalledWith RelationshipCategory = "installed_with" + // CSAFRelationshipCategoryOptionalComponentOf is the "optional_component_of" category. + CSAFRelationshipCategoryOptionalComponentOf RelationshipCategory = "optional_component_of" +) + +var csafRelationshipCategoryPattern = alternativesUnmarshal( + string(CSAFRelationshipCategoryDefaultComponentOf), + string(CSAFRelationshipCategoryExternalComponentOf), + string(CSAFRelationshipCategoryInstalledOn), + string(CSAFRelationshipCategoryInstalledWith), + string(CSAFRelationshipCategoryOptionalComponentOf)) + +// Relationship establishes a link between two existing FullProductName elements. +type Relationship struct { + Category RelationshipCategory `json:"category"` // required + FullProductName FullProductName `json:"full_product_name"` // required + ProductReference ProductID `json:"product_reference"` // required + RelatesToProductReference ProductID `json:"relates_to_product_reference"` // required + +} + +// ProductTree contains product names that can be referenced elsewhere in the document. +type ProductTree struct { + Branches []*Branch `json:"branches,omitempty"` + FullProductNames []*FullProductName `json:"full_product_name,omitempty"` + ProductGroups *ProductGroups `json:"product_groups,omitempty"` + RelationShips []*Relationship `json:"relationships,omitempty"` +} + +// CVE holds the MITRE standard Common Vulnerabilities and Exposures (CVE) tracking number for a vulnerability. +type CVE string + +var CVEPattern = patternUnmarshal("^CVE-[0-9]{4}-[0-9]{4,}$") + +// WeaknessID is the identifier of a weakness. +type WeaknessID string + +var WeaknessIDPattern = patternUnmarshal("^CWE-[1-9]\\d{0,5}$") + +// CWE holds the MITRE standard Common Weakness Enumeration (CWE) for the weakness associated. +type CWE struct { + ID WeaknessID `json:"id"` // required + Name string `json:"name"` // required +} + +// FlagLabel is the label of a flag for a vulnerability. +type FlagLabel string + +const ( + // CSAFFlagLabelComponentNotPresent is the "component_not_present" label. + CSAFFlagLabelComponentNotPresent FlagLabel = "component_not_present" + // CSAFFlagLabelInlineMitigationsAlreadyExist is the "inline_mitigations_already_exist" label. + CSAFFlagLabelInlineMitigationsAlreadyExist FlagLabel = "inline_mitigations_already_exist" + // CSAFFlagLabelVulnerableCodeCannotBeControlledByAdversary is the "vulnerable_code_cannot_be_controlled_by_adversary" label. + CSAFFlagLabelVulnerableCodeCannotBeControlledByAdversary FlagLabel = "vulnerable_code_cannot_be_controlled_by_adversary" + // CSAFFlagLabelVulnerableCodeNotInExecutePath is the "vulnerable_code_not_in_execute_path" label. + CSAFFlagLabelVulnerableCodeNotInExecutePath FlagLabel = "vulnerable_code_not_in_execute_path" + // CSAFFlagLabelVulnerableCodeNotPresent is the "vulnerable_code_not_present" label. + CSAFFlagLabelVulnerableCodeNotPresent FlagLabel = "vulnerable_code_not_present" +) + +var csafFlagLabelPattern = alternativesUnmarshal( + string(CSAFFlagLabelComponentNotPresent), + string(CSAFFlagLabelInlineMitigationsAlreadyExist), + string(CSAFFlagLabelVulnerableCodeCannotBeControlledByAdversary), + string(CSAFFlagLabelVulnerableCodeNotInExecutePath), + string(CSAFFlagLabelVulnerableCodeNotPresent)) + +// Flag contains product specific information in regard to this vulnerability as a single +// machine readable flag. For example, this could be a machine readable justification +// code why a product is not affected. +type Flag struct { + Date *string `json:"date,omitempty"` + GroupIds *ProductGroups `json:"group_ids,omitempty"` + Label FlagLabel `json:"label"` // required + ProductIds *Products `json:"product_ids,omitempty"` +} + +// VulnerabilityID is the identifier of a vulnerability. +type VulnerabilityID struct { + SystemName string `json:"system_name"` // required + Text string `json:"text"` // required +} + +// InvolvementParty is the party of an involvement. +type InvolvementParty string + +const ( + // CSAFInvolvementPartyCoordinator is the "coordinator" party. + CSAFInvolvementPartyCoordinator InvolvementParty = "coordinator" + // CSAFInvolvementPartyDiscoverer is the "discoverer" party. + CSAFInvolvementPartyDiscoverer InvolvementParty = "discoverer" + // CSAFInvolvementPartyOther is the "other" party. + CSAFInvolvementPartyOther InvolvementParty = "other" + // CSAFInvolvementPartyUser is the "user" party. + CSAFInvolvementPartyUser InvolvementParty = "user" + // CSAFInvolvementPartyVendor is the "vendor" party. + CSAFInvolvementPartyVendor InvolvementParty = "vendor" +) + +var csafInvolvementPartyPattern = alternativesUnmarshal( + string(CSAFInvolvementPartyCoordinator), + string(CSAFInvolvementPartyDiscoverer), + string(CSAFInvolvementPartyOther), + string(CSAFInvolvementPartyUser), + string(CSAFInvolvementPartyVendor)) + +// InvolvementStatus is the status of an involvement. +type InvolvementStatus string + +const ( + // CSAFInvolvementStatusCompleted is the "completed" status. + CSAFInvolvementStatusCompleted InvolvementStatus = "completed" + // CSAFInvolvementStatusContactAttempted is the "contact_attempted" status. + CSAFInvolvementStatusContactAttempted InvolvementStatus = "contact_attempted" + // CSAFInvolvementStatusDisputed is the "disputed" status. + CSAFInvolvementStatusDisputed InvolvementStatus = "disputed" + // CSAFInvolvementStatusInProgress is the "in_progress" status. + CSAFInvolvementStatusInProgress InvolvementStatus = "in_progress" + // CSAFInvolvementStatusNotContacted is the "not_contacted" status. + CSAFInvolvementStatusNotContacted InvolvementStatus = "not_contacted" + // CSAFInvolvementStatusOpen is the "open" status. + CSAFInvolvementStatusOpen InvolvementStatus = "open" +) + +var csafInvolvementStatusPattern = alternativesUnmarshal( + string(CSAFInvolvementStatusCompleted), + string(CSAFInvolvementStatusContactAttempted), + string(CSAFInvolvementStatusDisputed), + string(CSAFInvolvementStatusInProgress), + string(CSAFInvolvementStatusNotContacted), + string(CSAFInvolvementStatusOpen)) + +// Involvement is a container that allows the document producers to comment on the level of involvement +// (or engagement) of themselves (or third parties) in the vulnerability identification, scoping, and +// remediation process. It can also be used to convey the disclosure timeline. +// The ordered tuple of the values of party and date (if present) SHALL be unique within the involvements +// of a vulnerability. +type Involvement struct { + Date *string `json:"date,omitempty"` + Party InvolvementParty `json:"party"` // required + Status InvolvementStatus `json:"status"` // required + Summary *string `json:"summary,omitempty"` +} + +// ProductStatus contains different lists of ProductIDs which provide details on +// the status of the referenced product related to the current vulnerability. +type ProductStatus struct { + FirstAffected *Products `json:"first_affected,omitempty"` + FirstFixed *Products `json:"first_fixed,omitempty"` + Fixed *Products `json:"fixed,omitempty"` + KnownAffected *Products `json:"known_affected,omitempty"` + KnownNotAffected *Products `json:"known_not_affected,omitempty"` + LastAffected *Products `json:"last_affected,omitempty"` + Recommended *Products `json:"recommended,omitempty"` + UnderInvestigation *Products `json:"under_investigation,omitempty"` +} + +// RemediationCategory is the category of a remediation. +type RemediationCategory string + +const ( + // CSAFRemediationCategoryMitigation is the "mitigation" category. + CSAFRemediationCategoryMitigation RemediationCategory = "mitigation" + // CSAFRemediationCategoryNoFixPlanned is the "no_fix_planned" category. + CSAFRemediationCategoryNoFixPlanned RemediationCategory = "no_fix_planned" + // CSAFRemediationCategoryNoneAvailable is the "none_available" category. + CSAFRemediationCategoryNoneAvailable RemediationCategory = "none_available" + // CSAFRemediationCategoryVendorFix is the "vendor_fix" category. + CSAFRemediationCategoryVendorFix RemediationCategory = "vendor_fix" + // CSAFRemediationCategoryWorkaround is the "workaround" category. + CSAFRemediationCategoryWorkaround RemediationCategory = "workaround" +) + +var csafRemediationCategoryPattern = alternativesUnmarshal( + string(CSAFRemediationCategoryMitigation), + string(CSAFRemediationCategoryNoFixPlanned), + string(CSAFRemediationCategoryNoneAvailable), + string(CSAFRemediationCategoryVendorFix), + string(CSAFRemediationCategoryWorkaround)) + +// RestartRequiredCategory is the category of RestartRequired. +type RestartRequiredCategory string + +const ( + // CSAFRestartRequiredCategoryConnected is the "connected" category. + CSAFRestartRequiredCategoryConnected RestartRequiredCategory = "connected" + // CSAFRestartRequiredCategoryDependencies is the "dependencies" category. + CSAFRestartRequiredCategoryDependencies RestartRequiredCategory = "dependencies" + // CSAFRestartRequiredCategoryMachine is the "machine" category. + CSAFRestartRequiredCategoryMachine RestartRequiredCategory = "machine" + // CSAFRestartRequiredCategoryNone is the "none" category. + CSAFRestartRequiredCategoryNone RestartRequiredCategory = "none" + // CSAFRestartRequiredCategoryParent is the "parent" category. + CSAFRestartRequiredCategoryParent RestartRequiredCategory = "parent" + // CSAFRestartRequiredCategoryService is the "service" category. + CSAFRestartRequiredCategoryService RestartRequiredCategory = "service" + // CSAFRestartRequiredCategorySystem is the "system" category. + CSAFRestartRequiredCategorySystem RestartRequiredCategory = "system" + // CSAFRestartRequiredCategoryVulnerableComponent is the "vulnerable_component" category. + CSAFRestartRequiredCategoryVulnerableComponent RestartRequiredCategory = "vulnerable_component" + // CSAFRestartRequiredCategoryZone is the "zone" category. + CSAFRestartRequiredCategoryZone RestartRequiredCategory = "zone" +) + +var csafRestartRequiredCategoryPattern = alternativesUnmarshal( + string(CSAFRestartRequiredCategoryConnected), + string(CSAFRestartRequiredCategoryDependencies), + string(CSAFRestartRequiredCategoryMachine), + string(CSAFRestartRequiredCategoryNone), + string(CSAFRestartRequiredCategoryParent), + string(CSAFRestartRequiredCategoryService), + string(CSAFRestartRequiredCategorySystem), + string(CSAFRestartRequiredCategoryVulnerableComponent), + string(CSAFRestartRequiredCategoryZone)) + +// RestartRequired provides information on category of restart is required by this remediation to become +// effective. +type RestartRequired struct { + Category RestartRequiredCategory `json:"category"` // required + Details *string `json:"details,omitempty"` +} + +// Remediation specifies details on how to handle (and presumably, fix) a vulnerability. +type Remediation struct { + Category *RemediationCategory `json:"category"` // required + Date *string `json:"date,omitempty"` + Details *string `json:"details"` // required + Entitlements []*string `json:"entitlements,omitempty"` + GroupIds *ProductGroups `json:"group_ids,omitempty"` + ProductIds *Products `json:"product_ids,omitempty"` + RestartRequired *RestartRequired `json:"restart_required,omitempty"` + URL *string `json:"url,omitempty"` +} + +// CVSSv3Version is the version of a CVSSv3 item. +type CVSSv3Version string + +// CVSSv3Version30 is version 3.0 of a CVSSv3 item. +const CVSSv3Version30 CVSSv3Version = "3.0" + +// CVSSv3Version31 is version 3.1 of a CVSSv3 item. +const CVSSv3Version31 CVSSv3Version = "3.1" + +// CVSSv3VectorString is the VectorString of a CVSSv3 item with version 3.x. +type CVSSv3VectorString string + +var CVSSv3VectorStringPattern = patternUnmarshal(`^CVSS:3[.][01]/((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])$`) + +var CVSSv3VersionPattern = alternativesUnmarshal( + string(CVSSv3Version30), + string(CVSSv3Version31)) + +// CVSSv2 holding a CVSS v2.0 value +type CVSSv2 struct { + Version string `json:"version"` // required + VectorString string `json:"vectorString"` // required + AccessVector *string `json:"accessVector"` + AccessComplexity *string `json:"accessComplexity"` + Authentication *string `json:"authentication"` + ConfidentialityImpact *string `json:"confidentialityImpact"` + IntegrityImpact *string `json:"integrityImpact"` + AvailabilityImpact *string `json:"availabilityImpact"` + BaseScore float64 `json:"baseScore"` // required + Exploitability *string `json:"exploitability"` + RemediationLevel *string `json:"remediationLevel"` + ReportConfidence *string `json:"reportConfidence"` + TemporalScore *string `json:"temporalScore"` + CollateralDamagePotential *string `json:"collateralDamagePotential"` + TargetDistribution *string `json:"targetDistribution"` + ConfidentialityRequirement *string `json:"confidentialityRequirement"` + IntegrityRequirement *string `json:"integrityRequirement"` + AvailabilityRequirement *string `json:"availabilityRequirement"` + EnvironmentalScore *string `json:"environmentalScore"` +} + +// CVSSv3 holding a CVSS v3.x value +type CVSSv3 struct { + Version string `json:"version"` // required + VectorString string `json:"vectorString"` // required + AttackVector *string `json:"attackVector"` + AttackComplexity *string `json:"attackComplexity"` + PrivilegesRequired *string `json:"privilegesRequired"` + UserInteraction *string `json:"userInteraction"` + Scope *string `json:"scope"` + ConfidentialityImpact *string `json:"confidentialityImpact"` + IntegrityImpact string `json:"integrityImpact"` + AvailabilityImpact *string `json:"availabilityImpact"` + BaseScore float64 `json:"baseScore"` // required + BaseSeverity string `json:"baseSeverity"` // required + ExploitCodeMaturity *string `json:"exploitCodeMaturity"` + RemediationLevel *string `json:"remediationLevel"` + ReportConfidence *string `json:"reportConfidence"` + TemporalScore *string `json:"temporalScore"` + TemporalSeverity *string `json:"temporalSeverity"` + ConfidentialityRequirement *string `json:"confidentialityRequirement"` + IntegrityRequirement *string `json:"integrityRequirement"` + AvailabilityRequirement *string `json:"availabilityRequirement"` + ModifiedAttackVector *string `json:"modifiedAttackVector"` + ModifiedAttackComplexity *string `json:"modifiedAttackComplexity"` + ModifiedPrivilegesRequired *string `json:"modifiedPrivilegesRequired"` + ModifiedUserInteraction *string `json:"modifiedUserInteraction"` + ModifiedScope *string `json:"modifiedScope"` + ModifiedConfidentialityImpact *string `json:"modifiedConfidentialityImpact"` + ModifiedIntegrityImpact *string `json:"modifiedIntegrityImpact"` + ModifiedAvailabilityImpact *string `json:"modifiedAvailabilityImpact"` + EenvironmentalScore *string `json:"environmentalScore"` + EnvironmentalSeverity *string `json:"environmentalSeverity"` +} + +// Score specifies information about (at least one) score of the vulnerability and for which +// products the given value applies. A Score item has at least 2 properties. +type Score struct { + CVSSv2 *CVSSv2 `json:"cvss_v2,omitempty"` + CVSSv3 *CVSSv3 `json:"cvss_v3,omitempty"` + Products *Products `json:"products"` // required +} + +// ThreatCategory is the category of a threat. +type ThreatCategory string + +const ( + // CSAFThreatCategoryExploitStatus is the "exploit_status" category. + CSAFThreatCategoryExploitStatus ThreatCategory = "exploit_status" + // CSAFThreatCategoryImpact is the "impact" category. + CSAFThreatCategoryImpact ThreatCategory = "impact" + // CSAFThreatCategoryTargetSet is the "target_set" category. + CSAFThreatCategoryTargetSet ThreatCategory = "target_set" +) + +var csafThreatCategoryPattern = alternativesUnmarshal( + string(CSAFThreatCategoryExploitStatus), + string(CSAFThreatCategoryImpact), + string(CSAFThreatCategoryTargetSet)) + +// Threat contains information about a vulnerability that can change with time. +type Threat struct { + Category ThreatCategory `json:"category"` // required + Date *string `json:"date,omitempty"` + Details string `json:"details"` // required + GroupIds *ProductGroups `json:"group_ids,omitempty"` + ProductIds *Products `json:"product_ids,omitempty"` +} + +// Vulnerability contains all fields that are related to a single vulnerability in the document. +type Vulnerability struct { + Acknowledgements []*Acknowledgement `json:"acknowledgements,omitempty"` + CVE *CVE `json:"cve,omitempty"` + CWE *CWE `json:"cwe,omitempty"` + DiscoveryDate *string `json:"discovery_date,omitempty"` + Flags []*Flag `json:"flags,omitempty"` + Ids []*VulnerabilityID `json:"ids,omitempty"` // unique ID elements + Involvements []*Involvement `json:"involvements,omitempty"` + Notes []*Note `json:"notes,omitempty"` + ProductStatus *ProductStatus `json:"product_status,omitempty"` + References []*Reference `json:"references,omitempty"` + ReleaseDate *string `json:"release_date,omitempty"` + Remediations []*Remediation `json:"remediations,omitempty"` + Scores []*Score `json:"scores,omitempty"` + Threats []*Threat `json:"threats,omitempty"` + Title *string `json:"title,omitempty"` +} + +// Advisory represents a CSAF advisory. +type Advisory struct { + Document Document `json:"document"` // required + ProductTree *ProductTree `json:"product_tree,omitempty"` + Vulnerabilities []*Vulnerability `json:"vulnerabilities,omitempty"` +} + +// Validate checks if the advisory is valid. +// Returns an error if the validation fails otherwise nil. +func (adv *Advisory) Validate() error { + // TODO + return nil +} + +// LoadAdvisory loads an advisory from a file. +func LoadAdvisory(fname string) (*Advisory, error) { + f, err := os.Open(fname) + if err != nil { + return nil, err + } + + var advisory Advisory + dec := json.NewDecoder(f) + if err := dec.Decode(&advisory); err != nil { + return nil, err + } + defer f.Close() + + return &advisory, nil +} + +// SaveAdvisory writes the JSON encoding of the given advisory to a +// file with the given name. +// It returns nil, otherwise an error. +func SaveAdvisory(adv *Advisory, fname string) error { + var w io.WriteCloser + f, err := os.Create(fname) + if err != nil { + return err + } + w = f + + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + err = enc.Encode(adv) + if e := w.Close(); err != nil { + err = e + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (bc *BranchCategory) UnmarshalText(data []byte) error { + s, err := csafBranchCategoryPattern(data) + if err == nil { + *bc = BranchCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (nc *NoteCategory) UnmarshalText(data []byte) error { + s, err := csafNoteCategoryPattern(data) + if err == nil { + *nc = NoteCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (rc *ReferenceCategory) UnmarshalText(data []byte) error { + s, err := csafReferenceCategoryPattern(data) + if err == nil { + *rc = ReferenceCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (dtl *DocumentTLPLabel) UnmarshalText(data []byte) error { + s, err := csafDocumentTLPLabelPattern(data) + if err == nil { + *dtl = DocumentTLPLabel(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (pc *PublisherCategory) UnmarshalText(data []byte) error { + s, err := csafPublisherCategoryPattern(data) + if err == nil { + *pc = PublisherCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (ts *TrackingStatus) UnmarshalText(data []byte) error { + s, err := csafTrackingStatusPattern(data) + if err == nil { + *ts = TrackingStatus(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (rc *RelationshipCategory) UnmarshalText(data []byte) error { + s, err := csafRelationshipCategoryPattern(data) + if err == nil { + *rc = RelationshipCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (fl *FlagLabel) UnmarshalText(data []byte) error { + s, err := csafFlagLabelPattern(data) + if err == nil { + *fl = FlagLabel(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (ip *InvolvementParty) UnmarshalText(data []byte) error { + s, err := csafInvolvementPartyPattern(data) + if err == nil { + *ip = InvolvementParty(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (is *InvolvementStatus) UnmarshalText(data []byte) error { + s, err := csafInvolvementStatusPattern(data) + if err == nil { + *is = InvolvementStatus(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (rc *RemediationCategory) UnmarshalText(data []byte) error { + s, err := csafRemediationCategoryPattern(data) + if err == nil { + *rc = RemediationCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (rrc *RestartRequiredCategory) UnmarshalText(data []byte) error { + s, err := csafRestartRequiredCategoryPattern(data) + if err == nil { + *rrc = RestartRequiredCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (tc *ThreatCategory) UnmarshalText(data []byte) error { + s, err := csafThreatCategoryPattern(data) + if err == nil { + *tc = ThreatCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (cpe *CPE) UnmarshalText(data []byte) error { + s, err := CPEPattern(data) + if err == nil { + *cpe = CPE(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (fhv *FileHashValue) UnmarshalText(data []byte) error { + s, err := FileHashValuePattern(data) + if err == nil { + *fhv = FileHashValue(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (p *PURL) UnmarshalText(data []byte) error { + s, err := PURLPattern(data) + if err == nil { + *p = PURL(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (l *Lang) UnmarshalText(data []byte) error { + s, err := LangPattern(data) + if err == nil { + *l = Lang(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (v *Version) UnmarshalText(data []byte) error { + s, err := VersionPattern(data) + if err == nil { + *v = Version(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (dc *DocumentCategory) UnmarshalText(data []byte) error { + s, err := DocumentCategoryPattern(data) + if err == nil { + *dc = DocumentCategory(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (cv *CSAFVersion) UnmarshalText(data []byte) error { + s, err := CSAFVersionPattern(data) + if err == nil { + *cv = CSAFVersion(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (ti *TrackingID) UnmarshalText(data []byte) error { + s, err := TrackingIDPattern(data) + if err == nil { + *ti = TrackingID(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (cve *CVE) UnmarshalText(data []byte) error { + s, err := CVEPattern(data) + if err == nil { + *cve = CVE(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (wi *WeaknessID) UnmarshalText(data []byte) error { + s, err := WeaknessIDPattern(data) + if err == nil { + *wi = WeaknessID(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (cv *CVSSv3Version) UnmarshalText(data []byte) error { + s, err := CVSSv3VersionPattern(data) + if err == nil { + *cv = CVSSv3Version(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (cvs *CVSSv3VectorString) UnmarshalText(data []byte) error { + s, err := CVSSv3VectorStringPattern(data) + if err == nil { + *cvs = CVSSv3VectorString(s) + } + return err +} From 96608a07fefbb7ba1b487372914d4b5dd066fe12 Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Sat, 2 Sep 2023 17:03:46 +0200 Subject: [PATCH 02/24] Move defer.Close to right position. --- csaf/advisory.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index dc73902..8d52636 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -781,14 +781,11 @@ func LoadAdvisory(fname string) (*Advisory, error) { if err != nil { return nil, err } - + defer f.Close() var advisory Advisory - dec := json.NewDecoder(f) - if err := dec.Decode(&advisory); err != nil { + if err := json.NewDecoder(f).Decode(&advisory); err != nil { return nil, err } - defer f.Close() - return &advisory, nil } From e82168342302e4b4d7f7c8d6b70b37a2adebbc5d Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Sat, 2 Sep 2023 17:38:12 +0200 Subject: [PATCH 03/24] Add generator for CVSS enums --- README.md | 6 + csaf/advisory.go | 98 +++---- csaf/cvss20enums.go | 314 ++++++++++++++++++++++ csaf/cvss30enums.go | 500 ++++++++++++++++++++++++++++++++++++ csaf/cvss31enums.go | 500 ++++++++++++++++++++++++++++++++++++ csaf/doc.go | 4 + csaf/generate_cvss_enums.go | 152 +++++++++++ 7 files changed, 1525 insertions(+), 49 deletions(-) create mode 100644 csaf/cvss20enums.go create mode 100644 csaf/cvss30enums.go create mode 100644 csaf/cvss31enums.go create mode 100644 csaf/generate_cvss_enums.go diff --git a/README.md b/README.md index 09aa341..a03cd3a 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,12 @@ Download the binaries from the most recent release assets on Github. Binaries will be placed in directories named like `bin-linux-amd64/` and `bin-windows-amd64/`. +- Maintainers only: No need to do this if you have cloned this repository for unmodified usage only. +``` +go generate ./... +``` +will update the machine generated code. + ### Setup (Trusted Provider) diff --git a/csaf/advisory.go b/csaf/advisory.go index dc73902..9895f5b 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -653,59 +653,59 @@ var CVSSv3VersionPattern = alternativesUnmarshal( // CVSSv2 holding a CVSS v2.0 value type CVSSv2 struct { - Version string `json:"version"` // required - VectorString string `json:"vectorString"` // required - AccessVector *string `json:"accessVector"` - AccessComplexity *string `json:"accessComplexity"` - Authentication *string `json:"authentication"` - ConfidentialityImpact *string `json:"confidentialityImpact"` - IntegrityImpact *string `json:"integrityImpact"` - AvailabilityImpact *string `json:"availabilityImpact"` - BaseScore float64 `json:"baseScore"` // required - Exploitability *string `json:"exploitability"` - RemediationLevel *string `json:"remediationLevel"` - ReportConfidence *string `json:"reportConfidence"` - TemporalScore *string `json:"temporalScore"` - CollateralDamagePotential *string `json:"collateralDamagePotential"` - TargetDistribution *string `json:"targetDistribution"` - ConfidentialityRequirement *string `json:"confidentialityRequirement"` - IntegrityRequirement *string `json:"integrityRequirement"` - AvailabilityRequirement *string `json:"availabilityRequirement"` - EnvironmentalScore *string `json:"environmentalScore"` + Version string `json:"version"` // required + VectorString string `json:"vectorString"` // required + AccessVector *CVSS20AccessVector `json:"accessVector"` + AccessComplexity *CVSS20AccessComplexity `json:"accessComplexity"` + Authentication *CVSS20Authentication `json:"authentication"` + ConfidentialityImpact *string `json:"confidentialityImpact"` + IntegrityImpact *string `json:"integrityImpact"` + AvailabilityImpact *string `json:"availabilityImpact"` + BaseScore float64 `json:"baseScore"` // required + Exploitability *CVSS20Exploitability `json:"exploitability"` + RemediationLevel *CVSS20RemediationLevel `json:"remediationLevel"` + ReportConfidence *string `json:"reportConfidence"` + TemporalScore *string `json:"temporalScore"` + CollateralDamagePotential *CVSS20CollateralDamagePotential `json:"collateralDamagePotential"` + TargetDistribution *CVSS20TargetDistribution `json:"targetDistribution"` + ConfidentialityRequirement *string `json:"confidentialityRequirement"` + IntegrityRequirement *string `json:"integrityRequirement"` + AvailabilityRequirement *string `json:"availabilityRequirement"` + EnvironmentalScore *string `json:"environmentalScore"` } // CVSSv3 holding a CVSS v3.x value type CVSSv3 struct { - Version string `json:"version"` // required - VectorString string `json:"vectorString"` // required - AttackVector *string `json:"attackVector"` - AttackComplexity *string `json:"attackComplexity"` - PrivilegesRequired *string `json:"privilegesRequired"` - UserInteraction *string `json:"userInteraction"` - Scope *string `json:"scope"` - ConfidentialityImpact *string `json:"confidentialityImpact"` - IntegrityImpact string `json:"integrityImpact"` - AvailabilityImpact *string `json:"availabilityImpact"` - BaseScore float64 `json:"baseScore"` // required - BaseSeverity string `json:"baseSeverity"` // required - ExploitCodeMaturity *string `json:"exploitCodeMaturity"` - RemediationLevel *string `json:"remediationLevel"` - ReportConfidence *string `json:"reportConfidence"` - TemporalScore *string `json:"temporalScore"` - TemporalSeverity *string `json:"temporalSeverity"` - ConfidentialityRequirement *string `json:"confidentialityRequirement"` - IntegrityRequirement *string `json:"integrityRequirement"` - AvailabilityRequirement *string `json:"availabilityRequirement"` - ModifiedAttackVector *string `json:"modifiedAttackVector"` - ModifiedAttackComplexity *string `json:"modifiedAttackComplexity"` - ModifiedPrivilegesRequired *string `json:"modifiedPrivilegesRequired"` - ModifiedUserInteraction *string `json:"modifiedUserInteraction"` - ModifiedScope *string `json:"modifiedScope"` - ModifiedConfidentialityImpact *string `json:"modifiedConfidentialityImpact"` - ModifiedIntegrityImpact *string `json:"modifiedIntegrityImpact"` - ModifiedAvailabilityImpact *string `json:"modifiedAvailabilityImpact"` - EenvironmentalScore *string `json:"environmentalScore"` - EnvironmentalSeverity *string `json:"environmentalSeverity"` + Version string `json:"version"` // required + VectorString string `json:"vectorString"` // required + AttackVector *string `json:"attackVector"` + AttackComplexity *CVSS30AttackComplexity `json:"attackComplexity"` + PrivilegesRequired *CVSS30PrivilegesRequired `json:"privilegesRequired"` + UserInteraction *CVSS30UserInteraction `json:"userInteraction"` + Scope *CVSS30Scope `json:"scope"` + ConfidentialityImpact *string `json:"confidentialityImpact"` + IntegrityImpact string `json:"integrityImpact"` + AvailabilityImpact *string `json:"availabilityImpact"` + BaseScore float64 `json:"baseScore"` // required + BaseSeverity string `json:"baseSeverity"` // required + ExploitCodeMaturity *CVSS30ExploitCodeMaturity `json:"exploitCodeMaturity"` + RemediationLevel *CVSS30RemediationLevel `json:"remediationLevel"` + ReportConfidence *string `json:"reportConfidence"` + TemporalScore *string `json:"temporalScore"` + TemporalSeverity *string `json:"temporalSeverity"` + ConfidentialityRequirement *string `json:"confidentialityRequirement"` + IntegrityRequirement *string `json:"integrityRequirement"` + AvailabilityRequirement *string `json:"availabilityRequirement"` + ModifiedAttackVector *CVSS30ModifiedAttackVector `json:"modifiedAttackVector"` + ModifiedAttackComplexity *CVSS30ModifiedAttackComplexity `json:"modifiedAttackComplexity"` + ModifiedPrivilegesRequired *string `json:"modifiedPrivilegesRequired"` + ModifiedUserInteraction *string `json:"modifiedUserInteraction"` + ModifiedScope *string `json:"modifiedScope"` + ModifiedConfidentialityImpact *string `json:"modifiedConfidentialityImpact"` + ModifiedIntegrityImpact *string `json:"modifiedIntegrityImpact"` + ModifiedAvailabilityImpact *string `json:"modifiedAvailabilityImpact"` + EenvironmentalScore *string `json:"environmentalScore"` + EnvironmentalSeverity *string `json:"environmentalSeverity"` } // Score specifies information about (at least one) score of the vulnerability and for which diff --git a/csaf/cvss20enums.go b/csaf/cvss20enums.go new file mode 100644 index 0000000..8862e8e --- /dev/null +++ b/csaf/cvss20enums.go @@ -0,0 +1,314 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) +// Software-Engineering: 2023 Intevation GmbH +// +// THIS FILE IS MACHINE GENERATED. EDIT WITH CARE! + +package csaf + +// CVSS20AccessComplexity represents the accessComplexityType in CVSS20. +type CVSS20AccessComplexity string + +const ( + // CVSS20AccessComplexityHigh is a constant for "HIGH". + CVSS20AccessComplexityHigh CVSS20AccessComplexity = "HIGH" + // CVSS20AccessComplexityMedium is a constant for "MEDIUM". + CVSS20AccessComplexityMedium CVSS20AccessComplexity = "MEDIUM" + // CVSS20AccessComplexityLow is a constant for "LOW". + CVSS20AccessComplexityLow CVSS20AccessComplexity = "LOW" +) + +var cvss20AccessComplexityPattern = alternativesUnmarshal( + string(CVSS20AccessComplexityHigh), + string(CVSS20AccessComplexityMedium), + string(CVSS20AccessComplexityLow), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20AccessComplexity) UnmarshalText(data []byte) error { + s, err := cvss20AccessComplexityPattern(data) + if err == nil { + *e = CVSS20AccessComplexity(s) + } + return err +} + +// CVSS20AccessVector represents the accessVectorType in CVSS20. +type CVSS20AccessVector string + +const ( + // CVSS20AccessVectorNetwork is a constant for "NETWORK". + CVSS20AccessVectorNetwork CVSS20AccessVector = "NETWORK" + // CVSS20AccessVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". + CVSS20AccessVectorAdjacentNetwork CVSS20AccessVector = "ADJACENT_NETWORK" + // CVSS20AccessVectorLocal is a constant for "LOCAL". + CVSS20AccessVectorLocal CVSS20AccessVector = "LOCAL" +) + +var cvss20AccessVectorPattern = alternativesUnmarshal( + string(CVSS20AccessVectorNetwork), + string(CVSS20AccessVectorAdjacentNetwork), + string(CVSS20AccessVectorLocal), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20AccessVector) UnmarshalText(data []byte) error { + s, err := cvss20AccessVectorPattern(data) + if err == nil { + *e = CVSS20AccessVector(s) + } + return err +} + +// CVSS20Authentication represents the authenticationType in CVSS20. +type CVSS20Authentication string + +const ( + // CVSS20AuthenticationMultiple is a constant for "MULTIPLE". + CVSS20AuthenticationMultiple CVSS20Authentication = "MULTIPLE" + // CVSS20AuthenticationSingle is a constant for "SINGLE". + CVSS20AuthenticationSingle CVSS20Authentication = "SINGLE" + // CVSS20AuthenticationNone is a constant for "NONE". + CVSS20AuthenticationNone CVSS20Authentication = "NONE" +) + +var cvss20AuthenticationPattern = alternativesUnmarshal( + string(CVSS20AuthenticationMultiple), + string(CVSS20AuthenticationSingle), + string(CVSS20AuthenticationNone), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20Authentication) UnmarshalText(data []byte) error { + s, err := cvss20AuthenticationPattern(data) + if err == nil { + *e = CVSS20Authentication(s) + } + return err +} + +// CVSS20CiaRequirement represents the ciaRequirementType in CVSS20. +type CVSS20CiaRequirement string + +const ( + // CVSS20CiaRequirementLow is a constant for "LOW". + CVSS20CiaRequirementLow CVSS20CiaRequirement = "LOW" + // CVSS20CiaRequirementMedium is a constant for "MEDIUM". + CVSS20CiaRequirementMedium CVSS20CiaRequirement = "MEDIUM" + // CVSS20CiaRequirementHigh is a constant for "HIGH". + CVSS20CiaRequirementHigh CVSS20CiaRequirement = "HIGH" + // CVSS20CiaRequirementNotDefined is a constant for "NOT_DEFINED". + CVSS20CiaRequirementNotDefined CVSS20CiaRequirement = "NOT_DEFINED" +) + +var cvss20CiaRequirementPattern = alternativesUnmarshal( + string(CVSS20CiaRequirementLow), + string(CVSS20CiaRequirementMedium), + string(CVSS20CiaRequirementHigh), + string(CVSS20CiaRequirementNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20CiaRequirement) UnmarshalText(data []byte) error { + s, err := cvss20CiaRequirementPattern(data) + if err == nil { + *e = CVSS20CiaRequirement(s) + } + return err +} + +// CVSS20Cia represents the ciaType in CVSS20. +type CVSS20Cia string + +const ( + // CVSS20CiaNone is a constant for "NONE". + CVSS20CiaNone CVSS20Cia = "NONE" + // CVSS20CiaPartial is a constant for "PARTIAL". + CVSS20CiaPartial CVSS20Cia = "PARTIAL" + // CVSS20CiaComplete is a constant for "COMPLETE". + CVSS20CiaComplete CVSS20Cia = "COMPLETE" +) + +var cvss20CiaPattern = alternativesUnmarshal( + string(CVSS20CiaNone), + string(CVSS20CiaPartial), + string(CVSS20CiaComplete), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20Cia) UnmarshalText(data []byte) error { + s, err := cvss20CiaPattern(data) + if err == nil { + *e = CVSS20Cia(s) + } + return err +} + +// CVSS20CollateralDamagePotential represents the collateralDamagePotentialType in CVSS20. +type CVSS20CollateralDamagePotential string + +const ( + // CVSS20CollateralDamagePotentialNone is a constant for "NONE". + CVSS20CollateralDamagePotentialNone CVSS20CollateralDamagePotential = "NONE" + // CVSS20CollateralDamagePotentialLow is a constant for "LOW". + CVSS20CollateralDamagePotentialLow CVSS20CollateralDamagePotential = "LOW" + // CVSS20CollateralDamagePotentialLowMedium is a constant for "LOW_MEDIUM". + CVSS20CollateralDamagePotentialLowMedium CVSS20CollateralDamagePotential = "LOW_MEDIUM" + // CVSS20CollateralDamagePotentialMediumHigh is a constant for "MEDIUM_HIGH". + CVSS20CollateralDamagePotentialMediumHigh CVSS20CollateralDamagePotential = "MEDIUM_HIGH" + // CVSS20CollateralDamagePotentialHigh is a constant for "HIGH". + CVSS20CollateralDamagePotentialHigh CVSS20CollateralDamagePotential = "HIGH" + // CVSS20CollateralDamagePotentialNotDefined is a constant for "NOT_DEFINED". + CVSS20CollateralDamagePotentialNotDefined CVSS20CollateralDamagePotential = "NOT_DEFINED" +) + +var cvss20CollateralDamagePotentialPattern = alternativesUnmarshal( + string(CVSS20CollateralDamagePotentialNone), + string(CVSS20CollateralDamagePotentialLow), + string(CVSS20CollateralDamagePotentialLowMedium), + string(CVSS20CollateralDamagePotentialMediumHigh), + string(CVSS20CollateralDamagePotentialHigh), + string(CVSS20CollateralDamagePotentialNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20CollateralDamagePotential) UnmarshalText(data []byte) error { + s, err := cvss20CollateralDamagePotentialPattern(data) + if err == nil { + *e = CVSS20CollateralDamagePotential(s) + } + return err +} + +// CVSS20Exploitability represents the exploitabilityType in CVSS20. +type CVSS20Exploitability string + +const ( + // CVSS20ExploitabilityUnproven is a constant for "UNPROVEN". + CVSS20ExploitabilityUnproven CVSS20Exploitability = "UNPROVEN" + // CVSS20ExploitabilityProofOfConcept is a constant for "PROOF_OF_CONCEPT". + CVSS20ExploitabilityProofOfConcept CVSS20Exploitability = "PROOF_OF_CONCEPT" + // CVSS20ExploitabilityFunctional is a constant for "FUNCTIONAL". + CVSS20ExploitabilityFunctional CVSS20Exploitability = "FUNCTIONAL" + // CVSS20ExploitabilityHigh is a constant for "HIGH". + CVSS20ExploitabilityHigh CVSS20Exploitability = "HIGH" + // CVSS20ExploitabilityNotDefined is a constant for "NOT_DEFINED". + CVSS20ExploitabilityNotDefined CVSS20Exploitability = "NOT_DEFINED" +) + +var cvss20ExploitabilityPattern = alternativesUnmarshal( + string(CVSS20ExploitabilityUnproven), + string(CVSS20ExploitabilityProofOfConcept), + string(CVSS20ExploitabilityFunctional), + string(CVSS20ExploitabilityHigh), + string(CVSS20ExploitabilityNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20Exploitability) UnmarshalText(data []byte) error { + s, err := cvss20ExploitabilityPattern(data) + if err == nil { + *e = CVSS20Exploitability(s) + } + return err +} + +// CVSS20RemediationLevel represents the remediationLevelType in CVSS20. +type CVSS20RemediationLevel string + +const ( + // CVSS20RemediationLevelOfficialFix is a constant for "OFFICIAL_FIX". + CVSS20RemediationLevelOfficialFix CVSS20RemediationLevel = "OFFICIAL_FIX" + // CVSS20RemediationLevelTemporaryFix is a constant for "TEMPORARY_FIX". + CVSS20RemediationLevelTemporaryFix CVSS20RemediationLevel = "TEMPORARY_FIX" + // CVSS20RemediationLevelWorkaround is a constant for "WORKAROUND". + CVSS20RemediationLevelWorkaround CVSS20RemediationLevel = "WORKAROUND" + // CVSS20RemediationLevelUnavailable is a constant for "UNAVAILABLE". + CVSS20RemediationLevelUnavailable CVSS20RemediationLevel = "UNAVAILABLE" + // CVSS20RemediationLevelNotDefined is a constant for "NOT_DEFINED". + CVSS20RemediationLevelNotDefined CVSS20RemediationLevel = "NOT_DEFINED" +) + +var cvss20RemediationLevelPattern = alternativesUnmarshal( + string(CVSS20RemediationLevelOfficialFix), + string(CVSS20RemediationLevelTemporaryFix), + string(CVSS20RemediationLevelWorkaround), + string(CVSS20RemediationLevelUnavailable), + string(CVSS20RemediationLevelNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20RemediationLevel) UnmarshalText(data []byte) error { + s, err := cvss20RemediationLevelPattern(data) + if err == nil { + *e = CVSS20RemediationLevel(s) + } + return err +} + +// CVSS20ReportConfidence represents the reportConfidenceType in CVSS20. +type CVSS20ReportConfidence string + +const ( + // CVSS20ReportConfidenceUnconfirmed is a constant for "UNCONFIRMED". + CVSS20ReportConfidenceUnconfirmed CVSS20ReportConfidence = "UNCONFIRMED" + // CVSS20ReportConfidenceUncorroborated is a constant for "UNCORROBORATED". + CVSS20ReportConfidenceUncorroborated CVSS20ReportConfidence = "UNCORROBORATED" + // CVSS20ReportConfidenceConfirmed is a constant for "CONFIRMED". + CVSS20ReportConfidenceConfirmed CVSS20ReportConfidence = "CONFIRMED" + // CVSS20ReportConfidenceNotDefined is a constant for "NOT_DEFINED". + CVSS20ReportConfidenceNotDefined CVSS20ReportConfidence = "NOT_DEFINED" +) + +var cvss20ReportConfidencePattern = alternativesUnmarshal( + string(CVSS20ReportConfidenceUnconfirmed), + string(CVSS20ReportConfidenceUncorroborated), + string(CVSS20ReportConfidenceConfirmed), + string(CVSS20ReportConfidenceNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20ReportConfidence) UnmarshalText(data []byte) error { + s, err := cvss20ReportConfidencePattern(data) + if err == nil { + *e = CVSS20ReportConfidence(s) + } + return err +} + +// CVSS20TargetDistribution represents the targetDistributionType in CVSS20. +type CVSS20TargetDistribution string + +const ( + // CVSS20TargetDistributionNone is a constant for "NONE". + CVSS20TargetDistributionNone CVSS20TargetDistribution = "NONE" + // CVSS20TargetDistributionLow is a constant for "LOW". + CVSS20TargetDistributionLow CVSS20TargetDistribution = "LOW" + // CVSS20TargetDistributionMedium is a constant for "MEDIUM". + CVSS20TargetDistributionMedium CVSS20TargetDistribution = "MEDIUM" + // CVSS20TargetDistributionHigh is a constant for "HIGH". + CVSS20TargetDistributionHigh CVSS20TargetDistribution = "HIGH" + // CVSS20TargetDistributionNotDefined is a constant for "NOT_DEFINED". + CVSS20TargetDistributionNotDefined CVSS20TargetDistribution = "NOT_DEFINED" +) + +var cvss20TargetDistributionPattern = alternativesUnmarshal( + string(CVSS20TargetDistributionNone), + string(CVSS20TargetDistributionLow), + string(CVSS20TargetDistributionMedium), + string(CVSS20TargetDistributionHigh), + string(CVSS20TargetDistributionNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS20TargetDistribution) UnmarshalText(data []byte) error { + s, err := cvss20TargetDistributionPattern(data) + if err == nil { + *e = CVSS20TargetDistribution(s) + } + return err +} diff --git a/csaf/cvss30enums.go b/csaf/cvss30enums.go new file mode 100644 index 0000000..7524174 --- /dev/null +++ b/csaf/cvss30enums.go @@ -0,0 +1,500 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) +// Software-Engineering: 2023 Intevation GmbH +// +// THIS FILE IS MACHINE GENERATED. EDIT WITH CARE! + +package csaf + +// CVSS30AttackComplexity represents the attackComplexityType in CVSS30. +type CVSS30AttackComplexity string + +const ( + // CVSS30AttackComplexityHigh is a constant for "HIGH". + CVSS30AttackComplexityHigh CVSS30AttackComplexity = "HIGH" + // CVSS30AttackComplexityLow is a constant for "LOW". + CVSS30AttackComplexityLow CVSS30AttackComplexity = "LOW" +) + +var cvss30AttackComplexityPattern = alternativesUnmarshal( + string(CVSS30AttackComplexityHigh), + string(CVSS30AttackComplexityLow), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30AttackComplexity) UnmarshalText(data []byte) error { + s, err := cvss30AttackComplexityPattern(data) + if err == nil { + *e = CVSS30AttackComplexity(s) + } + return err +} + +// CVSS30AttackVector represents the attackVectorType in CVSS30. +type CVSS30AttackVector string + +const ( + // CVSS30AttackVectorNetwork is a constant for "NETWORK". + CVSS30AttackVectorNetwork CVSS30AttackVector = "NETWORK" + // CVSS30AttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". + CVSS30AttackVectorAdjacentNetwork CVSS30AttackVector = "ADJACENT_NETWORK" + // CVSS30AttackVectorLocal is a constant for "LOCAL". + CVSS30AttackVectorLocal CVSS30AttackVector = "LOCAL" + // CVSS30AttackVectorPhysical is a constant for "PHYSICAL". + CVSS30AttackVectorPhysical CVSS30AttackVector = "PHYSICAL" +) + +var cvss30AttackVectorPattern = alternativesUnmarshal( + string(CVSS30AttackVectorNetwork), + string(CVSS30AttackVectorAdjacentNetwork), + string(CVSS30AttackVectorLocal), + string(CVSS30AttackVectorPhysical), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30AttackVector) UnmarshalText(data []byte) error { + s, err := cvss30AttackVectorPattern(data) + if err == nil { + *e = CVSS30AttackVector(s) + } + return err +} + +// CVSS30CiaRequirement represents the ciaRequirementType in CVSS30. +type CVSS30CiaRequirement string + +const ( + // CVSS30CiaRequirementLow is a constant for "LOW". + CVSS30CiaRequirementLow CVSS30CiaRequirement = "LOW" + // CVSS30CiaRequirementMedium is a constant for "MEDIUM". + CVSS30CiaRequirementMedium CVSS30CiaRequirement = "MEDIUM" + // CVSS30CiaRequirementHigh is a constant for "HIGH". + CVSS30CiaRequirementHigh CVSS30CiaRequirement = "HIGH" + // CVSS30CiaRequirementNotDefined is a constant for "NOT_DEFINED". + CVSS30CiaRequirementNotDefined CVSS30CiaRequirement = "NOT_DEFINED" +) + +var cvss30CiaRequirementPattern = alternativesUnmarshal( + string(CVSS30CiaRequirementLow), + string(CVSS30CiaRequirementMedium), + string(CVSS30CiaRequirementHigh), + string(CVSS30CiaRequirementNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30CiaRequirement) UnmarshalText(data []byte) error { + s, err := cvss30CiaRequirementPattern(data) + if err == nil { + *e = CVSS30CiaRequirement(s) + } + return err +} + +// CVSS30Cia represents the ciaType in CVSS30. +type CVSS30Cia string + +const ( + // CVSS30CiaNone is a constant for "NONE". + CVSS30CiaNone CVSS30Cia = "NONE" + // CVSS30CiaLow is a constant for "LOW". + CVSS30CiaLow CVSS30Cia = "LOW" + // CVSS30CiaHigh is a constant for "HIGH". + CVSS30CiaHigh CVSS30Cia = "HIGH" +) + +var cvss30CiaPattern = alternativesUnmarshal( + string(CVSS30CiaNone), + string(CVSS30CiaLow), + string(CVSS30CiaHigh), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30Cia) UnmarshalText(data []byte) error { + s, err := cvss30CiaPattern(data) + if err == nil { + *e = CVSS30Cia(s) + } + return err +} + +// CVSS30Confidence represents the confidenceType in CVSS30. +type CVSS30Confidence string + +const ( + // CVSS30ConfidenceUnknown is a constant for "UNKNOWN". + CVSS30ConfidenceUnknown CVSS30Confidence = "UNKNOWN" + // CVSS30ConfidenceReasonable is a constant for "REASONABLE". + CVSS30ConfidenceReasonable CVSS30Confidence = "REASONABLE" + // CVSS30ConfidenceConfirmed is a constant for "CONFIRMED". + CVSS30ConfidenceConfirmed CVSS30Confidence = "CONFIRMED" + // CVSS30ConfidenceNotDefined is a constant for "NOT_DEFINED". + CVSS30ConfidenceNotDefined CVSS30Confidence = "NOT_DEFINED" +) + +var cvss30ConfidencePattern = alternativesUnmarshal( + string(CVSS30ConfidenceUnknown), + string(CVSS30ConfidenceReasonable), + string(CVSS30ConfidenceConfirmed), + string(CVSS30ConfidenceNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30Confidence) UnmarshalText(data []byte) error { + s, err := cvss30ConfidencePattern(data) + if err == nil { + *e = CVSS30Confidence(s) + } + return err +} + +// CVSS30ExploitCodeMaturity represents the exploitCodeMaturityType in CVSS30. +type CVSS30ExploitCodeMaturity string + +const ( + // CVSS30ExploitCodeMaturityUnproven is a constant for "UNPROVEN". + CVSS30ExploitCodeMaturityUnproven CVSS30ExploitCodeMaturity = "UNPROVEN" + // CVSS30ExploitCodeMaturityProofOfConcept is a constant for "PROOF_OF_CONCEPT". + CVSS30ExploitCodeMaturityProofOfConcept CVSS30ExploitCodeMaturity = "PROOF_OF_CONCEPT" + // CVSS30ExploitCodeMaturityFunctional is a constant for "FUNCTIONAL". + CVSS30ExploitCodeMaturityFunctional CVSS30ExploitCodeMaturity = "FUNCTIONAL" + // CVSS30ExploitCodeMaturityHigh is a constant for "HIGH". + CVSS30ExploitCodeMaturityHigh CVSS30ExploitCodeMaturity = "HIGH" + // CVSS30ExploitCodeMaturityNotDefined is a constant for "NOT_DEFINED". + CVSS30ExploitCodeMaturityNotDefined CVSS30ExploitCodeMaturity = "NOT_DEFINED" +) + +var cvss30ExploitCodeMaturityPattern = alternativesUnmarshal( + string(CVSS30ExploitCodeMaturityUnproven), + string(CVSS30ExploitCodeMaturityProofOfConcept), + string(CVSS30ExploitCodeMaturityFunctional), + string(CVSS30ExploitCodeMaturityHigh), + string(CVSS30ExploitCodeMaturityNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30ExploitCodeMaturity) UnmarshalText(data []byte) error { + s, err := cvss30ExploitCodeMaturityPattern(data) + if err == nil { + *e = CVSS30ExploitCodeMaturity(s) + } + return err +} + +// CVSS30ModifiedAttackComplexity represents the modifiedAttackComplexityType in CVSS30. +type CVSS30ModifiedAttackComplexity string + +const ( + // CVSS30ModifiedAttackComplexityHigh is a constant for "HIGH". + CVSS30ModifiedAttackComplexityHigh CVSS30ModifiedAttackComplexity = "HIGH" + // CVSS30ModifiedAttackComplexityLow is a constant for "LOW". + CVSS30ModifiedAttackComplexityLow CVSS30ModifiedAttackComplexity = "LOW" + // CVSS30ModifiedAttackComplexityNotDefined is a constant for "NOT_DEFINED". + CVSS30ModifiedAttackComplexityNotDefined CVSS30ModifiedAttackComplexity = "NOT_DEFINED" +) + +var cvss30ModifiedAttackComplexityPattern = alternativesUnmarshal( + string(CVSS30ModifiedAttackComplexityHigh), + string(CVSS30ModifiedAttackComplexityLow), + string(CVSS30ModifiedAttackComplexityNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30ModifiedAttackComplexity) UnmarshalText(data []byte) error { + s, err := cvss30ModifiedAttackComplexityPattern(data) + if err == nil { + *e = CVSS30ModifiedAttackComplexity(s) + } + return err +} + +// CVSS30ModifiedAttackVector represents the modifiedAttackVectorType in CVSS30. +type CVSS30ModifiedAttackVector string + +const ( + // CVSS30ModifiedAttackVectorNetwork is a constant for "NETWORK". + CVSS30ModifiedAttackVectorNetwork CVSS30ModifiedAttackVector = "NETWORK" + // CVSS30ModifiedAttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". + CVSS30ModifiedAttackVectorAdjacentNetwork CVSS30ModifiedAttackVector = "ADJACENT_NETWORK" + // CVSS30ModifiedAttackVectorLocal is a constant for "LOCAL". + CVSS30ModifiedAttackVectorLocal CVSS30ModifiedAttackVector = "LOCAL" + // CVSS30ModifiedAttackVectorPhysical is a constant for "PHYSICAL". + CVSS30ModifiedAttackVectorPhysical CVSS30ModifiedAttackVector = "PHYSICAL" + // CVSS30ModifiedAttackVectorNotDefined is a constant for "NOT_DEFINED". + CVSS30ModifiedAttackVectorNotDefined CVSS30ModifiedAttackVector = "NOT_DEFINED" +) + +var cvss30ModifiedAttackVectorPattern = alternativesUnmarshal( + string(CVSS30ModifiedAttackVectorNetwork), + string(CVSS30ModifiedAttackVectorAdjacentNetwork), + string(CVSS30ModifiedAttackVectorLocal), + string(CVSS30ModifiedAttackVectorPhysical), + string(CVSS30ModifiedAttackVectorNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30ModifiedAttackVector) UnmarshalText(data []byte) error { + s, err := cvss30ModifiedAttackVectorPattern(data) + if err == nil { + *e = CVSS30ModifiedAttackVector(s) + } + return err +} + +// CVSS30ModifiedCia represents the modifiedCiaType in CVSS30. +type CVSS30ModifiedCia string + +const ( + // CVSS30ModifiedCiaNone is a constant for "NONE". + CVSS30ModifiedCiaNone CVSS30ModifiedCia = "NONE" + // CVSS30ModifiedCiaLow is a constant for "LOW". + CVSS30ModifiedCiaLow CVSS30ModifiedCia = "LOW" + // CVSS30ModifiedCiaHigh is a constant for "HIGH". + CVSS30ModifiedCiaHigh CVSS30ModifiedCia = "HIGH" + // CVSS30ModifiedCiaNotDefined is a constant for "NOT_DEFINED". + CVSS30ModifiedCiaNotDefined CVSS30ModifiedCia = "NOT_DEFINED" +) + +var cvss30ModifiedCiaPattern = alternativesUnmarshal( + string(CVSS30ModifiedCiaNone), + string(CVSS30ModifiedCiaLow), + string(CVSS30ModifiedCiaHigh), + string(CVSS30ModifiedCiaNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30ModifiedCia) UnmarshalText(data []byte) error { + s, err := cvss30ModifiedCiaPattern(data) + if err == nil { + *e = CVSS30ModifiedCia(s) + } + return err +} + +// CVSS30ModifiedPrivilegesRequired represents the modifiedPrivilegesRequiredType in CVSS30. +type CVSS30ModifiedPrivilegesRequired string + +const ( + // CVSS30ModifiedPrivilegesRequiredHigh is a constant for "HIGH". + CVSS30ModifiedPrivilegesRequiredHigh CVSS30ModifiedPrivilegesRequired = "HIGH" + // CVSS30ModifiedPrivilegesRequiredLow is a constant for "LOW". + CVSS30ModifiedPrivilegesRequiredLow CVSS30ModifiedPrivilegesRequired = "LOW" + // CVSS30ModifiedPrivilegesRequiredNone is a constant for "NONE". + CVSS30ModifiedPrivilegesRequiredNone CVSS30ModifiedPrivilegesRequired = "NONE" + // CVSS30ModifiedPrivilegesRequiredNotDefined is a constant for "NOT_DEFINED". + CVSS30ModifiedPrivilegesRequiredNotDefined CVSS30ModifiedPrivilegesRequired = "NOT_DEFINED" +) + +var cvss30ModifiedPrivilegesRequiredPattern = alternativesUnmarshal( + string(CVSS30ModifiedPrivilegesRequiredHigh), + string(CVSS30ModifiedPrivilegesRequiredLow), + string(CVSS30ModifiedPrivilegesRequiredNone), + string(CVSS30ModifiedPrivilegesRequiredNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30ModifiedPrivilegesRequired) UnmarshalText(data []byte) error { + s, err := cvss30ModifiedPrivilegesRequiredPattern(data) + if err == nil { + *e = CVSS30ModifiedPrivilegesRequired(s) + } + return err +} + +// CVSS30ModifiedScope represents the modifiedScopeType in CVSS30. +type CVSS30ModifiedScope string + +const ( + // CVSS30ModifiedScopeUnchanged is a constant for "UNCHANGED". + CVSS30ModifiedScopeUnchanged CVSS30ModifiedScope = "UNCHANGED" + // CVSS30ModifiedScopeChanged is a constant for "CHANGED". + CVSS30ModifiedScopeChanged CVSS30ModifiedScope = "CHANGED" + // CVSS30ModifiedScopeNotDefined is a constant for "NOT_DEFINED". + CVSS30ModifiedScopeNotDefined CVSS30ModifiedScope = "NOT_DEFINED" +) + +var cvss30ModifiedScopePattern = alternativesUnmarshal( + string(CVSS30ModifiedScopeUnchanged), + string(CVSS30ModifiedScopeChanged), + string(CVSS30ModifiedScopeNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30ModifiedScope) UnmarshalText(data []byte) error { + s, err := cvss30ModifiedScopePattern(data) + if err == nil { + *e = CVSS30ModifiedScope(s) + } + return err +} + +// CVSS30ModifiedUserInteraction represents the modifiedUserInteractionType in CVSS30. +type CVSS30ModifiedUserInteraction string + +const ( + // CVSS30ModifiedUserInteractionNone is a constant for "NONE". + CVSS30ModifiedUserInteractionNone CVSS30ModifiedUserInteraction = "NONE" + // CVSS30ModifiedUserInteractionRequired is a constant for "REQUIRED". + CVSS30ModifiedUserInteractionRequired CVSS30ModifiedUserInteraction = "REQUIRED" + // CVSS30ModifiedUserInteractionNotDefined is a constant for "NOT_DEFINED". + CVSS30ModifiedUserInteractionNotDefined CVSS30ModifiedUserInteraction = "NOT_DEFINED" +) + +var cvss30ModifiedUserInteractionPattern = alternativesUnmarshal( + string(CVSS30ModifiedUserInteractionNone), + string(CVSS30ModifiedUserInteractionRequired), + string(CVSS30ModifiedUserInteractionNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30ModifiedUserInteraction) UnmarshalText(data []byte) error { + s, err := cvss30ModifiedUserInteractionPattern(data) + if err == nil { + *e = CVSS30ModifiedUserInteraction(s) + } + return err +} + +// CVSS30PrivilegesRequired represents the privilegesRequiredType in CVSS30. +type CVSS30PrivilegesRequired string + +const ( + // CVSS30PrivilegesRequiredHigh is a constant for "HIGH". + CVSS30PrivilegesRequiredHigh CVSS30PrivilegesRequired = "HIGH" + // CVSS30PrivilegesRequiredLow is a constant for "LOW". + CVSS30PrivilegesRequiredLow CVSS30PrivilegesRequired = "LOW" + // CVSS30PrivilegesRequiredNone is a constant for "NONE". + CVSS30PrivilegesRequiredNone CVSS30PrivilegesRequired = "NONE" +) + +var cvss30PrivilegesRequiredPattern = alternativesUnmarshal( + string(CVSS30PrivilegesRequiredHigh), + string(CVSS30PrivilegesRequiredLow), + string(CVSS30PrivilegesRequiredNone), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30PrivilegesRequired) UnmarshalText(data []byte) error { + s, err := cvss30PrivilegesRequiredPattern(data) + if err == nil { + *e = CVSS30PrivilegesRequired(s) + } + return err +} + +// CVSS30RemediationLevel represents the remediationLevelType in CVSS30. +type CVSS30RemediationLevel string + +const ( + // CVSS30RemediationLevelOfficialFix is a constant for "OFFICIAL_FIX". + CVSS30RemediationLevelOfficialFix CVSS30RemediationLevel = "OFFICIAL_FIX" + // CVSS30RemediationLevelTemporaryFix is a constant for "TEMPORARY_FIX". + CVSS30RemediationLevelTemporaryFix CVSS30RemediationLevel = "TEMPORARY_FIX" + // CVSS30RemediationLevelWorkaround is a constant for "WORKAROUND". + CVSS30RemediationLevelWorkaround CVSS30RemediationLevel = "WORKAROUND" + // CVSS30RemediationLevelUnavailable is a constant for "UNAVAILABLE". + CVSS30RemediationLevelUnavailable CVSS30RemediationLevel = "UNAVAILABLE" + // CVSS30RemediationLevelNotDefined is a constant for "NOT_DEFINED". + CVSS30RemediationLevelNotDefined CVSS30RemediationLevel = "NOT_DEFINED" +) + +var cvss30RemediationLevelPattern = alternativesUnmarshal( + string(CVSS30RemediationLevelOfficialFix), + string(CVSS30RemediationLevelTemporaryFix), + string(CVSS30RemediationLevelWorkaround), + string(CVSS30RemediationLevelUnavailable), + string(CVSS30RemediationLevelNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30RemediationLevel) UnmarshalText(data []byte) error { + s, err := cvss30RemediationLevelPattern(data) + if err == nil { + *e = CVSS30RemediationLevel(s) + } + return err +} + +// CVSS30Scope represents the scopeType in CVSS30. +type CVSS30Scope string + +const ( + // CVSS30ScopeUnchanged is a constant for "UNCHANGED". + CVSS30ScopeUnchanged CVSS30Scope = "UNCHANGED" + // CVSS30ScopeChanged is a constant for "CHANGED". + CVSS30ScopeChanged CVSS30Scope = "CHANGED" +) + +var cvss30ScopePattern = alternativesUnmarshal( + string(CVSS30ScopeUnchanged), + string(CVSS30ScopeChanged), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30Scope) UnmarshalText(data []byte) error { + s, err := cvss30ScopePattern(data) + if err == nil { + *e = CVSS30Scope(s) + } + return err +} + +// CVSS30Severity represents the severityType in CVSS30. +type CVSS30Severity string + +const ( + // CVSS30SeverityNone is a constant for "NONE". + CVSS30SeverityNone CVSS30Severity = "NONE" + // CVSS30SeverityLow is a constant for "LOW". + CVSS30SeverityLow CVSS30Severity = "LOW" + // CVSS30SeverityMedium is a constant for "MEDIUM". + CVSS30SeverityMedium CVSS30Severity = "MEDIUM" + // CVSS30SeverityHigh is a constant for "HIGH". + CVSS30SeverityHigh CVSS30Severity = "HIGH" + // CVSS30SeverityCritical is a constant for "CRITICAL". + CVSS30SeverityCritical CVSS30Severity = "CRITICAL" +) + +var cvss30SeverityPattern = alternativesUnmarshal( + string(CVSS30SeverityNone), + string(CVSS30SeverityLow), + string(CVSS30SeverityMedium), + string(CVSS30SeverityHigh), + string(CVSS30SeverityCritical), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30Severity) UnmarshalText(data []byte) error { + s, err := cvss30SeverityPattern(data) + if err == nil { + *e = CVSS30Severity(s) + } + return err +} + +// CVSS30UserInteraction represents the userInteractionType in CVSS30. +type CVSS30UserInteraction string + +const ( + // CVSS30UserInteractionNone is a constant for "NONE". + CVSS30UserInteractionNone CVSS30UserInteraction = "NONE" + // CVSS30UserInteractionRequired is a constant for "REQUIRED". + CVSS30UserInteractionRequired CVSS30UserInteraction = "REQUIRED" +) + +var cvss30UserInteractionPattern = alternativesUnmarshal( + string(CVSS30UserInteractionNone), + string(CVSS30UserInteractionRequired), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS30UserInteraction) UnmarshalText(data []byte) error { + s, err := cvss30UserInteractionPattern(data) + if err == nil { + *e = CVSS30UserInteraction(s) + } + return err +} diff --git a/csaf/cvss31enums.go b/csaf/cvss31enums.go new file mode 100644 index 0000000..0de4946 --- /dev/null +++ b/csaf/cvss31enums.go @@ -0,0 +1,500 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) +// Software-Engineering: 2023 Intevation GmbH +// +// THIS FILE IS MACHINE GENERATED. EDIT WITH CARE! + +package csaf + +// CVSS31AttackComplexity represents the attackComplexityType in CVSS31. +type CVSS31AttackComplexity string + +const ( + // CVSS31AttackComplexityHigh is a constant for "HIGH". + CVSS31AttackComplexityHigh CVSS31AttackComplexity = "HIGH" + // CVSS31AttackComplexityLow is a constant for "LOW". + CVSS31AttackComplexityLow CVSS31AttackComplexity = "LOW" +) + +var cvss31AttackComplexityPattern = alternativesUnmarshal( + string(CVSS31AttackComplexityHigh), + string(CVSS31AttackComplexityLow), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31AttackComplexity) UnmarshalText(data []byte) error { + s, err := cvss31AttackComplexityPattern(data) + if err == nil { + *e = CVSS31AttackComplexity(s) + } + return err +} + +// CVSS31AttackVector represents the attackVectorType in CVSS31. +type CVSS31AttackVector string + +const ( + // CVSS31AttackVectorNetwork is a constant for "NETWORK". + CVSS31AttackVectorNetwork CVSS31AttackVector = "NETWORK" + // CVSS31AttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". + CVSS31AttackVectorAdjacentNetwork CVSS31AttackVector = "ADJACENT_NETWORK" + // CVSS31AttackVectorLocal is a constant for "LOCAL". + CVSS31AttackVectorLocal CVSS31AttackVector = "LOCAL" + // CVSS31AttackVectorPhysical is a constant for "PHYSICAL". + CVSS31AttackVectorPhysical CVSS31AttackVector = "PHYSICAL" +) + +var cvss31AttackVectorPattern = alternativesUnmarshal( + string(CVSS31AttackVectorNetwork), + string(CVSS31AttackVectorAdjacentNetwork), + string(CVSS31AttackVectorLocal), + string(CVSS31AttackVectorPhysical), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31AttackVector) UnmarshalText(data []byte) error { + s, err := cvss31AttackVectorPattern(data) + if err == nil { + *e = CVSS31AttackVector(s) + } + return err +} + +// CVSS31CiaRequirement represents the ciaRequirementType in CVSS31. +type CVSS31CiaRequirement string + +const ( + // CVSS31CiaRequirementLow is a constant for "LOW". + CVSS31CiaRequirementLow CVSS31CiaRequirement = "LOW" + // CVSS31CiaRequirementMedium is a constant for "MEDIUM". + CVSS31CiaRequirementMedium CVSS31CiaRequirement = "MEDIUM" + // CVSS31CiaRequirementHigh is a constant for "HIGH". + CVSS31CiaRequirementHigh CVSS31CiaRequirement = "HIGH" + // CVSS31CiaRequirementNotDefined is a constant for "NOT_DEFINED". + CVSS31CiaRequirementNotDefined CVSS31CiaRequirement = "NOT_DEFINED" +) + +var cvss31CiaRequirementPattern = alternativesUnmarshal( + string(CVSS31CiaRequirementLow), + string(CVSS31CiaRequirementMedium), + string(CVSS31CiaRequirementHigh), + string(CVSS31CiaRequirementNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31CiaRequirement) UnmarshalText(data []byte) error { + s, err := cvss31CiaRequirementPattern(data) + if err == nil { + *e = CVSS31CiaRequirement(s) + } + return err +} + +// CVSS31Cia represents the ciaType in CVSS31. +type CVSS31Cia string + +const ( + // CVSS31CiaNone is a constant for "NONE". + CVSS31CiaNone CVSS31Cia = "NONE" + // CVSS31CiaLow is a constant for "LOW". + CVSS31CiaLow CVSS31Cia = "LOW" + // CVSS31CiaHigh is a constant for "HIGH". + CVSS31CiaHigh CVSS31Cia = "HIGH" +) + +var cvss31CiaPattern = alternativesUnmarshal( + string(CVSS31CiaNone), + string(CVSS31CiaLow), + string(CVSS31CiaHigh), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31Cia) UnmarshalText(data []byte) error { + s, err := cvss31CiaPattern(data) + if err == nil { + *e = CVSS31Cia(s) + } + return err +} + +// CVSS31Confidence represents the confidenceType in CVSS31. +type CVSS31Confidence string + +const ( + // CVSS31ConfidenceUnknown is a constant for "UNKNOWN". + CVSS31ConfidenceUnknown CVSS31Confidence = "UNKNOWN" + // CVSS31ConfidenceReasonable is a constant for "REASONABLE". + CVSS31ConfidenceReasonable CVSS31Confidence = "REASONABLE" + // CVSS31ConfidenceConfirmed is a constant for "CONFIRMED". + CVSS31ConfidenceConfirmed CVSS31Confidence = "CONFIRMED" + // CVSS31ConfidenceNotDefined is a constant for "NOT_DEFINED". + CVSS31ConfidenceNotDefined CVSS31Confidence = "NOT_DEFINED" +) + +var cvss31ConfidencePattern = alternativesUnmarshal( + string(CVSS31ConfidenceUnknown), + string(CVSS31ConfidenceReasonable), + string(CVSS31ConfidenceConfirmed), + string(CVSS31ConfidenceNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31Confidence) UnmarshalText(data []byte) error { + s, err := cvss31ConfidencePattern(data) + if err == nil { + *e = CVSS31Confidence(s) + } + return err +} + +// CVSS31ExploitCodeMaturity represents the exploitCodeMaturityType in CVSS31. +type CVSS31ExploitCodeMaturity string + +const ( + // CVSS31ExploitCodeMaturityUnproven is a constant for "UNPROVEN". + CVSS31ExploitCodeMaturityUnproven CVSS31ExploitCodeMaturity = "UNPROVEN" + // CVSS31ExploitCodeMaturityProofOfConcept is a constant for "PROOF_OF_CONCEPT". + CVSS31ExploitCodeMaturityProofOfConcept CVSS31ExploitCodeMaturity = "PROOF_OF_CONCEPT" + // CVSS31ExploitCodeMaturityFunctional is a constant for "FUNCTIONAL". + CVSS31ExploitCodeMaturityFunctional CVSS31ExploitCodeMaturity = "FUNCTIONAL" + // CVSS31ExploitCodeMaturityHigh is a constant for "HIGH". + CVSS31ExploitCodeMaturityHigh CVSS31ExploitCodeMaturity = "HIGH" + // CVSS31ExploitCodeMaturityNotDefined is a constant for "NOT_DEFINED". + CVSS31ExploitCodeMaturityNotDefined CVSS31ExploitCodeMaturity = "NOT_DEFINED" +) + +var cvss31ExploitCodeMaturityPattern = alternativesUnmarshal( + string(CVSS31ExploitCodeMaturityUnproven), + string(CVSS31ExploitCodeMaturityProofOfConcept), + string(CVSS31ExploitCodeMaturityFunctional), + string(CVSS31ExploitCodeMaturityHigh), + string(CVSS31ExploitCodeMaturityNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31ExploitCodeMaturity) UnmarshalText(data []byte) error { + s, err := cvss31ExploitCodeMaturityPattern(data) + if err == nil { + *e = CVSS31ExploitCodeMaturity(s) + } + return err +} + +// CVSS31ModifiedAttackComplexity represents the modifiedAttackComplexityType in CVSS31. +type CVSS31ModifiedAttackComplexity string + +const ( + // CVSS31ModifiedAttackComplexityHigh is a constant for "HIGH". + CVSS31ModifiedAttackComplexityHigh CVSS31ModifiedAttackComplexity = "HIGH" + // CVSS31ModifiedAttackComplexityLow is a constant for "LOW". + CVSS31ModifiedAttackComplexityLow CVSS31ModifiedAttackComplexity = "LOW" + // CVSS31ModifiedAttackComplexityNotDefined is a constant for "NOT_DEFINED". + CVSS31ModifiedAttackComplexityNotDefined CVSS31ModifiedAttackComplexity = "NOT_DEFINED" +) + +var cvss31ModifiedAttackComplexityPattern = alternativesUnmarshal( + string(CVSS31ModifiedAttackComplexityHigh), + string(CVSS31ModifiedAttackComplexityLow), + string(CVSS31ModifiedAttackComplexityNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31ModifiedAttackComplexity) UnmarshalText(data []byte) error { + s, err := cvss31ModifiedAttackComplexityPattern(data) + if err == nil { + *e = CVSS31ModifiedAttackComplexity(s) + } + return err +} + +// CVSS31ModifiedAttackVector represents the modifiedAttackVectorType in CVSS31. +type CVSS31ModifiedAttackVector string + +const ( + // CVSS31ModifiedAttackVectorNetwork is a constant for "NETWORK". + CVSS31ModifiedAttackVectorNetwork CVSS31ModifiedAttackVector = "NETWORK" + // CVSS31ModifiedAttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". + CVSS31ModifiedAttackVectorAdjacentNetwork CVSS31ModifiedAttackVector = "ADJACENT_NETWORK" + // CVSS31ModifiedAttackVectorLocal is a constant for "LOCAL". + CVSS31ModifiedAttackVectorLocal CVSS31ModifiedAttackVector = "LOCAL" + // CVSS31ModifiedAttackVectorPhysical is a constant for "PHYSICAL". + CVSS31ModifiedAttackVectorPhysical CVSS31ModifiedAttackVector = "PHYSICAL" + // CVSS31ModifiedAttackVectorNotDefined is a constant for "NOT_DEFINED". + CVSS31ModifiedAttackVectorNotDefined CVSS31ModifiedAttackVector = "NOT_DEFINED" +) + +var cvss31ModifiedAttackVectorPattern = alternativesUnmarshal( + string(CVSS31ModifiedAttackVectorNetwork), + string(CVSS31ModifiedAttackVectorAdjacentNetwork), + string(CVSS31ModifiedAttackVectorLocal), + string(CVSS31ModifiedAttackVectorPhysical), + string(CVSS31ModifiedAttackVectorNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31ModifiedAttackVector) UnmarshalText(data []byte) error { + s, err := cvss31ModifiedAttackVectorPattern(data) + if err == nil { + *e = CVSS31ModifiedAttackVector(s) + } + return err +} + +// CVSS31ModifiedCia represents the modifiedCiaType in CVSS31. +type CVSS31ModifiedCia string + +const ( + // CVSS31ModifiedCiaNone is a constant for "NONE". + CVSS31ModifiedCiaNone CVSS31ModifiedCia = "NONE" + // CVSS31ModifiedCiaLow is a constant for "LOW". + CVSS31ModifiedCiaLow CVSS31ModifiedCia = "LOW" + // CVSS31ModifiedCiaHigh is a constant for "HIGH". + CVSS31ModifiedCiaHigh CVSS31ModifiedCia = "HIGH" + // CVSS31ModifiedCiaNotDefined is a constant for "NOT_DEFINED". + CVSS31ModifiedCiaNotDefined CVSS31ModifiedCia = "NOT_DEFINED" +) + +var cvss31ModifiedCiaPattern = alternativesUnmarshal( + string(CVSS31ModifiedCiaNone), + string(CVSS31ModifiedCiaLow), + string(CVSS31ModifiedCiaHigh), + string(CVSS31ModifiedCiaNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31ModifiedCia) UnmarshalText(data []byte) error { + s, err := cvss31ModifiedCiaPattern(data) + if err == nil { + *e = CVSS31ModifiedCia(s) + } + return err +} + +// CVSS31ModifiedPrivilegesRequired represents the modifiedPrivilegesRequiredType in CVSS31. +type CVSS31ModifiedPrivilegesRequired string + +const ( + // CVSS31ModifiedPrivilegesRequiredHigh is a constant for "HIGH". + CVSS31ModifiedPrivilegesRequiredHigh CVSS31ModifiedPrivilegesRequired = "HIGH" + // CVSS31ModifiedPrivilegesRequiredLow is a constant for "LOW". + CVSS31ModifiedPrivilegesRequiredLow CVSS31ModifiedPrivilegesRequired = "LOW" + // CVSS31ModifiedPrivilegesRequiredNone is a constant for "NONE". + CVSS31ModifiedPrivilegesRequiredNone CVSS31ModifiedPrivilegesRequired = "NONE" + // CVSS31ModifiedPrivilegesRequiredNotDefined is a constant for "NOT_DEFINED". + CVSS31ModifiedPrivilegesRequiredNotDefined CVSS31ModifiedPrivilegesRequired = "NOT_DEFINED" +) + +var cvss31ModifiedPrivilegesRequiredPattern = alternativesUnmarshal( + string(CVSS31ModifiedPrivilegesRequiredHigh), + string(CVSS31ModifiedPrivilegesRequiredLow), + string(CVSS31ModifiedPrivilegesRequiredNone), + string(CVSS31ModifiedPrivilegesRequiredNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31ModifiedPrivilegesRequired) UnmarshalText(data []byte) error { + s, err := cvss31ModifiedPrivilegesRequiredPattern(data) + if err == nil { + *e = CVSS31ModifiedPrivilegesRequired(s) + } + return err +} + +// CVSS31ModifiedScope represents the modifiedScopeType in CVSS31. +type CVSS31ModifiedScope string + +const ( + // CVSS31ModifiedScopeUnchanged is a constant for "UNCHANGED". + CVSS31ModifiedScopeUnchanged CVSS31ModifiedScope = "UNCHANGED" + // CVSS31ModifiedScopeChanged is a constant for "CHANGED". + CVSS31ModifiedScopeChanged CVSS31ModifiedScope = "CHANGED" + // CVSS31ModifiedScopeNotDefined is a constant for "NOT_DEFINED". + CVSS31ModifiedScopeNotDefined CVSS31ModifiedScope = "NOT_DEFINED" +) + +var cvss31ModifiedScopePattern = alternativesUnmarshal( + string(CVSS31ModifiedScopeUnchanged), + string(CVSS31ModifiedScopeChanged), + string(CVSS31ModifiedScopeNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31ModifiedScope) UnmarshalText(data []byte) error { + s, err := cvss31ModifiedScopePattern(data) + if err == nil { + *e = CVSS31ModifiedScope(s) + } + return err +} + +// CVSS31ModifiedUserInteraction represents the modifiedUserInteractionType in CVSS31. +type CVSS31ModifiedUserInteraction string + +const ( + // CVSS31ModifiedUserInteractionNone is a constant for "NONE". + CVSS31ModifiedUserInteractionNone CVSS31ModifiedUserInteraction = "NONE" + // CVSS31ModifiedUserInteractionRequired is a constant for "REQUIRED". + CVSS31ModifiedUserInteractionRequired CVSS31ModifiedUserInteraction = "REQUIRED" + // CVSS31ModifiedUserInteractionNotDefined is a constant for "NOT_DEFINED". + CVSS31ModifiedUserInteractionNotDefined CVSS31ModifiedUserInteraction = "NOT_DEFINED" +) + +var cvss31ModifiedUserInteractionPattern = alternativesUnmarshal( + string(CVSS31ModifiedUserInteractionNone), + string(CVSS31ModifiedUserInteractionRequired), + string(CVSS31ModifiedUserInteractionNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31ModifiedUserInteraction) UnmarshalText(data []byte) error { + s, err := cvss31ModifiedUserInteractionPattern(data) + if err == nil { + *e = CVSS31ModifiedUserInteraction(s) + } + return err +} + +// CVSS31PrivilegesRequired represents the privilegesRequiredType in CVSS31. +type CVSS31PrivilegesRequired string + +const ( + // CVSS31PrivilegesRequiredHigh is a constant for "HIGH". + CVSS31PrivilegesRequiredHigh CVSS31PrivilegesRequired = "HIGH" + // CVSS31PrivilegesRequiredLow is a constant for "LOW". + CVSS31PrivilegesRequiredLow CVSS31PrivilegesRequired = "LOW" + // CVSS31PrivilegesRequiredNone is a constant for "NONE". + CVSS31PrivilegesRequiredNone CVSS31PrivilegesRequired = "NONE" +) + +var cvss31PrivilegesRequiredPattern = alternativesUnmarshal( + string(CVSS31PrivilegesRequiredHigh), + string(CVSS31PrivilegesRequiredLow), + string(CVSS31PrivilegesRequiredNone), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31PrivilegesRequired) UnmarshalText(data []byte) error { + s, err := cvss31PrivilegesRequiredPattern(data) + if err == nil { + *e = CVSS31PrivilegesRequired(s) + } + return err +} + +// CVSS31RemediationLevel represents the remediationLevelType in CVSS31. +type CVSS31RemediationLevel string + +const ( + // CVSS31RemediationLevelOfficialFix is a constant for "OFFICIAL_FIX". + CVSS31RemediationLevelOfficialFix CVSS31RemediationLevel = "OFFICIAL_FIX" + // CVSS31RemediationLevelTemporaryFix is a constant for "TEMPORARY_FIX". + CVSS31RemediationLevelTemporaryFix CVSS31RemediationLevel = "TEMPORARY_FIX" + // CVSS31RemediationLevelWorkaround is a constant for "WORKAROUND". + CVSS31RemediationLevelWorkaround CVSS31RemediationLevel = "WORKAROUND" + // CVSS31RemediationLevelUnavailable is a constant for "UNAVAILABLE". + CVSS31RemediationLevelUnavailable CVSS31RemediationLevel = "UNAVAILABLE" + // CVSS31RemediationLevelNotDefined is a constant for "NOT_DEFINED". + CVSS31RemediationLevelNotDefined CVSS31RemediationLevel = "NOT_DEFINED" +) + +var cvss31RemediationLevelPattern = alternativesUnmarshal( + string(CVSS31RemediationLevelOfficialFix), + string(CVSS31RemediationLevelTemporaryFix), + string(CVSS31RemediationLevelWorkaround), + string(CVSS31RemediationLevelUnavailable), + string(CVSS31RemediationLevelNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31RemediationLevel) UnmarshalText(data []byte) error { + s, err := cvss31RemediationLevelPattern(data) + if err == nil { + *e = CVSS31RemediationLevel(s) + } + return err +} + +// CVSS31Scope represents the scopeType in CVSS31. +type CVSS31Scope string + +const ( + // CVSS31ScopeUnchanged is a constant for "UNCHANGED". + CVSS31ScopeUnchanged CVSS31Scope = "UNCHANGED" + // CVSS31ScopeChanged is a constant for "CHANGED". + CVSS31ScopeChanged CVSS31Scope = "CHANGED" +) + +var cvss31ScopePattern = alternativesUnmarshal( + string(CVSS31ScopeUnchanged), + string(CVSS31ScopeChanged), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31Scope) UnmarshalText(data []byte) error { + s, err := cvss31ScopePattern(data) + if err == nil { + *e = CVSS31Scope(s) + } + return err +} + +// CVSS31Severity represents the severityType in CVSS31. +type CVSS31Severity string + +const ( + // CVSS31SeverityNone is a constant for "NONE". + CVSS31SeverityNone CVSS31Severity = "NONE" + // CVSS31SeverityLow is a constant for "LOW". + CVSS31SeverityLow CVSS31Severity = "LOW" + // CVSS31SeverityMedium is a constant for "MEDIUM". + CVSS31SeverityMedium CVSS31Severity = "MEDIUM" + // CVSS31SeverityHigh is a constant for "HIGH". + CVSS31SeverityHigh CVSS31Severity = "HIGH" + // CVSS31SeverityCritical is a constant for "CRITICAL". + CVSS31SeverityCritical CVSS31Severity = "CRITICAL" +) + +var cvss31SeverityPattern = alternativesUnmarshal( + string(CVSS31SeverityNone), + string(CVSS31SeverityLow), + string(CVSS31SeverityMedium), + string(CVSS31SeverityHigh), + string(CVSS31SeverityCritical), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31Severity) UnmarshalText(data []byte) error { + s, err := cvss31SeverityPattern(data) + if err == nil { + *e = CVSS31Severity(s) + } + return err +} + +// CVSS31UserInteraction represents the userInteractionType in CVSS31. +type CVSS31UserInteraction string + +const ( + // CVSS31UserInteractionNone is a constant for "NONE". + CVSS31UserInteractionNone CVSS31UserInteraction = "NONE" + // CVSS31UserInteractionRequired is a constant for "REQUIRED". + CVSS31UserInteractionRequired CVSS31UserInteraction = "REQUIRED" +) + +var cvss31UserInteractionPattern = alternativesUnmarshal( + string(CVSS31UserInteractionNone), + string(CVSS31UserInteractionRequired), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS31UserInteraction) UnmarshalText(data []byte) error { + s, err := cvss31UserInteractionPattern(data) + if err == nil { + *e = CVSS31UserInteraction(s) + } + return err +} diff --git a/csaf/doc.go b/csaf/doc.go index 83dd571..92d8ee3 100644 --- a/csaf/doc.go +++ b/csaf/doc.go @@ -8,3 +8,7 @@ // Package csaf contains the core data models used by the csaf distribution. package csaf + +//go:generate go run ./generate_cvss_enums.go -o cvss20enums.go -i ./schema/cvss-v2.0.json -p CVSS20 +//go:generate go run ./generate_cvss_enums.go -o cvss30enums.go -i ./schema/cvss-v3.0.json -p CVSS30 +//go:generate go run ./generate_cvss_enums.go -o cvss31enums.go -i ./schema/cvss-v3.1.json -p CVSS31 diff --git a/csaf/generate_cvss_enums.go b/csaf/generate_cvss_enums.go new file mode 100644 index 0000000..911b64d --- /dev/null +++ b/csaf/generate_cvss_enums.go @@ -0,0 +1,152 @@ +//go:build ignore + +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) +// Software-Engineering: 2023 Intevation GmbH + +package main + +import ( + "bytes" + "encoding/json" + "flag" + "go/format" + "log" + "os" + "slices" + "strings" + "text/template" +) + +const tmplText = `// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) +// Software-Engineering: 2023 Intevation GmbH +// +// THIS FILE IS MACHINE GENERATED. EDIT WITH CARE! + +package csaf + +{{ range $key := .Keys }} +{{ $def := index $.Definitions $key }} +// {{ $type := printf "%s%s" $.Prefix (typename $key) }}{{ $type }} represents the {{ $key }} in {{ $.Prefix }}. +type {{ $type }} string +const ( + {{ range $enum := $def.Enum -}} + // {{ $type}}{{ symbol $enum }} is a constant for "{{ $enum }}". + {{ $type }}{{ symbol $enum }} {{ $type }} = "{{ $enum }}" + {{ end }} +) +var {{ tolower $.Prefix }}{{ typename $key }}Pattern = alternativesUnmarshal( + {{ range $enum := $def.Enum -}} + string({{ $type }}{{ symbol $enum }}), + {{ end }} +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *{{ $type }}) UnmarshalText(data []byte) error { + s, err := {{ tolower $.Prefix }}{{ typename $key }}Pattern(data) + if err == nil { + *e = {{ $type }}(s) + } + return err +} +{{ end }} +` + +var tmpl = template.Must(template.New("enums").Funcs(funcs).Parse(tmplText)) + +type definition struct { + Type string `json:"type"` + Enum []string `json:"enum"` +} + +type schema struct { + Definitions map[string]*definition `json:"definitions"` +} + +var funcs = template.FuncMap{ + "tolower": strings.ToLower, + "symbol": func(s string) string { + s = strings.ToLower(s) + s = strings.ReplaceAll(s, "_", " ") + s = strings.Title(s) + s = strings.ReplaceAll(s, " ", "") + return s + }, + "typename": func(s string) string { + if strings.HasSuffix(s, "Type") { + s = s[:len(s)-len("Type")] + } + s = strings.Title(s) + return s + }, +} + +func loadSchema(filename string) (*schema, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + var s schema + if err := json.NewDecoder(f).Decode(&s); err != nil { + return nil, err + } + return &s, nil +} + +func check(err error) { + if err != nil { + log.Fatalf("error: %v\n", err) + } +} + +func main() { + var ( + input = flag.String("i", "input", "") + output = flag.String("o", "output", "") + prefix = flag.String("p", "prefix", "") + ) + flag.Parse() + if *input == "" { + log.Fatalln("missing schema") + } + if *output == "" { + log.Fatalln("missing output") + } + if *prefix == "" { + log.Fatalln("missing prefix") + } + + s, err := loadSchema(*input) + check(err) + + defs := make([]string, 0, len(s.Definitions)) + for k, v := range s.Definitions { + if v.Type == "string" && len(v.Enum) > 0 { + defs = append(defs, k) + } + } + slices.Sort(defs) + + var source bytes.Buffer + + check(tmpl.Execute(&source, map[string]any{ + "Prefix": *prefix, + "Definitions": s.Definitions, + "Keys": defs, + })) + + formatted, err := format.Source(source.Bytes()) + check(err) + + check(os.WriteFile(*output, formatted, 0644)) +} From f59a8cc7a9eb99e4d2d2a967d1a7b4d9e164bf6c Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Mon, 4 Sep 2023 15:58:28 +0200 Subject: [PATCH 04/24] use generated types --- csaf/advisory.go | 78 ++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index 601b56e..76019b6 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -658,54 +658,54 @@ type CVSSv2 struct { AccessVector *CVSS20AccessVector `json:"accessVector"` AccessComplexity *CVSS20AccessComplexity `json:"accessComplexity"` Authentication *CVSS20Authentication `json:"authentication"` - ConfidentialityImpact *string `json:"confidentialityImpact"` - IntegrityImpact *string `json:"integrityImpact"` - AvailabilityImpact *string `json:"availabilityImpact"` + ConfidentialityImpact *CVSS20Cia `json:"confidentialityImpact"` + IntegrityImpact *CVSS20Cia `json:"integrityImpact"` + AvailabilityImpact *CVSS20Cia `json:"availabilityImpact"` BaseScore float64 `json:"baseScore"` // required Exploitability *CVSS20Exploitability `json:"exploitability"` RemediationLevel *CVSS20RemediationLevel `json:"remediationLevel"` - ReportConfidence *string `json:"reportConfidence"` - TemporalScore *string `json:"temporalScore"` + ReportConfidence *CVSS20ReportConfidence `json:"reportConfidence"` + TemporalScore *float64 `json:"temporalScore"` CollateralDamagePotential *CVSS20CollateralDamagePotential `json:"collateralDamagePotential"` TargetDistribution *CVSS20TargetDistribution `json:"targetDistribution"` - ConfidentialityRequirement *string `json:"confidentialityRequirement"` - IntegrityRequirement *string `json:"integrityRequirement"` - AvailabilityRequirement *string `json:"availabilityRequirement"` - EnvironmentalScore *string `json:"environmentalScore"` + ConfidentialityRequirement *CVSS20CiaRequirement `json:"confidentialityRequirement"` + IntegrityRequirement *CVSS20CiaRequirement `json:"integrityRequirement"` + AvailabilityRequirement *CVSS20CiaRequirement `json:"availabilityRequirement"` + EnvironmentalScore *float64 `json:"environmentalScore"` } // CVSSv3 holding a CVSS v3.x value type CVSSv3 struct { - Version string `json:"version"` // required - VectorString string `json:"vectorString"` // required - AttackVector *string `json:"attackVector"` - AttackComplexity *CVSS30AttackComplexity `json:"attackComplexity"` - PrivilegesRequired *CVSS30PrivilegesRequired `json:"privilegesRequired"` - UserInteraction *CVSS30UserInteraction `json:"userInteraction"` - Scope *CVSS30Scope `json:"scope"` - ConfidentialityImpact *string `json:"confidentialityImpact"` - IntegrityImpact string `json:"integrityImpact"` - AvailabilityImpact *string `json:"availabilityImpact"` - BaseScore float64 `json:"baseScore"` // required - BaseSeverity string `json:"baseSeverity"` // required - ExploitCodeMaturity *CVSS30ExploitCodeMaturity `json:"exploitCodeMaturity"` - RemediationLevel *CVSS30RemediationLevel `json:"remediationLevel"` - ReportConfidence *string `json:"reportConfidence"` - TemporalScore *string `json:"temporalScore"` - TemporalSeverity *string `json:"temporalSeverity"` - ConfidentialityRequirement *string `json:"confidentialityRequirement"` - IntegrityRequirement *string `json:"integrityRequirement"` - AvailabilityRequirement *string `json:"availabilityRequirement"` - ModifiedAttackVector *CVSS30ModifiedAttackVector `json:"modifiedAttackVector"` - ModifiedAttackComplexity *CVSS30ModifiedAttackComplexity `json:"modifiedAttackComplexity"` - ModifiedPrivilegesRequired *string `json:"modifiedPrivilegesRequired"` - ModifiedUserInteraction *string `json:"modifiedUserInteraction"` - ModifiedScope *string `json:"modifiedScope"` - ModifiedConfidentialityImpact *string `json:"modifiedConfidentialityImpact"` - ModifiedIntegrityImpact *string `json:"modifiedIntegrityImpact"` - ModifiedAvailabilityImpact *string `json:"modifiedAvailabilityImpact"` - EenvironmentalScore *string `json:"environmentalScore"` - EnvironmentalSeverity *string `json:"environmentalSeverity"` + Version string `json:"version"` // required + VectorString string `json:"vectorString"` // required + AttackVector *CVSS30AttackVector `json:"attackVector"` + AttackComplexity *CVSS30AttackComplexity `json:"attackComplexity"` + PrivilegesRequired *CVSS30PrivilegesRequired `json:"privilegesRequired"` + UserInteraction *CVSS30UserInteraction `json:"userInteraction"` + Scope *CVSS30Scope `json:"scope"` + ConfidentialityImpact *CVSS30Cia `json:"confidentialityImpact"` + IntegrityImpact CVSS30Cia `json:"integrityImpact"` + AvailabilityImpact *CVSS30Cia `json:"availabilityImpact"` + BaseScore float64 `json:"baseScore"` // required + BaseSeverity CVSS30Severity `json:"baseSeverity"` // required + ExploitCodeMaturity *CVSS30ExploitCodeMaturity `json:"exploitCodeMaturity"` + RemediationLevel *CVSS30RemediationLevel `json:"remediationLevel"` + ReportConfidence *CVSS30Confidence `json:"reportConfidence"` + TemporalScore *float64 `json:"temporalScore"` + TemporalSeverity *CVSS30Severity `json:"temporalSeverity"` + ConfidentialityRequirement *CVSS30CiaRequirement `json:"confidentialityRequirement"` + IntegrityRequirement *CVSS30CiaRequirement `json:"integrityRequirement"` + AvailabilityRequirement *CVSS30CiaRequirement `json:"availabilityRequirement"` + ModifiedAttackVector *CVSS30ModifiedAttackVector `json:"modifiedAttackVector"` + ModifiedAttackComplexity *CVSS30ModifiedAttackComplexity `json:"modifiedAttackComplexity"` + ModifiedPrivilegesRequired *CVSS30ModifiedPrivilegesRequired `json:"modifiedPrivilegesRequired"` + ModifiedUserInteraction *CVSS30ModifiedUserInteraction `json:"modifiedUserInteraction"` + ModifiedScope *CVSS30ModifiedScope `json:"modifiedScope"` + ModifiedConfidentialityImpact *CVSS30ModifiedCia `json:"modifiedConfidentialityImpact"` + ModifiedIntegrityImpact *CVSS30ModifiedCia `json:"modifiedIntegrityImpact"` + ModifiedAvailabilityImpact *CVSS30ModifiedCia `json:"modifiedAvailabilityImpact"` + EenvironmentalScore *float64 `json:"environmentalScore"` + EnvironmentalSeverity *CVSS30Severity `json:"environmentalSeverity"` } // Score specifies information about (at least one) score of the vulnerability and for which From 4fc2fd9bf2d9a95ce3b21b30e3c1096314283114 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Mon, 4 Sep 2023 16:06:47 +0200 Subject: [PATCH 05/24] added omitempty for cvss structs --- csaf/advisory.go | 84 ++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index 76019b6..39604a8 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -655,57 +655,57 @@ var CVSSv3VersionPattern = alternativesUnmarshal( type CVSSv2 struct { Version string `json:"version"` // required VectorString string `json:"vectorString"` // required - AccessVector *CVSS20AccessVector `json:"accessVector"` - AccessComplexity *CVSS20AccessComplexity `json:"accessComplexity"` - Authentication *CVSS20Authentication `json:"authentication"` - ConfidentialityImpact *CVSS20Cia `json:"confidentialityImpact"` - IntegrityImpact *CVSS20Cia `json:"integrityImpact"` - AvailabilityImpact *CVSS20Cia `json:"availabilityImpact"` + AccessVector *CVSS20AccessVector `json:"accessVector,omitempty"` + AccessComplexity *CVSS20AccessComplexity `json:"accessComplexity,omitempty"` + Authentication *CVSS20Authentication `json:"authentication,omitempty"` + ConfidentialityImpact *CVSS20Cia `json:"confidentialityImpact,omitempty"` + IntegrityImpact *CVSS20Cia `json:"integrityImpact,omitempty"` + AvailabilityImpact *CVSS20Cia `json:"availabilityImpact,omitempty"` BaseScore float64 `json:"baseScore"` // required - Exploitability *CVSS20Exploitability `json:"exploitability"` - RemediationLevel *CVSS20RemediationLevel `json:"remediationLevel"` - ReportConfidence *CVSS20ReportConfidence `json:"reportConfidence"` - TemporalScore *float64 `json:"temporalScore"` - CollateralDamagePotential *CVSS20CollateralDamagePotential `json:"collateralDamagePotential"` - TargetDistribution *CVSS20TargetDistribution `json:"targetDistribution"` - ConfidentialityRequirement *CVSS20CiaRequirement `json:"confidentialityRequirement"` - IntegrityRequirement *CVSS20CiaRequirement `json:"integrityRequirement"` - AvailabilityRequirement *CVSS20CiaRequirement `json:"availabilityRequirement"` - EnvironmentalScore *float64 `json:"environmentalScore"` + Exploitability *CVSS20Exploitability `json:"exploitability,omitempty"` + RemediationLevel *CVSS20RemediationLevel `json:"remediationLevel,omitempty"` + ReportConfidence *CVSS20ReportConfidence `json:"reportConfidence,omitempty"` + TemporalScore *float64 `json:"temporalScore,omitempty"` + CollateralDamagePotential *CVSS20CollateralDamagePotential `json:"collateralDamagePotential,omitempty"` + TargetDistribution *CVSS20TargetDistribution `json:"targetDistribution,omitempty"` + ConfidentialityRequirement *CVSS20CiaRequirement `json:"confidentialityRequirement,omitempty"` + IntegrityRequirement *CVSS20CiaRequirement `json:"integrityRequirement,omitempty"` + AvailabilityRequirement *CVSS20CiaRequirement `json:"availabilityRequirement,omitempty"` + EnvironmentalScore *float64 `json:"environmentalScore,omitempty"` } // CVSSv3 holding a CVSS v3.x value type CVSSv3 struct { Version string `json:"version"` // required VectorString string `json:"vectorString"` // required - AttackVector *CVSS30AttackVector `json:"attackVector"` - AttackComplexity *CVSS30AttackComplexity `json:"attackComplexity"` - PrivilegesRequired *CVSS30PrivilegesRequired `json:"privilegesRequired"` - UserInteraction *CVSS30UserInteraction `json:"userInteraction"` - Scope *CVSS30Scope `json:"scope"` - ConfidentialityImpact *CVSS30Cia `json:"confidentialityImpact"` - IntegrityImpact CVSS30Cia `json:"integrityImpact"` - AvailabilityImpact *CVSS30Cia `json:"availabilityImpact"` + AttackVector *CVSS30AttackVector `json:"attackVector,omitempty"` + AttackComplexity *CVSS30AttackComplexity `json:"attackComplexity,omitempty"` + PrivilegesRequired *CVSS30PrivilegesRequired `json:"privilegesRequired,omitempty"` + UserInteraction *CVSS30UserInteraction `json:"userInteraction,omitempty"` + Scope *CVSS30Scope `json:"scope,omitempty"` + ConfidentialityImpact *CVSS30Cia `json:"confidentialityImpact,omitempty"` + IntegrityImpact CVSS30Cia `json:"integrityImpact,omitempty"` + AvailabilityImpact *CVSS30Cia `json:"availabilityImpact,omitempty"` BaseScore float64 `json:"baseScore"` // required BaseSeverity CVSS30Severity `json:"baseSeverity"` // required - ExploitCodeMaturity *CVSS30ExploitCodeMaturity `json:"exploitCodeMaturity"` - RemediationLevel *CVSS30RemediationLevel `json:"remediationLevel"` - ReportConfidence *CVSS30Confidence `json:"reportConfidence"` - TemporalScore *float64 `json:"temporalScore"` - TemporalSeverity *CVSS30Severity `json:"temporalSeverity"` - ConfidentialityRequirement *CVSS30CiaRequirement `json:"confidentialityRequirement"` - IntegrityRequirement *CVSS30CiaRequirement `json:"integrityRequirement"` - AvailabilityRequirement *CVSS30CiaRequirement `json:"availabilityRequirement"` - ModifiedAttackVector *CVSS30ModifiedAttackVector `json:"modifiedAttackVector"` - ModifiedAttackComplexity *CVSS30ModifiedAttackComplexity `json:"modifiedAttackComplexity"` - ModifiedPrivilegesRequired *CVSS30ModifiedPrivilegesRequired `json:"modifiedPrivilegesRequired"` - ModifiedUserInteraction *CVSS30ModifiedUserInteraction `json:"modifiedUserInteraction"` - ModifiedScope *CVSS30ModifiedScope `json:"modifiedScope"` - ModifiedConfidentialityImpact *CVSS30ModifiedCia `json:"modifiedConfidentialityImpact"` - ModifiedIntegrityImpact *CVSS30ModifiedCia `json:"modifiedIntegrityImpact"` - ModifiedAvailabilityImpact *CVSS30ModifiedCia `json:"modifiedAvailabilityImpact"` - EenvironmentalScore *float64 `json:"environmentalScore"` - EnvironmentalSeverity *CVSS30Severity `json:"environmentalSeverity"` + ExploitCodeMaturity *CVSS30ExploitCodeMaturity `json:"exploitCodeMaturity,omitempty"` + RemediationLevel *CVSS30RemediationLevel `json:"remediationLevel,omitempty"` + ReportConfidence *CVSS30Confidence `json:"reportConfidence,omitempty"` + TemporalScore *float64 `json:"temporalScore,omitempty"` + TemporalSeverity *CVSS30Severity `json:"temporalSeverity,omitempty"` + ConfidentialityRequirement *CVSS30CiaRequirement `json:"confidentialityRequirement,omitempty"` + IntegrityRequirement *CVSS30CiaRequirement `json:"integrityRequirement,omitempty"` + AvailabilityRequirement *CVSS30CiaRequirement `json:"availabilityRequirement,omitempty"` + ModifiedAttackVector *CVSS30ModifiedAttackVector `json:"modifiedAttackVector,omitempty"` + ModifiedAttackComplexity *CVSS30ModifiedAttackComplexity `json:"modifiedAttackComplexity,omitempty"` + ModifiedPrivilegesRequired *CVSS30ModifiedPrivilegesRequired `json:"modifiedPrivilegesRequired,omitempty"` + ModifiedUserInteraction *CVSS30ModifiedUserInteraction `json:"modifiedUserInteraction,omitempty"` + ModifiedScope *CVSS30ModifiedScope `json:"modifiedScope,omitempty"` + ModifiedConfidentialityImpact *CVSS30ModifiedCia `json:"modifiedConfidentialityImpact,omitempty"` + ModifiedIntegrityImpact *CVSS30ModifiedCia `json:"modifiedIntegrityImpact,omitempty"` + ModifiedAvailabilityImpact *CVSS30ModifiedCia `json:"modifiedAvailabilityImpact,omitempty"` + EenvironmentalScore *float64 `json:"environmentalScore,omitempty"` + EnvironmentalSeverity *CVSS30Severity `json:"environmentalSeverity,omitempty"` } // Score specifies information about (at least one) score of the vulnerability and for which From 3acabdf73b857dbc0bf1d873df7c915d8f4e9905 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Mon, 4 Sep 2023 17:41:44 +0200 Subject: [PATCH 06/24] reusing TLPLabel and Category from models.go --- csaf/advisory.go | 78 +++++------------------------------------------- 1 file changed, 7 insertions(+), 71 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index 39604a8..3772db6 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -222,30 +222,10 @@ const CSAFVersion20 CSAFVersion = "2.0" var CSAFVersionPattern = alternativesUnmarshal(string(CSAFVersion20)) -// DocumentTLPLabel is the label of a TLP. -type DocumentTLPLabel string - -const ( - // DocumentTLPLabelAmber is the "AMBER" label. - DocumentTLPLabelAmber DocumentTLPLabel = "AMBER" - // DocumentTLPLabelGreen is the "GREEN" label. - DocumentTLPLabelGreen DocumentTLPLabel = "GREEN" - // DocumentTLPLabelRed is the "RED" label. - DocumentTLPLabelRed DocumentTLPLabel = "RED" - // DocumentTLPLabelWhite is the "WHITE" label. - DocumentTLPLabelWhite DocumentTLPLabel = "WHITE" -) - -var csafDocumentTLPLabelPattern = alternativesUnmarshal( - string(DocumentTLPLabelAmber), - string(DocumentTLPLabelGreen), - string(DocumentTLPLabelRed), - string(DocumentTLPLabelWhite)) - // TLP provides details about the TLP classification of the document. type TLP struct { - DocumentTLPLabel DocumentTLPLabel `json:"label"` // required - URL *string `json:"url,omitempty"` + DocumentTLPLabel TLPLabel `json:"label"` // required + URL *string `json:"url,omitempty"` } // DocumentDistribution describes rules for sharing a document. @@ -254,39 +234,13 @@ type DocumentDistribution struct { TLP *TLP `json:"tlp,omitempty"` } -// PublisherCategory is the category of a publisher. -type PublisherCategory string - -const ( - // CSAFPublisherCategoryCoordinator is the "coordinator" category. - CSAFPublisherCategoryCoordinator PublisherCategory = "coordinator" - // CSAFPublisherCategoryDiscoverer is the "discoverer" category. - CSAFPublisherCategoryDiscoverer PublisherCategory = "discoverer" - // CSAFPublisherCategoryOther is the "other" category. - CSAFPublisherCategoryOther PublisherCategory = "other" - // CSAFPublisherCategoryTranslator is the "translator" category. - CSAFPublisherCategoryTranslator PublisherCategory = "translator" - // CSAFPublisherCategoryUser is the "user" category. - CSAFPublisherCategoryUser PublisherCategory = "user" - // CSAFPublisherCategoryVendor is the "vendor" category. - CSAFPublisherCategoryVendor PublisherCategory = "vendor" -) - -var csafPublisherCategoryPattern = alternativesUnmarshal( - string(CSAFPublisherCategoryCoordinator), - string(CSAFPublisherCategoryDiscoverer), - string(CSAFPublisherCategoryOther), - string(CSAFPublisherCategoryTranslator), - string(CSAFPublisherCategoryUser), - string(CSAFPublisherCategoryVendor)) - // DocumentPublisher provides information about the publishing entity. type DocumentPublisher struct { - Category PublisherCategory `json:"category"` // required - ContactDetails *string `json:"contact_details,omitempty"` - IssuingAuthority *string `json:"issuing_authority,omitempty"` - Name string `json:"name"` // required - Namespace string `json:"namespace"` // required + Category Category `json:"category"` // required + ContactDetails *string `json:"contact_details,omitempty"` + IssuingAuthority *string `json:"issuing_authority,omitempty"` + Name string `json:"name"` // required + Namespace string `json:"namespace"` // required } // The version specifies a version string to denote clearly the evolution of the content of the document. @@ -836,24 +790,6 @@ func (rc *ReferenceCategory) UnmarshalText(data []byte) error { return err } -// UnmarshalText implements the encoding.TextUnmarshaller interface. -func (dtl *DocumentTLPLabel) UnmarshalText(data []byte) error { - s, err := csafDocumentTLPLabelPattern(data) - if err == nil { - *dtl = DocumentTLPLabel(s) - } - return err -} - -// UnmarshalText implements the encoding.TextUnmarshaller interface. -func (pc *PublisherCategory) UnmarshalText(data []byte) error { - s, err := csafPublisherCategoryPattern(data) - if err == nil { - *pc = PublisherCategory(s) - } - return err -} - // UnmarshalText implements the encoding.TextUnmarshaller interface. func (ts *TrackingStatus) UnmarshalText(data []byte) error { s, err := csafTrackingStatusPattern(data) From 7f36ecb48c338e4c6a42ed73d435cce0fe986e77 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Tue, 5 Sep 2023 16:41:52 +0200 Subject: [PATCH 07/24] added missing types for CVSS2 + changed variable names for more consistency --- csaf/advisory.go | 87 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 28 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index 3772db6..b25a5f7 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -587,28 +587,41 @@ type Remediation struct { URL *string `json:"url,omitempty"` } -// CVSSv3Version is the version of a CVSSv3 item. -type CVSSv3Version string +// CVSSVersion2 is the version of a CVSS2 item. +type CVSSVersion2 string -// CVSSv3Version30 is version 3.0 of a CVSSv3 item. -const CVSSv3Version30 CVSSv3Version = "3.0" +// MetadataVersion20 is the current version of the schema. +const CVSSVersion20 CVSSVersion2 = "2.0" -// CVSSv3Version31 is version 3.1 of a CVSSv3 item. -const CVSSv3Version31 CVSSv3Version = "3.1" +var CVSSVersion2Pattern = alternativesUnmarshal(string(CVSSVersion20)) -// CVSSv3VectorString is the VectorString of a CVSSv3 item with version 3.x. -type CVSSv3VectorString string +// CVSS2VectorString is the VectorString of a CVSS2 item with version 3.x. +type CVSS2VectorString string -var CVSSv3VectorStringPattern = patternUnmarshal(`^CVSS:3[.][01]/((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])$`) +var CVSS2VectorStringPattern = patternUnmarshal(`^((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))$`) -var CVSSv3VersionPattern = alternativesUnmarshal( - string(CVSSv3Version30), - string(CVSSv3Version31)) +// CVSSVersion3 is the version of a CVSS3 item. +type CVSSVersion3 string -// CVSSv2 holding a CVSS v2.0 value -type CVSSv2 struct { - Version string `json:"version"` // required - VectorString string `json:"vectorString"` // required +// CVSS3Version30 is version 3.0 of a CVSS3 item. +const CVSSVersion30 CVSSVersion3 = "3.0" + +// CVSSVersion31 is version 3.1 of a CVSS3 item. +const CVSSVersion31 CVSSVersion3 = "3.1" + +var CVSS3VersionPattern = alternativesUnmarshal( + string(CVSSVersion30), + string(CVSSVersion31)) + +// CVSS3VectorString is the VectorString of a CVSS3 item with version 3.x. +type CVSS3VectorString string + +var CVSS3VectorStringPattern = patternUnmarshal(`^CVSS:3[.][01]/((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])$`) + +// CVSS2 holding a CVSS v2.0 value +type CVSS2 struct { + Version CVSSVersion2 `json:"version"` // required + VectorString CVSS2VectorString `json:"vectorString"` // required AccessVector *CVSS20AccessVector `json:"accessVector,omitempty"` AccessComplexity *CVSS20AccessComplexity `json:"accessComplexity,omitempty"` Authentication *CVSS20Authentication `json:"authentication,omitempty"` @@ -628,10 +641,10 @@ type CVSSv2 struct { EnvironmentalScore *float64 `json:"environmentalScore,omitempty"` } -// CVSSv3 holding a CVSS v3.x value -type CVSSv3 struct { - Version string `json:"version"` // required - VectorString string `json:"vectorString"` // required +// CVSS3 holding a CVSS v3.x value +type CVSS3 struct { + Version CVSSVersion3 `json:"version"` // required + VectorString CVSS3VectorString `json:"vectorString"` // required AttackVector *CVSS30AttackVector `json:"attackVector,omitempty"` AttackComplexity *CVSS30AttackComplexity `json:"attackComplexity,omitempty"` PrivilegesRequired *CVSS30PrivilegesRequired `json:"privilegesRequired,omitempty"` @@ -665,8 +678,8 @@ type CVSSv3 struct { // Score specifies information about (at least one) score of the vulnerability and for which // products the given value applies. A Score item has at least 2 properties. type Score struct { - CVSSv2 *CVSSv2 `json:"cvss_v2,omitempty"` - CVSSv3 *CVSSv3 `json:"cvss_v3,omitempty"` + CVSS2 *CVSS2 `json:"cvss_v2,omitempty"` + CVSS3 *CVSS3 `json:"cvss_v3,omitempty"` Products *Products `json:"products"` // required } @@ -953,19 +966,37 @@ func (wi *WeaknessID) UnmarshalText(data []byte) error { } // UnmarshalText implements the encoding.TextUnmarshaller interface. -func (cv *CVSSv3Version) UnmarshalText(data []byte) error { - s, err := CVSSv3VersionPattern(data) +func (cv *CVSSVersion2) UnmarshalText(data []byte) error { + s, err := CVSSVersion2Pattern(data) if err == nil { - *cv = CVSSv3Version(s) + *cv = CVSSVersion2(s) } return err } // UnmarshalText implements the encoding.TextUnmarshaller interface. -func (cvs *CVSSv3VectorString) UnmarshalText(data []byte) error { - s, err := CVSSv3VectorStringPattern(data) +func (cvs *CVSS2VectorString) UnmarshalText(data []byte) error { + s, err := CVSS2VectorStringPattern(data) if err == nil { - *cvs = CVSSv3VectorString(s) + *cvs = CVSS2VectorString(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (cv *CVSSVersion3) UnmarshalText(data []byte) error { + s, err := CVSS3VersionPattern(data) + if err == nil { + *cv = CVSSVersion3(s) + } + return err +} + +// UnmarshalText implements the encoding.TextUnmarshaller interface. +func (cvs *CVSS3VectorString) UnmarshalText(data []byte) error { + s, err := CVSS3VectorStringPattern(data) + if err == nil { + *cvs = CVSS3VectorString(s) } return err } From 22ef2a925ecc93cc63ac467c076f90d822ce19d1 Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Tue, 5 Sep 2023 19:14:57 +0200 Subject: [PATCH 08/24] Unexport patterns --- csaf/advisory.go | 92 ++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index b25a5f7..a55e29e 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -78,7 +78,7 @@ type Products []ProductID // FileHashValue represents the value of a hash. type FileHashValue string -var FileHashValuePattern = patternUnmarshal(`^[0-9a-fA-F]{32,}$`) +var fileHashValuePattern = patternUnmarshal(`^[0-9a-fA-F]{32,}$`) // FileHash is checksum hash. // Values for 'algorithm' are derived from the currently supported digests OpenSSL. Leading dashes were removed. @@ -96,12 +96,12 @@ type Hashes struct { // CPE represents a Common Platform Enumeration in an advisory. type CPE string -var CPEPattern = patternUnmarshal("^(cpe:2\\.3:[aho\\*\\-](:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#\\$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|\\}~]))+(\\?*|\\*?))|[\\*\\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\\*\\-]))(:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#\\$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|\\}~]))+(\\?*|\\*?))|[\\*\\-])){4})|([c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6})$") +var cpePattern = patternUnmarshal("^(cpe:2\\.3:[aho\\*\\-](:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#\\$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|\\}~]))+(\\?*|\\*?))|[\\*\\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\\*\\-]))(:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#\\$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|\\}~]))+(\\?*|\\*?))|[\\*\\-])){4})|([c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6})$") // PURL represents a package URL in an advisory. type PURL string -var PURLPattern = patternUnmarshal(`^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*/.+`) +var pURLPattern = patternUnmarshal(`^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*/.+`) // XGenericURI represents an identifier for a product. type XGenericURI struct { @@ -212,15 +212,15 @@ type AggregateSeverity struct { // DocumentCategory represents a category of a document. type DocumentCategory string -var DocumentCategoryPattern = patternUnmarshal(`^[^\\s\\-_\\.](.*[^\\s\\-_\\.])?$`) +var documentCategoryPattern = patternUnmarshal(`^[^\\s\\-_\\.](.*[^\\s\\-_\\.])?$`) -// CSAFVersion is the version of a document. -type CSAFVersion string +// Version is the version of a document. +type Version string -// CSAFVersion is the current version of CSAF. -const CSAFVersion20 CSAFVersion = "2.0" +// CSAFVersion20 is the current version of CSAF. +const CSAFVersion20 Version = "2.0" -var CSAFVersionPattern = alternativesUnmarshal(string(CSAFVersion20)) +var csafVersionPattern = alternativesUnmarshal(string(CSAFVersion20)) // TLP provides details about the TLP classification of the document. type TLP struct { @@ -243,10 +243,10 @@ type DocumentPublisher struct { Namespace string `json:"namespace"` // required } -// The version specifies a version string to denote clearly the evolution of the content of the document. -type Version string +// RevisionNumber specifies a version string to denote clearly the evolution of the content of the document. +type RevisionNumber string -var VersionPattern = patternUnmarshal(`^(0|[1-9][0-9]*)$|^((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*) +var versionPattern = patternUnmarshal(`^(0|[1-9][0-9]*)$|^((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*) (?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)$`) // Engine contains information about the engine that generated the CSAF document. @@ -266,14 +266,14 @@ type Generator struct { // TrackingID is a unique identifier for the document. type TrackingID string -var TrackingIDPattern = patternUnmarshal("^[\\S](.*[\\S])?$") +var trackingIDPattern = patternUnmarshal("^[\\S](.*[\\S])?$") // Revision contains information about one revision of the document. type Revision struct { - Date string `json:"date"` // required - LegacyVersion *string `json:"legacy_version,omitempty"` - Number Version `json:"number"` // required - Summary string `json:"summary"` // required + Date string `json:"date"` // required + LegacyVersion *string `json:"legacy_version,omitempty"` + Number RevisionNumber `json:"number"` // required + Summary string `json:"summary"` // required } // TrackingStatus is the category of a publisher. @@ -302,20 +302,20 @@ type Tracking struct { InitialReleaseDate string `json:"initial_release_date"` // required RevisionHistory []Revision `json:"revision_history"` // required Status TrackingStatus `json:"status"` // required - Version Version `json:"version"` // required + Version RevisionNumber `json:"version"` // required } // Lang is a language identifier, corresponding to IETF BCP 47 / RFC 5646. type Lang string -var LangPattern = patternUnmarshal("^(([A-Za-z]{2,3}(-[A-Za-z]{3}(-[A-Za-z]{3}){0,2})?|[A-Za-z]{4,8})(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-[A-WY-Za-wy-z0-9](-[A-Za-z0-9]{2,8})+)*(-[Xx](-[A-Za-z0-9]{1,8})+)?|[Xx](-[A-Za-z0-9]{1,8})+|[Ii]-[Dd][Ee][Ff][Aa][Uu][Ll][Tt]|[Ii]-[Mm][Ii][Nn][Gg][Oo])$") +var langPattern = patternUnmarshal("^(([A-Za-z]{2,3}(-[A-Za-z]{3}(-[A-Za-z]{3}){0,2})?|[A-Za-z]{4,8})(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-[A-WY-Za-wy-z0-9](-[A-Za-z0-9]{2,8})+)*(-[Xx](-[A-Za-z0-9]{1,8})+)?|[Xx](-[A-Za-z0-9]{1,8})+|[Ii]-[Dd][Ee][Ff][Aa][Uu][Ll][Tt]|[Ii]-[Mm][Ii][Nn][Gg][Oo])$") // Document contains meta-data about an advisory. type Document struct { Acknowledgements []Acknowledgement `json:"acknowledgements,omitempty"` AggregateSeverity *AggregateSeverity `json:"aggregate_severity,omitempty"` Category DocumentCategory `json:"category"` // required - CSAFVersion CSAFVersion `json:"csaf_version"` // required + CSAFVersion Version `json:"csaf_version"` // required Distribution *DocumentDistribution `json:"distribution,omitempty"` Lang *Lang `json:"lang,omitempty"` Notes []*Note `json:"notes,omitempty"` @@ -384,12 +384,12 @@ type ProductTree struct { // CVE holds the MITRE standard Common Vulnerabilities and Exposures (CVE) tracking number for a vulnerability. type CVE string -var CVEPattern = patternUnmarshal("^CVE-[0-9]{4}-[0-9]{4,}$") +var cvePattern = patternUnmarshal("^CVE-[0-9]{4}-[0-9]{4,}$") // WeaknessID is the identifier of a weakness. type WeaknessID string -var WeaknessIDPattern = patternUnmarshal("^CWE-[1-9]\\d{0,5}$") +var weaknessIDPattern = patternUnmarshal("^CWE-[1-9]\\d{0,5}$") // CWE holds the MITRE standard Common Weakness Enumeration (CWE) for the weakness associated. type CWE struct { @@ -590,33 +590,33 @@ type Remediation struct { // CVSSVersion2 is the version of a CVSS2 item. type CVSSVersion2 string -// MetadataVersion20 is the current version of the schema. +// CVSSVersion20 is the current version of the schema. const CVSSVersion20 CVSSVersion2 = "2.0" -var CVSSVersion2Pattern = alternativesUnmarshal(string(CVSSVersion20)) +var cvssVersion2Pattern = alternativesUnmarshal(string(CVSSVersion20)) // CVSS2VectorString is the VectorString of a CVSS2 item with version 3.x. type CVSS2VectorString string -var CVSS2VectorStringPattern = patternUnmarshal(`^((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))$`) +var cvss2VectorStringPattern = patternUnmarshal(`^((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))$`) // CVSSVersion3 is the version of a CVSS3 item. type CVSSVersion3 string -// CVSS3Version30 is version 3.0 of a CVSS3 item. +// CVSSVersion30 is version 3.0 of a CVSS3 item. const CVSSVersion30 CVSSVersion3 = "3.0" // CVSSVersion31 is version 3.1 of a CVSS3 item. const CVSSVersion31 CVSSVersion3 = "3.1" -var CVSS3VersionPattern = alternativesUnmarshal( +var cvss3VersionPattern = alternativesUnmarshal( string(CVSSVersion30), string(CVSSVersion31)) // CVSS3VectorString is the VectorString of a CVSS3 item with version 3.x. type CVSS3VectorString string -var CVSS3VectorStringPattern = patternUnmarshal(`^CVSS:3[.][01]/((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])$`) +var cvss3VectorStringPattern = patternUnmarshal(`^CVSS:3[.][01]/((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])$`) // CVSS2 holding a CVSS v2.0 value type CVSS2 struct { @@ -877,7 +877,7 @@ func (tc *ThreatCategory) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (cpe *CPE) UnmarshalText(data []byte) error { - s, err := CPEPattern(data) + s, err := cpePattern(data) if err == nil { *cpe = CPE(s) } @@ -886,7 +886,7 @@ func (cpe *CPE) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (fhv *FileHashValue) UnmarshalText(data []byte) error { - s, err := FileHashValuePattern(data) + s, err := fileHashValuePattern(data) if err == nil { *fhv = FileHashValue(s) } @@ -895,7 +895,7 @@ func (fhv *FileHashValue) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (p *PURL) UnmarshalText(data []byte) error { - s, err := PURLPattern(data) + s, err := pURLPattern(data) if err == nil { *p = PURL(s) } @@ -904,7 +904,7 @@ func (p *PURL) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (l *Lang) UnmarshalText(data []byte) error { - s, err := LangPattern(data) + s, err := langPattern(data) if err == nil { *l = Lang(s) } @@ -912,17 +912,17 @@ func (l *Lang) UnmarshalText(data []byte) error { } // UnmarshalText implements the encoding.TextUnmarshaller interface. -func (v *Version) UnmarshalText(data []byte) error { - s, err := VersionPattern(data) +func (v *RevisionNumber) UnmarshalText(data []byte) error { + s, err := versionPattern(data) if err == nil { - *v = Version(s) + *v = RevisionNumber(s) } return err } // UnmarshalText implements the encoding.TextUnmarshaller interface. func (dc *DocumentCategory) UnmarshalText(data []byte) error { - s, err := DocumentCategoryPattern(data) + s, err := documentCategoryPattern(data) if err == nil { *dc = DocumentCategory(s) } @@ -930,17 +930,17 @@ func (dc *DocumentCategory) UnmarshalText(data []byte) error { } // UnmarshalText implements the encoding.TextUnmarshaller interface. -func (cv *CSAFVersion) UnmarshalText(data []byte) error { - s, err := CSAFVersionPattern(data) +func (cv *Version) UnmarshalText(data []byte) error { + s, err := csafVersionPattern(data) if err == nil { - *cv = CSAFVersion(s) + *cv = Version(s) } return err } // UnmarshalText implements the encoding.TextUnmarshaller interface. func (ti *TrackingID) UnmarshalText(data []byte) error { - s, err := TrackingIDPattern(data) + s, err := trackingIDPattern(data) if err == nil { *ti = TrackingID(s) } @@ -949,7 +949,7 @@ func (ti *TrackingID) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (cve *CVE) UnmarshalText(data []byte) error { - s, err := CVEPattern(data) + s, err := cvePattern(data) if err == nil { *cve = CVE(s) } @@ -958,7 +958,7 @@ func (cve *CVE) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (wi *WeaknessID) UnmarshalText(data []byte) error { - s, err := WeaknessIDPattern(data) + s, err := weaknessIDPattern(data) if err == nil { *wi = WeaknessID(s) } @@ -967,7 +967,7 @@ func (wi *WeaknessID) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (cv *CVSSVersion2) UnmarshalText(data []byte) error { - s, err := CVSSVersion2Pattern(data) + s, err := cvssVersion2Pattern(data) if err == nil { *cv = CVSSVersion2(s) } @@ -976,7 +976,7 @@ func (cv *CVSSVersion2) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (cvs *CVSS2VectorString) UnmarshalText(data []byte) error { - s, err := CVSS2VectorStringPattern(data) + s, err := cvss2VectorStringPattern(data) if err == nil { *cvs = CVSS2VectorString(s) } @@ -985,7 +985,7 @@ func (cvs *CVSS2VectorString) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (cv *CVSSVersion3) UnmarshalText(data []byte) error { - s, err := CVSS3VersionPattern(data) + s, err := cvss3VersionPattern(data) if err == nil { *cv = CVSSVersion3(s) } @@ -994,7 +994,7 @@ func (cv *CVSSVersion3) UnmarshalText(data []byte) error { // UnmarshalText implements the encoding.TextUnmarshaller interface. func (cvs *CVSS3VectorString) UnmarshalText(data []byte) error { - s, err := CVSS3VectorStringPattern(data) + s, err := cvss3VectorStringPattern(data) if err == nil { *cvs = CVSS3VectorString(s) } From f45d273af928d566950865d6664f3d8e2e67d0cd Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Tue, 5 Sep 2023 19:53:48 +0200 Subject: [PATCH 09/24] fixed versionPattern --- csaf/advisory.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index a55e29e..4732ed3 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -246,8 +246,7 @@ type DocumentPublisher struct { // RevisionNumber specifies a version string to denote clearly the evolution of the content of the document. type RevisionNumber string -var versionPattern = patternUnmarshal(`^(0|[1-9][0-9]*)$|^((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*) - (?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)$`) +var versionPattern = patternUnmarshal("^(0|[1-9][0-9]*)$|^((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)$") // Engine contains information about the engine that generated the CSAF document. type Engine struct { From b03df5508a717e977155e49c9db91aa5a59ebc80 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Wed, 6 Sep 2023 15:44:56 +0200 Subject: [PATCH 10/24] added explanation for cvss3VectorStringPattern --- csaf/advisory.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/csaf/advisory.go b/csaf/advisory.go index 4732ed3..16d3503 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -615,6 +615,8 @@ var cvss3VersionPattern = alternativesUnmarshal( // CVSS3VectorString is the VectorString of a CVSS3 item with version 3.x. type CVSS3VectorString string +// cvss3VectorStringPattern is a combination of the vectorString patterns of CVSS 3.0 +// and CVSS 3.1 since the only difference is the number directly after the first dot. var cvss3VectorStringPattern = patternUnmarshal(`^CVSS:3[.][01]/((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])$`) // CVSS2 holding a CVSS v2.0 value From 4206c2e4b370899ca1d313f67c79f5e053fd96d8 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Wed, 6 Sep 2023 15:51:47 +0200 Subject: [PATCH 11/24] only using enums from CVSS 3.0 --- csaf/advisory.go | 60 +++--- csaf/cvss30enums.go | 500 -------------------------------------------- csaf/cvss31enums.go | 500 -------------------------------------------- csaf/cvss3enums.go | 500 ++++++++++++++++++++++++++++++++++++++++++++ csaf/doc.go | 5 +- 5 files changed, 533 insertions(+), 1032 deletions(-) delete mode 100644 csaf/cvss30enums.go delete mode 100644 csaf/cvss31enums.go create mode 100644 csaf/cvss3enums.go diff --git a/csaf/advisory.go b/csaf/advisory.go index 16d3503..1fb8a5d 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -644,36 +644,36 @@ type CVSS2 struct { // CVSS3 holding a CVSS v3.x value type CVSS3 struct { - Version CVSSVersion3 `json:"version"` // required - VectorString CVSS3VectorString `json:"vectorString"` // required - AttackVector *CVSS30AttackVector `json:"attackVector,omitempty"` - AttackComplexity *CVSS30AttackComplexity `json:"attackComplexity,omitempty"` - PrivilegesRequired *CVSS30PrivilegesRequired `json:"privilegesRequired,omitempty"` - UserInteraction *CVSS30UserInteraction `json:"userInteraction,omitempty"` - Scope *CVSS30Scope `json:"scope,omitempty"` - ConfidentialityImpact *CVSS30Cia `json:"confidentialityImpact,omitempty"` - IntegrityImpact CVSS30Cia `json:"integrityImpact,omitempty"` - AvailabilityImpact *CVSS30Cia `json:"availabilityImpact,omitempty"` - BaseScore float64 `json:"baseScore"` // required - BaseSeverity CVSS30Severity `json:"baseSeverity"` // required - ExploitCodeMaturity *CVSS30ExploitCodeMaturity `json:"exploitCodeMaturity,omitempty"` - RemediationLevel *CVSS30RemediationLevel `json:"remediationLevel,omitempty"` - ReportConfidence *CVSS30Confidence `json:"reportConfidence,omitempty"` - TemporalScore *float64 `json:"temporalScore,omitempty"` - TemporalSeverity *CVSS30Severity `json:"temporalSeverity,omitempty"` - ConfidentialityRequirement *CVSS30CiaRequirement `json:"confidentialityRequirement,omitempty"` - IntegrityRequirement *CVSS30CiaRequirement `json:"integrityRequirement,omitempty"` - AvailabilityRequirement *CVSS30CiaRequirement `json:"availabilityRequirement,omitempty"` - ModifiedAttackVector *CVSS30ModifiedAttackVector `json:"modifiedAttackVector,omitempty"` - ModifiedAttackComplexity *CVSS30ModifiedAttackComplexity `json:"modifiedAttackComplexity,omitempty"` - ModifiedPrivilegesRequired *CVSS30ModifiedPrivilegesRequired `json:"modifiedPrivilegesRequired,omitempty"` - ModifiedUserInteraction *CVSS30ModifiedUserInteraction `json:"modifiedUserInteraction,omitempty"` - ModifiedScope *CVSS30ModifiedScope `json:"modifiedScope,omitempty"` - ModifiedConfidentialityImpact *CVSS30ModifiedCia `json:"modifiedConfidentialityImpact,omitempty"` - ModifiedIntegrityImpact *CVSS30ModifiedCia `json:"modifiedIntegrityImpact,omitempty"` - ModifiedAvailabilityImpact *CVSS30ModifiedCia `json:"modifiedAvailabilityImpact,omitempty"` - EenvironmentalScore *float64 `json:"environmentalScore,omitempty"` - EnvironmentalSeverity *CVSS30Severity `json:"environmentalSeverity,omitempty"` + Version CVSSVersion3 `json:"version"` // required + VectorString CVSS3VectorString `json:"vectorString"` // required + AttackVector *CVSS3AttackVector `json:"attackVector,omitempty"` + AttackComplexity *CVSS3AttackComplexity `json:"attackComplexity,omitempty"` + PrivilegesRequired *CVSS3PrivilegesRequired `json:"privilegesRequired,omitempty"` + UserInteraction *CVSS3UserInteraction `json:"userInteraction,omitempty"` + Scope *CVSS3Scope `json:"scope,omitempty"` + ConfidentialityImpact *CVSS3Cia `json:"confidentialityImpact,omitempty"` + IntegrityImpact CVSS3Cia `json:"integrityImpact,omitempty"` + AvailabilityImpact *CVSS3Cia `json:"availabilityImpact,omitempty"` + BaseScore float64 `json:"baseScore"` // required + BaseSeverity CVSS3Severity `json:"baseSeverity"` // required + ExploitCodeMaturity *CVSS3ExploitCodeMaturity `json:"exploitCodeMaturity,omitempty"` + RemediationLevel *CVSS3RemediationLevel `json:"remediationLevel,omitempty"` + ReportConfidence *CVSS3Confidence `json:"reportConfidence,omitempty"` + TemporalScore *float64 `json:"temporalScore,omitempty"` + TemporalSeverity *CVSS3Severity `json:"temporalSeverity,omitempty"` + ConfidentialityRequirement *CVSS3CiaRequirement `json:"confidentialityRequirement,omitempty"` + IntegrityRequirement *CVSS3CiaRequirement `json:"integrityRequirement,omitempty"` + AvailabilityRequirement *CVSS3CiaRequirement `json:"availabilityRequirement,omitempty"` + ModifiedAttackVector *CVSS3ModifiedAttackVector `json:"modifiedAttackVector,omitempty"` + ModifiedAttackComplexity *CVSS3ModifiedAttackComplexity `json:"modifiedAttackComplexity,omitempty"` + ModifiedPrivilegesRequired *CVSS3ModifiedPrivilegesRequired `json:"modifiedPrivilegesRequired,omitempty"` + ModifiedUserInteraction *CVSS3ModifiedUserInteraction `json:"modifiedUserInteraction,omitempty"` + ModifiedScope *CVSS3ModifiedScope `json:"modifiedScope,omitempty"` + ModifiedConfidentialityImpact *CVSS3ModifiedCia `json:"modifiedConfidentialityImpact,omitempty"` + ModifiedIntegrityImpact *CVSS3ModifiedCia `json:"modifiedIntegrityImpact,omitempty"` + ModifiedAvailabilityImpact *CVSS3ModifiedCia `json:"modifiedAvailabilityImpact,omitempty"` + EenvironmentalScore *float64 `json:"environmentalScore,omitempty"` + EnvironmentalSeverity *CVSS3Severity `json:"environmentalSeverity,omitempty"` } // Score specifies information about (at least one) score of the vulnerability and for which diff --git a/csaf/cvss30enums.go b/csaf/cvss30enums.go deleted file mode 100644 index 7524174..0000000 --- a/csaf/cvss30enums.go +++ /dev/null @@ -1,500 +0,0 @@ -// This file is Free Software under the MIT License -// without warranty, see README.md and LICENSES/MIT.txt for details. -// -// SPDX-License-Identifier: MIT -// -// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) -// Software-Engineering: 2023 Intevation GmbH -// -// THIS FILE IS MACHINE GENERATED. EDIT WITH CARE! - -package csaf - -// CVSS30AttackComplexity represents the attackComplexityType in CVSS30. -type CVSS30AttackComplexity string - -const ( - // CVSS30AttackComplexityHigh is a constant for "HIGH". - CVSS30AttackComplexityHigh CVSS30AttackComplexity = "HIGH" - // CVSS30AttackComplexityLow is a constant for "LOW". - CVSS30AttackComplexityLow CVSS30AttackComplexity = "LOW" -) - -var cvss30AttackComplexityPattern = alternativesUnmarshal( - string(CVSS30AttackComplexityHigh), - string(CVSS30AttackComplexityLow), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30AttackComplexity) UnmarshalText(data []byte) error { - s, err := cvss30AttackComplexityPattern(data) - if err == nil { - *e = CVSS30AttackComplexity(s) - } - return err -} - -// CVSS30AttackVector represents the attackVectorType in CVSS30. -type CVSS30AttackVector string - -const ( - // CVSS30AttackVectorNetwork is a constant for "NETWORK". - CVSS30AttackVectorNetwork CVSS30AttackVector = "NETWORK" - // CVSS30AttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". - CVSS30AttackVectorAdjacentNetwork CVSS30AttackVector = "ADJACENT_NETWORK" - // CVSS30AttackVectorLocal is a constant for "LOCAL". - CVSS30AttackVectorLocal CVSS30AttackVector = "LOCAL" - // CVSS30AttackVectorPhysical is a constant for "PHYSICAL". - CVSS30AttackVectorPhysical CVSS30AttackVector = "PHYSICAL" -) - -var cvss30AttackVectorPattern = alternativesUnmarshal( - string(CVSS30AttackVectorNetwork), - string(CVSS30AttackVectorAdjacentNetwork), - string(CVSS30AttackVectorLocal), - string(CVSS30AttackVectorPhysical), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30AttackVector) UnmarshalText(data []byte) error { - s, err := cvss30AttackVectorPattern(data) - if err == nil { - *e = CVSS30AttackVector(s) - } - return err -} - -// CVSS30CiaRequirement represents the ciaRequirementType in CVSS30. -type CVSS30CiaRequirement string - -const ( - // CVSS30CiaRequirementLow is a constant for "LOW". - CVSS30CiaRequirementLow CVSS30CiaRequirement = "LOW" - // CVSS30CiaRequirementMedium is a constant for "MEDIUM". - CVSS30CiaRequirementMedium CVSS30CiaRequirement = "MEDIUM" - // CVSS30CiaRequirementHigh is a constant for "HIGH". - CVSS30CiaRequirementHigh CVSS30CiaRequirement = "HIGH" - // CVSS30CiaRequirementNotDefined is a constant for "NOT_DEFINED". - CVSS30CiaRequirementNotDefined CVSS30CiaRequirement = "NOT_DEFINED" -) - -var cvss30CiaRequirementPattern = alternativesUnmarshal( - string(CVSS30CiaRequirementLow), - string(CVSS30CiaRequirementMedium), - string(CVSS30CiaRequirementHigh), - string(CVSS30CiaRequirementNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30CiaRequirement) UnmarshalText(data []byte) error { - s, err := cvss30CiaRequirementPattern(data) - if err == nil { - *e = CVSS30CiaRequirement(s) - } - return err -} - -// CVSS30Cia represents the ciaType in CVSS30. -type CVSS30Cia string - -const ( - // CVSS30CiaNone is a constant for "NONE". - CVSS30CiaNone CVSS30Cia = "NONE" - // CVSS30CiaLow is a constant for "LOW". - CVSS30CiaLow CVSS30Cia = "LOW" - // CVSS30CiaHigh is a constant for "HIGH". - CVSS30CiaHigh CVSS30Cia = "HIGH" -) - -var cvss30CiaPattern = alternativesUnmarshal( - string(CVSS30CiaNone), - string(CVSS30CiaLow), - string(CVSS30CiaHigh), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30Cia) UnmarshalText(data []byte) error { - s, err := cvss30CiaPattern(data) - if err == nil { - *e = CVSS30Cia(s) - } - return err -} - -// CVSS30Confidence represents the confidenceType in CVSS30. -type CVSS30Confidence string - -const ( - // CVSS30ConfidenceUnknown is a constant for "UNKNOWN". - CVSS30ConfidenceUnknown CVSS30Confidence = "UNKNOWN" - // CVSS30ConfidenceReasonable is a constant for "REASONABLE". - CVSS30ConfidenceReasonable CVSS30Confidence = "REASONABLE" - // CVSS30ConfidenceConfirmed is a constant for "CONFIRMED". - CVSS30ConfidenceConfirmed CVSS30Confidence = "CONFIRMED" - // CVSS30ConfidenceNotDefined is a constant for "NOT_DEFINED". - CVSS30ConfidenceNotDefined CVSS30Confidence = "NOT_DEFINED" -) - -var cvss30ConfidencePattern = alternativesUnmarshal( - string(CVSS30ConfidenceUnknown), - string(CVSS30ConfidenceReasonable), - string(CVSS30ConfidenceConfirmed), - string(CVSS30ConfidenceNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30Confidence) UnmarshalText(data []byte) error { - s, err := cvss30ConfidencePattern(data) - if err == nil { - *e = CVSS30Confidence(s) - } - return err -} - -// CVSS30ExploitCodeMaturity represents the exploitCodeMaturityType in CVSS30. -type CVSS30ExploitCodeMaturity string - -const ( - // CVSS30ExploitCodeMaturityUnproven is a constant for "UNPROVEN". - CVSS30ExploitCodeMaturityUnproven CVSS30ExploitCodeMaturity = "UNPROVEN" - // CVSS30ExploitCodeMaturityProofOfConcept is a constant for "PROOF_OF_CONCEPT". - CVSS30ExploitCodeMaturityProofOfConcept CVSS30ExploitCodeMaturity = "PROOF_OF_CONCEPT" - // CVSS30ExploitCodeMaturityFunctional is a constant for "FUNCTIONAL". - CVSS30ExploitCodeMaturityFunctional CVSS30ExploitCodeMaturity = "FUNCTIONAL" - // CVSS30ExploitCodeMaturityHigh is a constant for "HIGH". - CVSS30ExploitCodeMaturityHigh CVSS30ExploitCodeMaturity = "HIGH" - // CVSS30ExploitCodeMaturityNotDefined is a constant for "NOT_DEFINED". - CVSS30ExploitCodeMaturityNotDefined CVSS30ExploitCodeMaturity = "NOT_DEFINED" -) - -var cvss30ExploitCodeMaturityPattern = alternativesUnmarshal( - string(CVSS30ExploitCodeMaturityUnproven), - string(CVSS30ExploitCodeMaturityProofOfConcept), - string(CVSS30ExploitCodeMaturityFunctional), - string(CVSS30ExploitCodeMaturityHigh), - string(CVSS30ExploitCodeMaturityNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30ExploitCodeMaturity) UnmarshalText(data []byte) error { - s, err := cvss30ExploitCodeMaturityPattern(data) - if err == nil { - *e = CVSS30ExploitCodeMaturity(s) - } - return err -} - -// CVSS30ModifiedAttackComplexity represents the modifiedAttackComplexityType in CVSS30. -type CVSS30ModifiedAttackComplexity string - -const ( - // CVSS30ModifiedAttackComplexityHigh is a constant for "HIGH". - CVSS30ModifiedAttackComplexityHigh CVSS30ModifiedAttackComplexity = "HIGH" - // CVSS30ModifiedAttackComplexityLow is a constant for "LOW". - CVSS30ModifiedAttackComplexityLow CVSS30ModifiedAttackComplexity = "LOW" - // CVSS30ModifiedAttackComplexityNotDefined is a constant for "NOT_DEFINED". - CVSS30ModifiedAttackComplexityNotDefined CVSS30ModifiedAttackComplexity = "NOT_DEFINED" -) - -var cvss30ModifiedAttackComplexityPattern = alternativesUnmarshal( - string(CVSS30ModifiedAttackComplexityHigh), - string(CVSS30ModifiedAttackComplexityLow), - string(CVSS30ModifiedAttackComplexityNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30ModifiedAttackComplexity) UnmarshalText(data []byte) error { - s, err := cvss30ModifiedAttackComplexityPattern(data) - if err == nil { - *e = CVSS30ModifiedAttackComplexity(s) - } - return err -} - -// CVSS30ModifiedAttackVector represents the modifiedAttackVectorType in CVSS30. -type CVSS30ModifiedAttackVector string - -const ( - // CVSS30ModifiedAttackVectorNetwork is a constant for "NETWORK". - CVSS30ModifiedAttackVectorNetwork CVSS30ModifiedAttackVector = "NETWORK" - // CVSS30ModifiedAttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". - CVSS30ModifiedAttackVectorAdjacentNetwork CVSS30ModifiedAttackVector = "ADJACENT_NETWORK" - // CVSS30ModifiedAttackVectorLocal is a constant for "LOCAL". - CVSS30ModifiedAttackVectorLocal CVSS30ModifiedAttackVector = "LOCAL" - // CVSS30ModifiedAttackVectorPhysical is a constant for "PHYSICAL". - CVSS30ModifiedAttackVectorPhysical CVSS30ModifiedAttackVector = "PHYSICAL" - // CVSS30ModifiedAttackVectorNotDefined is a constant for "NOT_DEFINED". - CVSS30ModifiedAttackVectorNotDefined CVSS30ModifiedAttackVector = "NOT_DEFINED" -) - -var cvss30ModifiedAttackVectorPattern = alternativesUnmarshal( - string(CVSS30ModifiedAttackVectorNetwork), - string(CVSS30ModifiedAttackVectorAdjacentNetwork), - string(CVSS30ModifiedAttackVectorLocal), - string(CVSS30ModifiedAttackVectorPhysical), - string(CVSS30ModifiedAttackVectorNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30ModifiedAttackVector) UnmarshalText(data []byte) error { - s, err := cvss30ModifiedAttackVectorPattern(data) - if err == nil { - *e = CVSS30ModifiedAttackVector(s) - } - return err -} - -// CVSS30ModifiedCia represents the modifiedCiaType in CVSS30. -type CVSS30ModifiedCia string - -const ( - // CVSS30ModifiedCiaNone is a constant for "NONE". - CVSS30ModifiedCiaNone CVSS30ModifiedCia = "NONE" - // CVSS30ModifiedCiaLow is a constant for "LOW". - CVSS30ModifiedCiaLow CVSS30ModifiedCia = "LOW" - // CVSS30ModifiedCiaHigh is a constant for "HIGH". - CVSS30ModifiedCiaHigh CVSS30ModifiedCia = "HIGH" - // CVSS30ModifiedCiaNotDefined is a constant for "NOT_DEFINED". - CVSS30ModifiedCiaNotDefined CVSS30ModifiedCia = "NOT_DEFINED" -) - -var cvss30ModifiedCiaPattern = alternativesUnmarshal( - string(CVSS30ModifiedCiaNone), - string(CVSS30ModifiedCiaLow), - string(CVSS30ModifiedCiaHigh), - string(CVSS30ModifiedCiaNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30ModifiedCia) UnmarshalText(data []byte) error { - s, err := cvss30ModifiedCiaPattern(data) - if err == nil { - *e = CVSS30ModifiedCia(s) - } - return err -} - -// CVSS30ModifiedPrivilegesRequired represents the modifiedPrivilegesRequiredType in CVSS30. -type CVSS30ModifiedPrivilegesRequired string - -const ( - // CVSS30ModifiedPrivilegesRequiredHigh is a constant for "HIGH". - CVSS30ModifiedPrivilegesRequiredHigh CVSS30ModifiedPrivilegesRequired = "HIGH" - // CVSS30ModifiedPrivilegesRequiredLow is a constant for "LOW". - CVSS30ModifiedPrivilegesRequiredLow CVSS30ModifiedPrivilegesRequired = "LOW" - // CVSS30ModifiedPrivilegesRequiredNone is a constant for "NONE". - CVSS30ModifiedPrivilegesRequiredNone CVSS30ModifiedPrivilegesRequired = "NONE" - // CVSS30ModifiedPrivilegesRequiredNotDefined is a constant for "NOT_DEFINED". - CVSS30ModifiedPrivilegesRequiredNotDefined CVSS30ModifiedPrivilegesRequired = "NOT_DEFINED" -) - -var cvss30ModifiedPrivilegesRequiredPattern = alternativesUnmarshal( - string(CVSS30ModifiedPrivilegesRequiredHigh), - string(CVSS30ModifiedPrivilegesRequiredLow), - string(CVSS30ModifiedPrivilegesRequiredNone), - string(CVSS30ModifiedPrivilegesRequiredNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30ModifiedPrivilegesRequired) UnmarshalText(data []byte) error { - s, err := cvss30ModifiedPrivilegesRequiredPattern(data) - if err == nil { - *e = CVSS30ModifiedPrivilegesRequired(s) - } - return err -} - -// CVSS30ModifiedScope represents the modifiedScopeType in CVSS30. -type CVSS30ModifiedScope string - -const ( - // CVSS30ModifiedScopeUnchanged is a constant for "UNCHANGED". - CVSS30ModifiedScopeUnchanged CVSS30ModifiedScope = "UNCHANGED" - // CVSS30ModifiedScopeChanged is a constant for "CHANGED". - CVSS30ModifiedScopeChanged CVSS30ModifiedScope = "CHANGED" - // CVSS30ModifiedScopeNotDefined is a constant for "NOT_DEFINED". - CVSS30ModifiedScopeNotDefined CVSS30ModifiedScope = "NOT_DEFINED" -) - -var cvss30ModifiedScopePattern = alternativesUnmarshal( - string(CVSS30ModifiedScopeUnchanged), - string(CVSS30ModifiedScopeChanged), - string(CVSS30ModifiedScopeNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30ModifiedScope) UnmarshalText(data []byte) error { - s, err := cvss30ModifiedScopePattern(data) - if err == nil { - *e = CVSS30ModifiedScope(s) - } - return err -} - -// CVSS30ModifiedUserInteraction represents the modifiedUserInteractionType in CVSS30. -type CVSS30ModifiedUserInteraction string - -const ( - // CVSS30ModifiedUserInteractionNone is a constant for "NONE". - CVSS30ModifiedUserInteractionNone CVSS30ModifiedUserInteraction = "NONE" - // CVSS30ModifiedUserInteractionRequired is a constant for "REQUIRED". - CVSS30ModifiedUserInteractionRequired CVSS30ModifiedUserInteraction = "REQUIRED" - // CVSS30ModifiedUserInteractionNotDefined is a constant for "NOT_DEFINED". - CVSS30ModifiedUserInteractionNotDefined CVSS30ModifiedUserInteraction = "NOT_DEFINED" -) - -var cvss30ModifiedUserInteractionPattern = alternativesUnmarshal( - string(CVSS30ModifiedUserInteractionNone), - string(CVSS30ModifiedUserInteractionRequired), - string(CVSS30ModifiedUserInteractionNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30ModifiedUserInteraction) UnmarshalText(data []byte) error { - s, err := cvss30ModifiedUserInteractionPattern(data) - if err == nil { - *e = CVSS30ModifiedUserInteraction(s) - } - return err -} - -// CVSS30PrivilegesRequired represents the privilegesRequiredType in CVSS30. -type CVSS30PrivilegesRequired string - -const ( - // CVSS30PrivilegesRequiredHigh is a constant for "HIGH". - CVSS30PrivilegesRequiredHigh CVSS30PrivilegesRequired = "HIGH" - // CVSS30PrivilegesRequiredLow is a constant for "LOW". - CVSS30PrivilegesRequiredLow CVSS30PrivilegesRequired = "LOW" - // CVSS30PrivilegesRequiredNone is a constant for "NONE". - CVSS30PrivilegesRequiredNone CVSS30PrivilegesRequired = "NONE" -) - -var cvss30PrivilegesRequiredPattern = alternativesUnmarshal( - string(CVSS30PrivilegesRequiredHigh), - string(CVSS30PrivilegesRequiredLow), - string(CVSS30PrivilegesRequiredNone), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30PrivilegesRequired) UnmarshalText(data []byte) error { - s, err := cvss30PrivilegesRequiredPattern(data) - if err == nil { - *e = CVSS30PrivilegesRequired(s) - } - return err -} - -// CVSS30RemediationLevel represents the remediationLevelType in CVSS30. -type CVSS30RemediationLevel string - -const ( - // CVSS30RemediationLevelOfficialFix is a constant for "OFFICIAL_FIX". - CVSS30RemediationLevelOfficialFix CVSS30RemediationLevel = "OFFICIAL_FIX" - // CVSS30RemediationLevelTemporaryFix is a constant for "TEMPORARY_FIX". - CVSS30RemediationLevelTemporaryFix CVSS30RemediationLevel = "TEMPORARY_FIX" - // CVSS30RemediationLevelWorkaround is a constant for "WORKAROUND". - CVSS30RemediationLevelWorkaround CVSS30RemediationLevel = "WORKAROUND" - // CVSS30RemediationLevelUnavailable is a constant for "UNAVAILABLE". - CVSS30RemediationLevelUnavailable CVSS30RemediationLevel = "UNAVAILABLE" - // CVSS30RemediationLevelNotDefined is a constant for "NOT_DEFINED". - CVSS30RemediationLevelNotDefined CVSS30RemediationLevel = "NOT_DEFINED" -) - -var cvss30RemediationLevelPattern = alternativesUnmarshal( - string(CVSS30RemediationLevelOfficialFix), - string(CVSS30RemediationLevelTemporaryFix), - string(CVSS30RemediationLevelWorkaround), - string(CVSS30RemediationLevelUnavailable), - string(CVSS30RemediationLevelNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30RemediationLevel) UnmarshalText(data []byte) error { - s, err := cvss30RemediationLevelPattern(data) - if err == nil { - *e = CVSS30RemediationLevel(s) - } - return err -} - -// CVSS30Scope represents the scopeType in CVSS30. -type CVSS30Scope string - -const ( - // CVSS30ScopeUnchanged is a constant for "UNCHANGED". - CVSS30ScopeUnchanged CVSS30Scope = "UNCHANGED" - // CVSS30ScopeChanged is a constant for "CHANGED". - CVSS30ScopeChanged CVSS30Scope = "CHANGED" -) - -var cvss30ScopePattern = alternativesUnmarshal( - string(CVSS30ScopeUnchanged), - string(CVSS30ScopeChanged), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30Scope) UnmarshalText(data []byte) error { - s, err := cvss30ScopePattern(data) - if err == nil { - *e = CVSS30Scope(s) - } - return err -} - -// CVSS30Severity represents the severityType in CVSS30. -type CVSS30Severity string - -const ( - // CVSS30SeverityNone is a constant for "NONE". - CVSS30SeverityNone CVSS30Severity = "NONE" - // CVSS30SeverityLow is a constant for "LOW". - CVSS30SeverityLow CVSS30Severity = "LOW" - // CVSS30SeverityMedium is a constant for "MEDIUM". - CVSS30SeverityMedium CVSS30Severity = "MEDIUM" - // CVSS30SeverityHigh is a constant for "HIGH". - CVSS30SeverityHigh CVSS30Severity = "HIGH" - // CVSS30SeverityCritical is a constant for "CRITICAL". - CVSS30SeverityCritical CVSS30Severity = "CRITICAL" -) - -var cvss30SeverityPattern = alternativesUnmarshal( - string(CVSS30SeverityNone), - string(CVSS30SeverityLow), - string(CVSS30SeverityMedium), - string(CVSS30SeverityHigh), - string(CVSS30SeverityCritical), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30Severity) UnmarshalText(data []byte) error { - s, err := cvss30SeverityPattern(data) - if err == nil { - *e = CVSS30Severity(s) - } - return err -} - -// CVSS30UserInteraction represents the userInteractionType in CVSS30. -type CVSS30UserInteraction string - -const ( - // CVSS30UserInteractionNone is a constant for "NONE". - CVSS30UserInteractionNone CVSS30UserInteraction = "NONE" - // CVSS30UserInteractionRequired is a constant for "REQUIRED". - CVSS30UserInteractionRequired CVSS30UserInteraction = "REQUIRED" -) - -var cvss30UserInteractionPattern = alternativesUnmarshal( - string(CVSS30UserInteractionNone), - string(CVSS30UserInteractionRequired), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS30UserInteraction) UnmarshalText(data []byte) error { - s, err := cvss30UserInteractionPattern(data) - if err == nil { - *e = CVSS30UserInteraction(s) - } - return err -} diff --git a/csaf/cvss31enums.go b/csaf/cvss31enums.go deleted file mode 100644 index 0de4946..0000000 --- a/csaf/cvss31enums.go +++ /dev/null @@ -1,500 +0,0 @@ -// This file is Free Software under the MIT License -// without warranty, see README.md and LICENSES/MIT.txt for details. -// -// SPDX-License-Identifier: MIT -// -// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) -// Software-Engineering: 2023 Intevation GmbH -// -// THIS FILE IS MACHINE GENERATED. EDIT WITH CARE! - -package csaf - -// CVSS31AttackComplexity represents the attackComplexityType in CVSS31. -type CVSS31AttackComplexity string - -const ( - // CVSS31AttackComplexityHigh is a constant for "HIGH". - CVSS31AttackComplexityHigh CVSS31AttackComplexity = "HIGH" - // CVSS31AttackComplexityLow is a constant for "LOW". - CVSS31AttackComplexityLow CVSS31AttackComplexity = "LOW" -) - -var cvss31AttackComplexityPattern = alternativesUnmarshal( - string(CVSS31AttackComplexityHigh), - string(CVSS31AttackComplexityLow), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31AttackComplexity) UnmarshalText(data []byte) error { - s, err := cvss31AttackComplexityPattern(data) - if err == nil { - *e = CVSS31AttackComplexity(s) - } - return err -} - -// CVSS31AttackVector represents the attackVectorType in CVSS31. -type CVSS31AttackVector string - -const ( - // CVSS31AttackVectorNetwork is a constant for "NETWORK". - CVSS31AttackVectorNetwork CVSS31AttackVector = "NETWORK" - // CVSS31AttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". - CVSS31AttackVectorAdjacentNetwork CVSS31AttackVector = "ADJACENT_NETWORK" - // CVSS31AttackVectorLocal is a constant for "LOCAL". - CVSS31AttackVectorLocal CVSS31AttackVector = "LOCAL" - // CVSS31AttackVectorPhysical is a constant for "PHYSICAL". - CVSS31AttackVectorPhysical CVSS31AttackVector = "PHYSICAL" -) - -var cvss31AttackVectorPattern = alternativesUnmarshal( - string(CVSS31AttackVectorNetwork), - string(CVSS31AttackVectorAdjacentNetwork), - string(CVSS31AttackVectorLocal), - string(CVSS31AttackVectorPhysical), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31AttackVector) UnmarshalText(data []byte) error { - s, err := cvss31AttackVectorPattern(data) - if err == nil { - *e = CVSS31AttackVector(s) - } - return err -} - -// CVSS31CiaRequirement represents the ciaRequirementType in CVSS31. -type CVSS31CiaRequirement string - -const ( - // CVSS31CiaRequirementLow is a constant for "LOW". - CVSS31CiaRequirementLow CVSS31CiaRequirement = "LOW" - // CVSS31CiaRequirementMedium is a constant for "MEDIUM". - CVSS31CiaRequirementMedium CVSS31CiaRequirement = "MEDIUM" - // CVSS31CiaRequirementHigh is a constant for "HIGH". - CVSS31CiaRequirementHigh CVSS31CiaRequirement = "HIGH" - // CVSS31CiaRequirementNotDefined is a constant for "NOT_DEFINED". - CVSS31CiaRequirementNotDefined CVSS31CiaRequirement = "NOT_DEFINED" -) - -var cvss31CiaRequirementPattern = alternativesUnmarshal( - string(CVSS31CiaRequirementLow), - string(CVSS31CiaRequirementMedium), - string(CVSS31CiaRequirementHigh), - string(CVSS31CiaRequirementNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31CiaRequirement) UnmarshalText(data []byte) error { - s, err := cvss31CiaRequirementPattern(data) - if err == nil { - *e = CVSS31CiaRequirement(s) - } - return err -} - -// CVSS31Cia represents the ciaType in CVSS31. -type CVSS31Cia string - -const ( - // CVSS31CiaNone is a constant for "NONE". - CVSS31CiaNone CVSS31Cia = "NONE" - // CVSS31CiaLow is a constant for "LOW". - CVSS31CiaLow CVSS31Cia = "LOW" - // CVSS31CiaHigh is a constant for "HIGH". - CVSS31CiaHigh CVSS31Cia = "HIGH" -) - -var cvss31CiaPattern = alternativesUnmarshal( - string(CVSS31CiaNone), - string(CVSS31CiaLow), - string(CVSS31CiaHigh), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31Cia) UnmarshalText(data []byte) error { - s, err := cvss31CiaPattern(data) - if err == nil { - *e = CVSS31Cia(s) - } - return err -} - -// CVSS31Confidence represents the confidenceType in CVSS31. -type CVSS31Confidence string - -const ( - // CVSS31ConfidenceUnknown is a constant for "UNKNOWN". - CVSS31ConfidenceUnknown CVSS31Confidence = "UNKNOWN" - // CVSS31ConfidenceReasonable is a constant for "REASONABLE". - CVSS31ConfidenceReasonable CVSS31Confidence = "REASONABLE" - // CVSS31ConfidenceConfirmed is a constant for "CONFIRMED". - CVSS31ConfidenceConfirmed CVSS31Confidence = "CONFIRMED" - // CVSS31ConfidenceNotDefined is a constant for "NOT_DEFINED". - CVSS31ConfidenceNotDefined CVSS31Confidence = "NOT_DEFINED" -) - -var cvss31ConfidencePattern = alternativesUnmarshal( - string(CVSS31ConfidenceUnknown), - string(CVSS31ConfidenceReasonable), - string(CVSS31ConfidenceConfirmed), - string(CVSS31ConfidenceNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31Confidence) UnmarshalText(data []byte) error { - s, err := cvss31ConfidencePattern(data) - if err == nil { - *e = CVSS31Confidence(s) - } - return err -} - -// CVSS31ExploitCodeMaturity represents the exploitCodeMaturityType in CVSS31. -type CVSS31ExploitCodeMaturity string - -const ( - // CVSS31ExploitCodeMaturityUnproven is a constant for "UNPROVEN". - CVSS31ExploitCodeMaturityUnproven CVSS31ExploitCodeMaturity = "UNPROVEN" - // CVSS31ExploitCodeMaturityProofOfConcept is a constant for "PROOF_OF_CONCEPT". - CVSS31ExploitCodeMaturityProofOfConcept CVSS31ExploitCodeMaturity = "PROOF_OF_CONCEPT" - // CVSS31ExploitCodeMaturityFunctional is a constant for "FUNCTIONAL". - CVSS31ExploitCodeMaturityFunctional CVSS31ExploitCodeMaturity = "FUNCTIONAL" - // CVSS31ExploitCodeMaturityHigh is a constant for "HIGH". - CVSS31ExploitCodeMaturityHigh CVSS31ExploitCodeMaturity = "HIGH" - // CVSS31ExploitCodeMaturityNotDefined is a constant for "NOT_DEFINED". - CVSS31ExploitCodeMaturityNotDefined CVSS31ExploitCodeMaturity = "NOT_DEFINED" -) - -var cvss31ExploitCodeMaturityPattern = alternativesUnmarshal( - string(CVSS31ExploitCodeMaturityUnproven), - string(CVSS31ExploitCodeMaturityProofOfConcept), - string(CVSS31ExploitCodeMaturityFunctional), - string(CVSS31ExploitCodeMaturityHigh), - string(CVSS31ExploitCodeMaturityNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31ExploitCodeMaturity) UnmarshalText(data []byte) error { - s, err := cvss31ExploitCodeMaturityPattern(data) - if err == nil { - *e = CVSS31ExploitCodeMaturity(s) - } - return err -} - -// CVSS31ModifiedAttackComplexity represents the modifiedAttackComplexityType in CVSS31. -type CVSS31ModifiedAttackComplexity string - -const ( - // CVSS31ModifiedAttackComplexityHigh is a constant for "HIGH". - CVSS31ModifiedAttackComplexityHigh CVSS31ModifiedAttackComplexity = "HIGH" - // CVSS31ModifiedAttackComplexityLow is a constant for "LOW". - CVSS31ModifiedAttackComplexityLow CVSS31ModifiedAttackComplexity = "LOW" - // CVSS31ModifiedAttackComplexityNotDefined is a constant for "NOT_DEFINED". - CVSS31ModifiedAttackComplexityNotDefined CVSS31ModifiedAttackComplexity = "NOT_DEFINED" -) - -var cvss31ModifiedAttackComplexityPattern = alternativesUnmarshal( - string(CVSS31ModifiedAttackComplexityHigh), - string(CVSS31ModifiedAttackComplexityLow), - string(CVSS31ModifiedAttackComplexityNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31ModifiedAttackComplexity) UnmarshalText(data []byte) error { - s, err := cvss31ModifiedAttackComplexityPattern(data) - if err == nil { - *e = CVSS31ModifiedAttackComplexity(s) - } - return err -} - -// CVSS31ModifiedAttackVector represents the modifiedAttackVectorType in CVSS31. -type CVSS31ModifiedAttackVector string - -const ( - // CVSS31ModifiedAttackVectorNetwork is a constant for "NETWORK". - CVSS31ModifiedAttackVectorNetwork CVSS31ModifiedAttackVector = "NETWORK" - // CVSS31ModifiedAttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". - CVSS31ModifiedAttackVectorAdjacentNetwork CVSS31ModifiedAttackVector = "ADJACENT_NETWORK" - // CVSS31ModifiedAttackVectorLocal is a constant for "LOCAL". - CVSS31ModifiedAttackVectorLocal CVSS31ModifiedAttackVector = "LOCAL" - // CVSS31ModifiedAttackVectorPhysical is a constant for "PHYSICAL". - CVSS31ModifiedAttackVectorPhysical CVSS31ModifiedAttackVector = "PHYSICAL" - // CVSS31ModifiedAttackVectorNotDefined is a constant for "NOT_DEFINED". - CVSS31ModifiedAttackVectorNotDefined CVSS31ModifiedAttackVector = "NOT_DEFINED" -) - -var cvss31ModifiedAttackVectorPattern = alternativesUnmarshal( - string(CVSS31ModifiedAttackVectorNetwork), - string(CVSS31ModifiedAttackVectorAdjacentNetwork), - string(CVSS31ModifiedAttackVectorLocal), - string(CVSS31ModifiedAttackVectorPhysical), - string(CVSS31ModifiedAttackVectorNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31ModifiedAttackVector) UnmarshalText(data []byte) error { - s, err := cvss31ModifiedAttackVectorPattern(data) - if err == nil { - *e = CVSS31ModifiedAttackVector(s) - } - return err -} - -// CVSS31ModifiedCia represents the modifiedCiaType in CVSS31. -type CVSS31ModifiedCia string - -const ( - // CVSS31ModifiedCiaNone is a constant for "NONE". - CVSS31ModifiedCiaNone CVSS31ModifiedCia = "NONE" - // CVSS31ModifiedCiaLow is a constant for "LOW". - CVSS31ModifiedCiaLow CVSS31ModifiedCia = "LOW" - // CVSS31ModifiedCiaHigh is a constant for "HIGH". - CVSS31ModifiedCiaHigh CVSS31ModifiedCia = "HIGH" - // CVSS31ModifiedCiaNotDefined is a constant for "NOT_DEFINED". - CVSS31ModifiedCiaNotDefined CVSS31ModifiedCia = "NOT_DEFINED" -) - -var cvss31ModifiedCiaPattern = alternativesUnmarshal( - string(CVSS31ModifiedCiaNone), - string(CVSS31ModifiedCiaLow), - string(CVSS31ModifiedCiaHigh), - string(CVSS31ModifiedCiaNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31ModifiedCia) UnmarshalText(data []byte) error { - s, err := cvss31ModifiedCiaPattern(data) - if err == nil { - *e = CVSS31ModifiedCia(s) - } - return err -} - -// CVSS31ModifiedPrivilegesRequired represents the modifiedPrivilegesRequiredType in CVSS31. -type CVSS31ModifiedPrivilegesRequired string - -const ( - // CVSS31ModifiedPrivilegesRequiredHigh is a constant for "HIGH". - CVSS31ModifiedPrivilegesRequiredHigh CVSS31ModifiedPrivilegesRequired = "HIGH" - // CVSS31ModifiedPrivilegesRequiredLow is a constant for "LOW". - CVSS31ModifiedPrivilegesRequiredLow CVSS31ModifiedPrivilegesRequired = "LOW" - // CVSS31ModifiedPrivilegesRequiredNone is a constant for "NONE". - CVSS31ModifiedPrivilegesRequiredNone CVSS31ModifiedPrivilegesRequired = "NONE" - // CVSS31ModifiedPrivilegesRequiredNotDefined is a constant for "NOT_DEFINED". - CVSS31ModifiedPrivilegesRequiredNotDefined CVSS31ModifiedPrivilegesRequired = "NOT_DEFINED" -) - -var cvss31ModifiedPrivilegesRequiredPattern = alternativesUnmarshal( - string(CVSS31ModifiedPrivilegesRequiredHigh), - string(CVSS31ModifiedPrivilegesRequiredLow), - string(CVSS31ModifiedPrivilegesRequiredNone), - string(CVSS31ModifiedPrivilegesRequiredNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31ModifiedPrivilegesRequired) UnmarshalText(data []byte) error { - s, err := cvss31ModifiedPrivilegesRequiredPattern(data) - if err == nil { - *e = CVSS31ModifiedPrivilegesRequired(s) - } - return err -} - -// CVSS31ModifiedScope represents the modifiedScopeType in CVSS31. -type CVSS31ModifiedScope string - -const ( - // CVSS31ModifiedScopeUnchanged is a constant for "UNCHANGED". - CVSS31ModifiedScopeUnchanged CVSS31ModifiedScope = "UNCHANGED" - // CVSS31ModifiedScopeChanged is a constant for "CHANGED". - CVSS31ModifiedScopeChanged CVSS31ModifiedScope = "CHANGED" - // CVSS31ModifiedScopeNotDefined is a constant for "NOT_DEFINED". - CVSS31ModifiedScopeNotDefined CVSS31ModifiedScope = "NOT_DEFINED" -) - -var cvss31ModifiedScopePattern = alternativesUnmarshal( - string(CVSS31ModifiedScopeUnchanged), - string(CVSS31ModifiedScopeChanged), - string(CVSS31ModifiedScopeNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31ModifiedScope) UnmarshalText(data []byte) error { - s, err := cvss31ModifiedScopePattern(data) - if err == nil { - *e = CVSS31ModifiedScope(s) - } - return err -} - -// CVSS31ModifiedUserInteraction represents the modifiedUserInteractionType in CVSS31. -type CVSS31ModifiedUserInteraction string - -const ( - // CVSS31ModifiedUserInteractionNone is a constant for "NONE". - CVSS31ModifiedUserInteractionNone CVSS31ModifiedUserInteraction = "NONE" - // CVSS31ModifiedUserInteractionRequired is a constant for "REQUIRED". - CVSS31ModifiedUserInteractionRequired CVSS31ModifiedUserInteraction = "REQUIRED" - // CVSS31ModifiedUserInteractionNotDefined is a constant for "NOT_DEFINED". - CVSS31ModifiedUserInteractionNotDefined CVSS31ModifiedUserInteraction = "NOT_DEFINED" -) - -var cvss31ModifiedUserInteractionPattern = alternativesUnmarshal( - string(CVSS31ModifiedUserInteractionNone), - string(CVSS31ModifiedUserInteractionRequired), - string(CVSS31ModifiedUserInteractionNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31ModifiedUserInteraction) UnmarshalText(data []byte) error { - s, err := cvss31ModifiedUserInteractionPattern(data) - if err == nil { - *e = CVSS31ModifiedUserInteraction(s) - } - return err -} - -// CVSS31PrivilegesRequired represents the privilegesRequiredType in CVSS31. -type CVSS31PrivilegesRequired string - -const ( - // CVSS31PrivilegesRequiredHigh is a constant for "HIGH". - CVSS31PrivilegesRequiredHigh CVSS31PrivilegesRequired = "HIGH" - // CVSS31PrivilegesRequiredLow is a constant for "LOW". - CVSS31PrivilegesRequiredLow CVSS31PrivilegesRequired = "LOW" - // CVSS31PrivilegesRequiredNone is a constant for "NONE". - CVSS31PrivilegesRequiredNone CVSS31PrivilegesRequired = "NONE" -) - -var cvss31PrivilegesRequiredPattern = alternativesUnmarshal( - string(CVSS31PrivilegesRequiredHigh), - string(CVSS31PrivilegesRequiredLow), - string(CVSS31PrivilegesRequiredNone), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31PrivilegesRequired) UnmarshalText(data []byte) error { - s, err := cvss31PrivilegesRequiredPattern(data) - if err == nil { - *e = CVSS31PrivilegesRequired(s) - } - return err -} - -// CVSS31RemediationLevel represents the remediationLevelType in CVSS31. -type CVSS31RemediationLevel string - -const ( - // CVSS31RemediationLevelOfficialFix is a constant for "OFFICIAL_FIX". - CVSS31RemediationLevelOfficialFix CVSS31RemediationLevel = "OFFICIAL_FIX" - // CVSS31RemediationLevelTemporaryFix is a constant for "TEMPORARY_FIX". - CVSS31RemediationLevelTemporaryFix CVSS31RemediationLevel = "TEMPORARY_FIX" - // CVSS31RemediationLevelWorkaround is a constant for "WORKAROUND". - CVSS31RemediationLevelWorkaround CVSS31RemediationLevel = "WORKAROUND" - // CVSS31RemediationLevelUnavailable is a constant for "UNAVAILABLE". - CVSS31RemediationLevelUnavailable CVSS31RemediationLevel = "UNAVAILABLE" - // CVSS31RemediationLevelNotDefined is a constant for "NOT_DEFINED". - CVSS31RemediationLevelNotDefined CVSS31RemediationLevel = "NOT_DEFINED" -) - -var cvss31RemediationLevelPattern = alternativesUnmarshal( - string(CVSS31RemediationLevelOfficialFix), - string(CVSS31RemediationLevelTemporaryFix), - string(CVSS31RemediationLevelWorkaround), - string(CVSS31RemediationLevelUnavailable), - string(CVSS31RemediationLevelNotDefined), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31RemediationLevel) UnmarshalText(data []byte) error { - s, err := cvss31RemediationLevelPattern(data) - if err == nil { - *e = CVSS31RemediationLevel(s) - } - return err -} - -// CVSS31Scope represents the scopeType in CVSS31. -type CVSS31Scope string - -const ( - // CVSS31ScopeUnchanged is a constant for "UNCHANGED". - CVSS31ScopeUnchanged CVSS31Scope = "UNCHANGED" - // CVSS31ScopeChanged is a constant for "CHANGED". - CVSS31ScopeChanged CVSS31Scope = "CHANGED" -) - -var cvss31ScopePattern = alternativesUnmarshal( - string(CVSS31ScopeUnchanged), - string(CVSS31ScopeChanged), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31Scope) UnmarshalText(data []byte) error { - s, err := cvss31ScopePattern(data) - if err == nil { - *e = CVSS31Scope(s) - } - return err -} - -// CVSS31Severity represents the severityType in CVSS31. -type CVSS31Severity string - -const ( - // CVSS31SeverityNone is a constant for "NONE". - CVSS31SeverityNone CVSS31Severity = "NONE" - // CVSS31SeverityLow is a constant for "LOW". - CVSS31SeverityLow CVSS31Severity = "LOW" - // CVSS31SeverityMedium is a constant for "MEDIUM". - CVSS31SeverityMedium CVSS31Severity = "MEDIUM" - // CVSS31SeverityHigh is a constant for "HIGH". - CVSS31SeverityHigh CVSS31Severity = "HIGH" - // CVSS31SeverityCritical is a constant for "CRITICAL". - CVSS31SeverityCritical CVSS31Severity = "CRITICAL" -) - -var cvss31SeverityPattern = alternativesUnmarshal( - string(CVSS31SeverityNone), - string(CVSS31SeverityLow), - string(CVSS31SeverityMedium), - string(CVSS31SeverityHigh), - string(CVSS31SeverityCritical), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31Severity) UnmarshalText(data []byte) error { - s, err := cvss31SeverityPattern(data) - if err == nil { - *e = CVSS31Severity(s) - } - return err -} - -// CVSS31UserInteraction represents the userInteractionType in CVSS31. -type CVSS31UserInteraction string - -const ( - // CVSS31UserInteractionNone is a constant for "NONE". - CVSS31UserInteractionNone CVSS31UserInteraction = "NONE" - // CVSS31UserInteractionRequired is a constant for "REQUIRED". - CVSS31UserInteractionRequired CVSS31UserInteraction = "REQUIRED" -) - -var cvss31UserInteractionPattern = alternativesUnmarshal( - string(CVSS31UserInteractionNone), - string(CVSS31UserInteractionRequired), -) - -// UnmarshalText implements the [encoding.TextUnmarshaler] interface. -func (e *CVSS31UserInteraction) UnmarshalText(data []byte) error { - s, err := cvss31UserInteractionPattern(data) - if err == nil { - *e = CVSS31UserInteraction(s) - } - return err -} diff --git a/csaf/cvss3enums.go b/csaf/cvss3enums.go new file mode 100644 index 0000000..494a46c --- /dev/null +++ b/csaf/cvss3enums.go @@ -0,0 +1,500 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) +// Software-Engineering: 2023 Intevation GmbH +// +// THIS FILE IS MACHINE GENERATED. EDIT WITH CARE! + +package csaf + +// CVSS3AttackComplexity represents the attackComplexityType in CVSS3. +type CVSS3AttackComplexity string + +const ( + // CVSS3AttackComplexityHigh is a constant for "HIGH". + CVSS3AttackComplexityHigh CVSS3AttackComplexity = "HIGH" + // CVSS3AttackComplexityLow is a constant for "LOW". + CVSS3AttackComplexityLow CVSS3AttackComplexity = "LOW" +) + +var cvss3AttackComplexityPattern = alternativesUnmarshal( + string(CVSS3AttackComplexityHigh), + string(CVSS3AttackComplexityLow), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3AttackComplexity) UnmarshalText(data []byte) error { + s, err := cvss3AttackComplexityPattern(data) + if err == nil { + *e = CVSS3AttackComplexity(s) + } + return err +} + +// CVSS3AttackVector represents the attackVectorType in CVSS3. +type CVSS3AttackVector string + +const ( + // CVSS3AttackVectorNetwork is a constant for "NETWORK". + CVSS3AttackVectorNetwork CVSS3AttackVector = "NETWORK" + // CVSS3AttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". + CVSS3AttackVectorAdjacentNetwork CVSS3AttackVector = "ADJACENT_NETWORK" + // CVSS3AttackVectorLocal is a constant for "LOCAL". + CVSS3AttackVectorLocal CVSS3AttackVector = "LOCAL" + // CVSS3AttackVectorPhysical is a constant for "PHYSICAL". + CVSS3AttackVectorPhysical CVSS3AttackVector = "PHYSICAL" +) + +var cvss3AttackVectorPattern = alternativesUnmarshal( + string(CVSS3AttackVectorNetwork), + string(CVSS3AttackVectorAdjacentNetwork), + string(CVSS3AttackVectorLocal), + string(CVSS3AttackVectorPhysical), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3AttackVector) UnmarshalText(data []byte) error { + s, err := cvss3AttackVectorPattern(data) + if err == nil { + *e = CVSS3AttackVector(s) + } + return err +} + +// CVSS3CiaRequirement represents the ciaRequirementType in CVSS3. +type CVSS3CiaRequirement string + +const ( + // CVSS3CiaRequirementLow is a constant for "LOW". + CVSS3CiaRequirementLow CVSS3CiaRequirement = "LOW" + // CVSS3CiaRequirementMedium is a constant for "MEDIUM". + CVSS3CiaRequirementMedium CVSS3CiaRequirement = "MEDIUM" + // CVSS3CiaRequirementHigh is a constant for "HIGH". + CVSS3CiaRequirementHigh CVSS3CiaRequirement = "HIGH" + // CVSS3CiaRequirementNotDefined is a constant for "NOT_DEFINED". + CVSS3CiaRequirementNotDefined CVSS3CiaRequirement = "NOT_DEFINED" +) + +var cvss3CiaRequirementPattern = alternativesUnmarshal( + string(CVSS3CiaRequirementLow), + string(CVSS3CiaRequirementMedium), + string(CVSS3CiaRequirementHigh), + string(CVSS3CiaRequirementNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3CiaRequirement) UnmarshalText(data []byte) error { + s, err := cvss3CiaRequirementPattern(data) + if err == nil { + *e = CVSS3CiaRequirement(s) + } + return err +} + +// CVSS3Cia represents the ciaType in CVSS3. +type CVSS3Cia string + +const ( + // CVSS3CiaNone is a constant for "NONE". + CVSS3CiaNone CVSS3Cia = "NONE" + // CVSS3CiaLow is a constant for "LOW". + CVSS3CiaLow CVSS3Cia = "LOW" + // CVSS3CiaHigh is a constant for "HIGH". + CVSS3CiaHigh CVSS3Cia = "HIGH" +) + +var cvss3CiaPattern = alternativesUnmarshal( + string(CVSS3CiaNone), + string(CVSS3CiaLow), + string(CVSS3CiaHigh), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3Cia) UnmarshalText(data []byte) error { + s, err := cvss3CiaPattern(data) + if err == nil { + *e = CVSS3Cia(s) + } + return err +} + +// CVSS3Confidence represents the confidenceType in CVSS3. +type CVSS3Confidence string + +const ( + // CVSS3ConfidenceUnknown is a constant for "UNKNOWN". + CVSS3ConfidenceUnknown CVSS3Confidence = "UNKNOWN" + // CVSS3ConfidenceReasonable is a constant for "REASONABLE". + CVSS3ConfidenceReasonable CVSS3Confidence = "REASONABLE" + // CVSS3ConfidenceConfirmed is a constant for "CONFIRMED". + CVSS3ConfidenceConfirmed CVSS3Confidence = "CONFIRMED" + // CVSS3ConfidenceNotDefined is a constant for "NOT_DEFINED". + CVSS3ConfidenceNotDefined CVSS3Confidence = "NOT_DEFINED" +) + +var cvss3ConfidencePattern = alternativesUnmarshal( + string(CVSS3ConfidenceUnknown), + string(CVSS3ConfidenceReasonable), + string(CVSS3ConfidenceConfirmed), + string(CVSS3ConfidenceNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3Confidence) UnmarshalText(data []byte) error { + s, err := cvss3ConfidencePattern(data) + if err == nil { + *e = CVSS3Confidence(s) + } + return err +} + +// CVSS3ExploitCodeMaturity represents the exploitCodeMaturityType in CVSS3. +type CVSS3ExploitCodeMaturity string + +const ( + // CVSS3ExploitCodeMaturityUnproven is a constant for "UNPROVEN". + CVSS3ExploitCodeMaturityUnproven CVSS3ExploitCodeMaturity = "UNPROVEN" + // CVSS3ExploitCodeMaturityProofOfConcept is a constant for "PROOF_OF_CONCEPT". + CVSS3ExploitCodeMaturityProofOfConcept CVSS3ExploitCodeMaturity = "PROOF_OF_CONCEPT" + // CVSS3ExploitCodeMaturityFunctional is a constant for "FUNCTIONAL". + CVSS3ExploitCodeMaturityFunctional CVSS3ExploitCodeMaturity = "FUNCTIONAL" + // CVSS3ExploitCodeMaturityHigh is a constant for "HIGH". + CVSS3ExploitCodeMaturityHigh CVSS3ExploitCodeMaturity = "HIGH" + // CVSS3ExploitCodeMaturityNotDefined is a constant for "NOT_DEFINED". + CVSS3ExploitCodeMaturityNotDefined CVSS3ExploitCodeMaturity = "NOT_DEFINED" +) + +var cvss3ExploitCodeMaturityPattern = alternativesUnmarshal( + string(CVSS3ExploitCodeMaturityUnproven), + string(CVSS3ExploitCodeMaturityProofOfConcept), + string(CVSS3ExploitCodeMaturityFunctional), + string(CVSS3ExploitCodeMaturityHigh), + string(CVSS3ExploitCodeMaturityNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3ExploitCodeMaturity) UnmarshalText(data []byte) error { + s, err := cvss3ExploitCodeMaturityPattern(data) + if err == nil { + *e = CVSS3ExploitCodeMaturity(s) + } + return err +} + +// CVSS3ModifiedAttackComplexity represents the modifiedAttackComplexityType in CVSS3. +type CVSS3ModifiedAttackComplexity string + +const ( + // CVSS3ModifiedAttackComplexityHigh is a constant for "HIGH". + CVSS3ModifiedAttackComplexityHigh CVSS3ModifiedAttackComplexity = "HIGH" + // CVSS3ModifiedAttackComplexityLow is a constant for "LOW". + CVSS3ModifiedAttackComplexityLow CVSS3ModifiedAttackComplexity = "LOW" + // CVSS3ModifiedAttackComplexityNotDefined is a constant for "NOT_DEFINED". + CVSS3ModifiedAttackComplexityNotDefined CVSS3ModifiedAttackComplexity = "NOT_DEFINED" +) + +var cvss3ModifiedAttackComplexityPattern = alternativesUnmarshal( + string(CVSS3ModifiedAttackComplexityHigh), + string(CVSS3ModifiedAttackComplexityLow), + string(CVSS3ModifiedAttackComplexityNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3ModifiedAttackComplexity) UnmarshalText(data []byte) error { + s, err := cvss3ModifiedAttackComplexityPattern(data) + if err == nil { + *e = CVSS3ModifiedAttackComplexity(s) + } + return err +} + +// CVSS3ModifiedAttackVector represents the modifiedAttackVectorType in CVSS3. +type CVSS3ModifiedAttackVector string + +const ( + // CVSS3ModifiedAttackVectorNetwork is a constant for "NETWORK". + CVSS3ModifiedAttackVectorNetwork CVSS3ModifiedAttackVector = "NETWORK" + // CVSS3ModifiedAttackVectorAdjacentNetwork is a constant for "ADJACENT_NETWORK". + CVSS3ModifiedAttackVectorAdjacentNetwork CVSS3ModifiedAttackVector = "ADJACENT_NETWORK" + // CVSS3ModifiedAttackVectorLocal is a constant for "LOCAL". + CVSS3ModifiedAttackVectorLocal CVSS3ModifiedAttackVector = "LOCAL" + // CVSS3ModifiedAttackVectorPhysical is a constant for "PHYSICAL". + CVSS3ModifiedAttackVectorPhysical CVSS3ModifiedAttackVector = "PHYSICAL" + // CVSS3ModifiedAttackVectorNotDefined is a constant for "NOT_DEFINED". + CVSS3ModifiedAttackVectorNotDefined CVSS3ModifiedAttackVector = "NOT_DEFINED" +) + +var cvss3ModifiedAttackVectorPattern = alternativesUnmarshal( + string(CVSS3ModifiedAttackVectorNetwork), + string(CVSS3ModifiedAttackVectorAdjacentNetwork), + string(CVSS3ModifiedAttackVectorLocal), + string(CVSS3ModifiedAttackVectorPhysical), + string(CVSS3ModifiedAttackVectorNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3ModifiedAttackVector) UnmarshalText(data []byte) error { + s, err := cvss3ModifiedAttackVectorPattern(data) + if err == nil { + *e = CVSS3ModifiedAttackVector(s) + } + return err +} + +// CVSS3ModifiedCia represents the modifiedCiaType in CVSS3. +type CVSS3ModifiedCia string + +const ( + // CVSS3ModifiedCiaNone is a constant for "NONE". + CVSS3ModifiedCiaNone CVSS3ModifiedCia = "NONE" + // CVSS3ModifiedCiaLow is a constant for "LOW". + CVSS3ModifiedCiaLow CVSS3ModifiedCia = "LOW" + // CVSS3ModifiedCiaHigh is a constant for "HIGH". + CVSS3ModifiedCiaHigh CVSS3ModifiedCia = "HIGH" + // CVSS3ModifiedCiaNotDefined is a constant for "NOT_DEFINED". + CVSS3ModifiedCiaNotDefined CVSS3ModifiedCia = "NOT_DEFINED" +) + +var cvss3ModifiedCiaPattern = alternativesUnmarshal( + string(CVSS3ModifiedCiaNone), + string(CVSS3ModifiedCiaLow), + string(CVSS3ModifiedCiaHigh), + string(CVSS3ModifiedCiaNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3ModifiedCia) UnmarshalText(data []byte) error { + s, err := cvss3ModifiedCiaPattern(data) + if err == nil { + *e = CVSS3ModifiedCia(s) + } + return err +} + +// CVSS3ModifiedPrivilegesRequired represents the modifiedPrivilegesRequiredType in CVSS3. +type CVSS3ModifiedPrivilegesRequired string + +const ( + // CVSS3ModifiedPrivilegesRequiredHigh is a constant for "HIGH". + CVSS3ModifiedPrivilegesRequiredHigh CVSS3ModifiedPrivilegesRequired = "HIGH" + // CVSS3ModifiedPrivilegesRequiredLow is a constant for "LOW". + CVSS3ModifiedPrivilegesRequiredLow CVSS3ModifiedPrivilegesRequired = "LOW" + // CVSS3ModifiedPrivilegesRequiredNone is a constant for "NONE". + CVSS3ModifiedPrivilegesRequiredNone CVSS3ModifiedPrivilegesRequired = "NONE" + // CVSS3ModifiedPrivilegesRequiredNotDefined is a constant for "NOT_DEFINED". + CVSS3ModifiedPrivilegesRequiredNotDefined CVSS3ModifiedPrivilegesRequired = "NOT_DEFINED" +) + +var cvss3ModifiedPrivilegesRequiredPattern = alternativesUnmarshal( + string(CVSS3ModifiedPrivilegesRequiredHigh), + string(CVSS3ModifiedPrivilegesRequiredLow), + string(CVSS3ModifiedPrivilegesRequiredNone), + string(CVSS3ModifiedPrivilegesRequiredNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3ModifiedPrivilegesRequired) UnmarshalText(data []byte) error { + s, err := cvss3ModifiedPrivilegesRequiredPattern(data) + if err == nil { + *e = CVSS3ModifiedPrivilegesRequired(s) + } + return err +} + +// CVSS3ModifiedScope represents the modifiedScopeType in CVSS3. +type CVSS3ModifiedScope string + +const ( + // CVSS3ModifiedScopeUnchanged is a constant for "UNCHANGED". + CVSS3ModifiedScopeUnchanged CVSS3ModifiedScope = "UNCHANGED" + // CVSS3ModifiedScopeChanged is a constant for "CHANGED". + CVSS3ModifiedScopeChanged CVSS3ModifiedScope = "CHANGED" + // CVSS3ModifiedScopeNotDefined is a constant for "NOT_DEFINED". + CVSS3ModifiedScopeNotDefined CVSS3ModifiedScope = "NOT_DEFINED" +) + +var cvss3ModifiedScopePattern = alternativesUnmarshal( + string(CVSS3ModifiedScopeUnchanged), + string(CVSS3ModifiedScopeChanged), + string(CVSS3ModifiedScopeNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3ModifiedScope) UnmarshalText(data []byte) error { + s, err := cvss3ModifiedScopePattern(data) + if err == nil { + *e = CVSS3ModifiedScope(s) + } + return err +} + +// CVSS3ModifiedUserInteraction represents the modifiedUserInteractionType in CVSS3. +type CVSS3ModifiedUserInteraction string + +const ( + // CVSS3ModifiedUserInteractionNone is a constant for "NONE". + CVSS3ModifiedUserInteractionNone CVSS3ModifiedUserInteraction = "NONE" + // CVSS3ModifiedUserInteractionRequired is a constant for "REQUIRED". + CVSS3ModifiedUserInteractionRequired CVSS3ModifiedUserInteraction = "REQUIRED" + // CVSS3ModifiedUserInteractionNotDefined is a constant for "NOT_DEFINED". + CVSS3ModifiedUserInteractionNotDefined CVSS3ModifiedUserInteraction = "NOT_DEFINED" +) + +var cvss3ModifiedUserInteractionPattern = alternativesUnmarshal( + string(CVSS3ModifiedUserInteractionNone), + string(CVSS3ModifiedUserInteractionRequired), + string(CVSS3ModifiedUserInteractionNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3ModifiedUserInteraction) UnmarshalText(data []byte) error { + s, err := cvss3ModifiedUserInteractionPattern(data) + if err == nil { + *e = CVSS3ModifiedUserInteraction(s) + } + return err +} + +// CVSS3PrivilegesRequired represents the privilegesRequiredType in CVSS3. +type CVSS3PrivilegesRequired string + +const ( + // CVSS3PrivilegesRequiredHigh is a constant for "HIGH". + CVSS3PrivilegesRequiredHigh CVSS3PrivilegesRequired = "HIGH" + // CVSS3PrivilegesRequiredLow is a constant for "LOW". + CVSS3PrivilegesRequiredLow CVSS3PrivilegesRequired = "LOW" + // CVSS3PrivilegesRequiredNone is a constant for "NONE". + CVSS3PrivilegesRequiredNone CVSS3PrivilegesRequired = "NONE" +) + +var cvss3PrivilegesRequiredPattern = alternativesUnmarshal( + string(CVSS3PrivilegesRequiredHigh), + string(CVSS3PrivilegesRequiredLow), + string(CVSS3PrivilegesRequiredNone), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3PrivilegesRequired) UnmarshalText(data []byte) error { + s, err := cvss3PrivilegesRequiredPattern(data) + if err == nil { + *e = CVSS3PrivilegesRequired(s) + } + return err +} + +// CVSS3RemediationLevel represents the remediationLevelType in CVSS3. +type CVSS3RemediationLevel string + +const ( + // CVSS3RemediationLevelOfficialFix is a constant for "OFFICIAL_FIX". + CVSS3RemediationLevelOfficialFix CVSS3RemediationLevel = "OFFICIAL_FIX" + // CVSS3RemediationLevelTemporaryFix is a constant for "TEMPORARY_FIX". + CVSS3RemediationLevelTemporaryFix CVSS3RemediationLevel = "TEMPORARY_FIX" + // CVSS3RemediationLevelWorkaround is a constant for "WORKAROUND". + CVSS3RemediationLevelWorkaround CVSS3RemediationLevel = "WORKAROUND" + // CVSS3RemediationLevelUnavailable is a constant for "UNAVAILABLE". + CVSS3RemediationLevelUnavailable CVSS3RemediationLevel = "UNAVAILABLE" + // CVSS3RemediationLevelNotDefined is a constant for "NOT_DEFINED". + CVSS3RemediationLevelNotDefined CVSS3RemediationLevel = "NOT_DEFINED" +) + +var cvss3RemediationLevelPattern = alternativesUnmarshal( + string(CVSS3RemediationLevelOfficialFix), + string(CVSS3RemediationLevelTemporaryFix), + string(CVSS3RemediationLevelWorkaround), + string(CVSS3RemediationLevelUnavailable), + string(CVSS3RemediationLevelNotDefined), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3RemediationLevel) UnmarshalText(data []byte) error { + s, err := cvss3RemediationLevelPattern(data) + if err == nil { + *e = CVSS3RemediationLevel(s) + } + return err +} + +// CVSS3Scope represents the scopeType in CVSS3. +type CVSS3Scope string + +const ( + // CVSS3ScopeUnchanged is a constant for "UNCHANGED". + CVSS3ScopeUnchanged CVSS3Scope = "UNCHANGED" + // CVSS3ScopeChanged is a constant for "CHANGED". + CVSS3ScopeChanged CVSS3Scope = "CHANGED" +) + +var cvss3ScopePattern = alternativesUnmarshal( + string(CVSS3ScopeUnchanged), + string(CVSS3ScopeChanged), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3Scope) UnmarshalText(data []byte) error { + s, err := cvss3ScopePattern(data) + if err == nil { + *e = CVSS3Scope(s) + } + return err +} + +// CVSS3Severity represents the severityType in CVSS3. +type CVSS3Severity string + +const ( + // CVSS3SeverityNone is a constant for "NONE". + CVSS3SeverityNone CVSS3Severity = "NONE" + // CVSS3SeverityLow is a constant for "LOW". + CVSS3SeverityLow CVSS3Severity = "LOW" + // CVSS3SeverityMedium is a constant for "MEDIUM". + CVSS3SeverityMedium CVSS3Severity = "MEDIUM" + // CVSS3SeverityHigh is a constant for "HIGH". + CVSS3SeverityHigh CVSS3Severity = "HIGH" + // CVSS3SeverityCritical is a constant for "CRITICAL". + CVSS3SeverityCritical CVSS3Severity = "CRITICAL" +) + +var cvss3SeverityPattern = alternativesUnmarshal( + string(CVSS3SeverityNone), + string(CVSS3SeverityLow), + string(CVSS3SeverityMedium), + string(CVSS3SeverityHigh), + string(CVSS3SeverityCritical), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3Severity) UnmarshalText(data []byte) error { + s, err := cvss3SeverityPattern(data) + if err == nil { + *e = CVSS3Severity(s) + } + return err +} + +// CVSS3UserInteraction represents the userInteractionType in CVSS3. +type CVSS3UserInteraction string + +const ( + // CVSS3UserInteractionNone is a constant for "NONE". + CVSS3UserInteractionNone CVSS3UserInteraction = "NONE" + // CVSS3UserInteractionRequired is a constant for "REQUIRED". + CVSS3UserInteractionRequired CVSS3UserInteraction = "REQUIRED" +) + +var cvss3UserInteractionPattern = alternativesUnmarshal( + string(CVSS3UserInteractionNone), + string(CVSS3UserInteractionRequired), +) + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (e *CVSS3UserInteraction) UnmarshalText(data []byte) error { + s, err := cvss3UserInteractionPattern(data) + if err == nil { + *e = CVSS3UserInteraction(s) + } + return err +} diff --git a/csaf/doc.go b/csaf/doc.go index 92d8ee3..22ff7fa 100644 --- a/csaf/doc.go +++ b/csaf/doc.go @@ -10,5 +10,6 @@ package csaf //go:generate go run ./generate_cvss_enums.go -o cvss20enums.go -i ./schema/cvss-v2.0.json -p CVSS20 -//go:generate go run ./generate_cvss_enums.go -o cvss30enums.go -i ./schema/cvss-v3.0.json -p CVSS30 -//go:generate go run ./generate_cvss_enums.go -o cvss31enums.go -i ./schema/cvss-v3.1.json -p CVSS31 +// Generating only enums for CVSS 3.0 and not for 3.1 since the enums of both of them +// are identical. +//go:generate go run ./generate_cvss_enums.go -o cvss3enums.go -i ./schema/cvss-v3.0.json -p CVSS3 From dc41aae07f08f96365dcbef6825c45d4b6692db5 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Thu, 7 Sep 2023 08:48:34 +0200 Subject: [PATCH 12/24] use up-to-date schema for CVSS 3.0 --- csaf/schema/cvss-v3.0.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csaf/schema/cvss-v3.0.json b/csaf/schema/cvss-v3.0.json index 28b3c38..af09ec6 100644 --- a/csaf/schema/cvss-v3.0.json +++ b/csaf/schema/cvss-v3.0.json @@ -108,7 +108,7 @@ }, "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])$" + "pattern": "^CVSS:3[.]0/((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" }, From 5a3661e81bca55e09bb1352d94451f95519167ea Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Fri, 8 Sep 2023 14:52:48 +0200 Subject: [PATCH 13/24] use type FileHashValue --- csaf/advisory.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index 1fb8a5d..c656ccb 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -83,8 +83,8 @@ var fileHashValuePattern = patternUnmarshal(`^[0-9a-fA-F]{32,}$`) // FileHash is checksum hash. // Values for 'algorithm' are derived from the currently supported digests OpenSSL. Leading dashes were removed. type FileHash struct { - Algorithm string `json:"algorithm"` // required, default: sha256 - Value string `json:"value"` // required + Algorithm string `json:"algorithm"` // required, default: sha256 + Value FileHashValue `json:"value"` // required } // Hashes is a list of hashes. From f868b13c24a5e61fd85a5148fda0a2b4a7a68877 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Fri, 8 Sep 2023 16:24:50 +0200 Subject: [PATCH 14/24] added function to validate document --- csaf/advisory.go | 284 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 210 insertions(+), 74 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index c656ccb..d00f997 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -10,6 +10,7 @@ package csaf import ( "encoding/json" + "fmt" "io" "os" ) @@ -83,14 +84,14 @@ var fileHashValuePattern = patternUnmarshal(`^[0-9a-fA-F]{32,}$`) // FileHash is checksum hash. // Values for 'algorithm' are derived from the currently supported digests OpenSSL. Leading dashes were removed. type FileHash struct { - Algorithm string `json:"algorithm"` // required, default: sha256 - Value FileHashValue `json:"value"` // required + Algorithm *string `json:"algorithm"` // required, default: sha256 + Value *FileHashValue `json:"value"` // required } // Hashes is a list of hashes. type Hashes struct { - FileHashes []FileHash `json:"file_hashes"` // required - FileName string `json:"filename"` // required + FileHashes []*FileHash `json:"file_hashes"` // required + FileName *string `json:"filename"` // required } // CPE represents a Common Platform Enumeration in an advisory. @@ -105,8 +106,8 @@ var pURLPattern = patternUnmarshal(`^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*/ // XGenericURI represents an identifier for a product. type XGenericURI struct { - Namespace string `json:"namespace"` // required - URI string `json:"uri"` // required + Namespace *string `json:"namespace"` // required + URI *string `json:"uri"` // required } // ProductIdentificationHelper bundles product identifier information. @@ -124,8 +125,8 @@ type ProductIdentificationHelper struct { // FullProductName is the full name of a product. type FullProductName struct { - Name string `json:"name"` // required - ProductID ProductID `json:"product_id"` // required + Name *string `json:"name"` // required + ProductID *ProductID `json:"product_id"` // required ProductIdentificationHelper *ProductIdentificationHelper `json:"product_identification_helper,omitempty"` } @@ -137,8 +138,8 @@ type FullProductName struct { // version ranges. type Branch struct { Branches []*Branch `json:"branches,omitempty"` - Category BranchCategory `json:"category"` // required - Name string `json:"name"` // required + Category *BranchCategory `json:"category"` // required + Name *string `json:"name"` // required Product *FullProductName `json:"product,omitempty"` } @@ -173,10 +174,10 @@ var csafNoteCategoryPattern = alternativesUnmarshal( // Note reflects the 'Note' object of an advisory. type Note struct { - Audience string `json:"audience,omitempty"` + Audience *string `json:"audience,omitempty"` NoteCategory *NoteCategory `json:"category"` // required Text *string `json:"text"` // required - Title string `json:"title,omitempty"` + Title *string `json:"title,omitempty"` } // ReferenceCategory is the category of a note. @@ -198,15 +199,15 @@ var csafReferenceCategoryPattern = alternativesUnmarshal( // or the entire document and to be of value to the document consumer. type Reference struct { ReferenceCategory *string `json:"category"` // optional, default: external - Summary string `json:"summary"` // required - URL string `json:"url"` // required + Summary *string `json:"summary"` // required + URL *string `json:"url"` // required } // AggregateSeverity stands for the urgency with which the vulnerabilities of an advisory // (not a specific one) should be addressed. type AggregateSeverity struct { Namespace *string `json:"namespace,omitempty"` - Text string `json:"text"` // required + Text *string `json:"text"` // required } // DocumentCategory represents a category of a document. @@ -224,8 +225,8 @@ var csafVersionPattern = alternativesUnmarshal(string(CSAFVersion20)) // TLP provides details about the TLP classification of the document. type TLP struct { - DocumentTLPLabel TLPLabel `json:"label"` // required - URL *string `json:"url,omitempty"` + DocumentTLPLabel *TLPLabel `json:"label"` // required + URL *string `json:"url,omitempty"` } // DocumentDistribution describes rules for sharing a document. @@ -236,11 +237,11 @@ type DocumentDistribution struct { // DocumentPublisher provides information about the publishing entity. type DocumentPublisher struct { - Category Category `json:"category"` // required - ContactDetails *string `json:"contact_details,omitempty"` - IssuingAuthority *string `json:"issuing_authority,omitempty"` - Name string `json:"name"` // required - Namespace string `json:"namespace"` // required + Category *Category `json:"category"` // required + ContactDetails *string `json:"contact_details,omitempty"` + IssuingAuthority *string `json:"issuing_authority,omitempty"` + Name *string `json:"name"` // required + Namespace *string `json:"namespace"` // required } // RevisionNumber specifies a version string to denote clearly the evolution of the content of the document. @@ -250,7 +251,7 @@ var versionPattern = patternUnmarshal("^(0|[1-9][0-9]*)$|^((0|[1-9]\\d*)\\.(0|[1 // Engine contains information about the engine that generated the CSAF document. type Engine struct { - Name string `json:"name"` // required + Name *string `json:"name"` // required Version *string `json:"version,omitempty"` } @@ -259,7 +260,7 @@ type Engine struct { // including the date it was generated and the entity that generated it. type Generator struct { Date *string `json:"date,omitempty"` - Engine Engine `json:"engine"` // required + Engine *Engine `json:"engine"` // required } // TrackingID is a unique identifier for the document. @@ -269,10 +270,10 @@ var trackingIDPattern = patternUnmarshal("^[\\S](.*[\\S])?$") // Revision contains information about one revision of the document. type Revision struct { - Date string `json:"date"` // required - LegacyVersion *string `json:"legacy_version,omitempty"` - Number RevisionNumber `json:"number"` // required - Summary string `json:"summary"` // required + Date *string `json:"date"` // required + LegacyVersion *string `json:"legacy_version,omitempty"` + Number *RevisionNumber `json:"number"` // required + Summary *string `json:"summary"` // required } // TrackingStatus is the category of a publisher. @@ -294,14 +295,14 @@ var csafTrackingStatusPattern = alternativesUnmarshal( // Tracking holds information that is necessary to track a CSAF document. type Tracking struct { - Aliases []*string `json:"aliases,omitempty"` // unique elements - CurrentReleaseDate string `json:"current_release_date"` // required - Generator *Generator `json:"generator"` - ID TrackingID `json:"id"` // required - InitialReleaseDate string `json:"initial_release_date"` // required - RevisionHistory []Revision `json:"revision_history"` // required - Status TrackingStatus `json:"status"` // required - Version RevisionNumber `json:"version"` // required + Aliases []*string `json:"aliases,omitempty"` // unique elements + CurrentReleaseDate *string `json:"current_release_date"` // required + Generator *Generator `json:"generator"` + ID *TrackingID `json:"id"` // required + InitialReleaseDate *string `json:"initial_release_date"` // required + RevisionHistory []*Revision `json:"revision_history"` // required + Status *TrackingStatus `json:"status"` // required + Version *RevisionNumber `json:"version"` // required } // Lang is a language identifier, corresponding to IETF BCP 47 / RFC 5646. @@ -311,18 +312,18 @@ var langPattern = patternUnmarshal("^(([A-Za-z]{2,3}(-[A-Za-z]{3}(-[A-Za-z]{3}){ // Document contains meta-data about an advisory. type Document struct { - Acknowledgements []Acknowledgement `json:"acknowledgements,omitempty"` + Acknowledgements []*Acknowledgement `json:"acknowledgements,omitempty"` AggregateSeverity *AggregateSeverity `json:"aggregate_severity,omitempty"` - Category DocumentCategory `json:"category"` // required - CSAFVersion Version `json:"csaf_version"` // required + Category *DocumentCategory `json:"category"` // required + CSAFVersion *Version `json:"csaf_version"` // required Distribution *DocumentDistribution `json:"distribution,omitempty"` Lang *Lang `json:"lang,omitempty"` Notes []*Note `json:"notes,omitempty"` - Publisher DocumentPublisher `json:"publisher"` // required + Publisher *DocumentPublisher `json:"publisher"` // required References []*Reference `json:"references,omitempty"` SourceLang *Lang `json:"source_lang,omitempty"` - Title string `json:"title"` // required - Tracking Tracking `json:"tracking"` // required + Title *string `json:"title"` // required + Tracking *Tracking `json:"tracking"` // required } // ProductGroupID is a reference token for product group instances. @@ -330,9 +331,9 @@ type ProductGroupID string // ProductGroup is a group of products in the document that belong to one group. type ProductGroup struct { - GroupID string `json:"group_id"` // required - ProductIDs Products `json:"product_ids"` // required, two or more unique elements - Summary *string `json:"summary,omitempty"` + GroupID *string `json:"group_id"` // required + ProductIDs *Products `json:"product_ids"` // required, two or more unique elements + Summary *string `json:"summary,omitempty"` } // ProductGroups is a list of ProductGroupIDs @@ -365,10 +366,10 @@ var csafRelationshipCategoryPattern = alternativesUnmarshal( // Relationship establishes a link between two existing FullProductName elements. type Relationship struct { - Category RelationshipCategory `json:"category"` // required - FullProductName FullProductName `json:"full_product_name"` // required - ProductReference ProductID `json:"product_reference"` // required - RelatesToProductReference ProductID `json:"relates_to_product_reference"` // required + Category *RelationshipCategory `json:"category"` // required + FullProductName *FullProductName `json:"full_product_name"` // required + ProductReference *ProductID `json:"product_reference"` // required + RelatesToProductReference *ProductID `json:"relates_to_product_reference"` // required } @@ -392,8 +393,8 @@ var weaknessIDPattern = patternUnmarshal("^CWE-[1-9]\\d{0,5}$") // CWE holds the MITRE standard Common Weakness Enumeration (CWE) for the weakness associated. type CWE struct { - ID WeaknessID `json:"id"` // required - Name string `json:"name"` // required + ID *WeaknessID `json:"id"` // required + Name *string `json:"name"` // required } // FlagLabel is the label of a flag for a vulnerability. @@ -425,14 +426,14 @@ var csafFlagLabelPattern = alternativesUnmarshal( type Flag struct { Date *string `json:"date,omitempty"` GroupIds *ProductGroups `json:"group_ids,omitempty"` - Label FlagLabel `json:"label"` // required + Label *FlagLabel `json:"label"` // required ProductIds *Products `json:"product_ids,omitempty"` } // VulnerabilityID is the identifier of a vulnerability. type VulnerabilityID struct { - SystemName string `json:"system_name"` // required - Text string `json:"text"` // required + SystemName *string `json:"system_name"` // required + Text *string `json:"text"` // required } // InvolvementParty is the party of an involvement. @@ -490,10 +491,10 @@ var csafInvolvementStatusPattern = alternativesUnmarshal( // The ordered tuple of the values of party and date (if present) SHALL be unique within the involvements // of a vulnerability. type Involvement struct { - Date *string `json:"date,omitempty"` - Party InvolvementParty `json:"party"` // required - Status InvolvementStatus `json:"status"` // required - Summary *string `json:"summary,omitempty"` + Date *string `json:"date,omitempty"` + Party *InvolvementParty `json:"party"` // required + Status *InvolvementStatus `json:"status"` // required + Summary *string `json:"summary,omitempty"` } // ProductStatus contains different lists of ProductIDs which provide details on @@ -570,8 +571,8 @@ var csafRestartRequiredCategoryPattern = alternativesUnmarshal( // RestartRequired provides information on category of restart is required by this remediation to become // effective. type RestartRequired struct { - Category RestartRequiredCategory `json:"category"` // required - Details *string `json:"details,omitempty"` + Category *RestartRequiredCategory `json:"category"` // required + Details *string `json:"details,omitempty"` } // Remediation specifies details on how to handle (and presumably, fix) a vulnerability. @@ -621,15 +622,15 @@ var cvss3VectorStringPattern = patternUnmarshal(`^CVSS:3[.][01]/((AV:[NALP]|AC:[ // CVSS2 holding a CVSS v2.0 value type CVSS2 struct { - Version CVSSVersion2 `json:"version"` // required - VectorString CVSS2VectorString `json:"vectorString"` // required + Version *CVSSVersion2 `json:"version"` // required + VectorString *CVSS2VectorString `json:"vectorString"` // required AccessVector *CVSS20AccessVector `json:"accessVector,omitempty"` AccessComplexity *CVSS20AccessComplexity `json:"accessComplexity,omitempty"` Authentication *CVSS20Authentication `json:"authentication,omitempty"` ConfidentialityImpact *CVSS20Cia `json:"confidentialityImpact,omitempty"` IntegrityImpact *CVSS20Cia `json:"integrityImpact,omitempty"` AvailabilityImpact *CVSS20Cia `json:"availabilityImpact,omitempty"` - BaseScore float64 `json:"baseScore"` // required + BaseScore *float64 `json:"baseScore"` // required Exploitability *CVSS20Exploitability `json:"exploitability,omitempty"` RemediationLevel *CVSS20RemediationLevel `json:"remediationLevel,omitempty"` ReportConfidence *CVSS20ReportConfidence `json:"reportConfidence,omitempty"` @@ -644,8 +645,8 @@ type CVSS2 struct { // CVSS3 holding a CVSS v3.x value type CVSS3 struct { - Version CVSSVersion3 `json:"version"` // required - VectorString CVSS3VectorString `json:"vectorString"` // required + Version *CVSSVersion3 `json:"version"` // required + VectorString *CVSS3VectorString `json:"vectorString"` // required AttackVector *CVSS3AttackVector `json:"attackVector,omitempty"` AttackComplexity *CVSS3AttackComplexity `json:"attackComplexity,omitempty"` PrivilegesRequired *CVSS3PrivilegesRequired `json:"privilegesRequired,omitempty"` @@ -654,8 +655,8 @@ type CVSS3 struct { ConfidentialityImpact *CVSS3Cia `json:"confidentialityImpact,omitempty"` IntegrityImpact CVSS3Cia `json:"integrityImpact,omitempty"` AvailabilityImpact *CVSS3Cia `json:"availabilityImpact,omitempty"` - BaseScore float64 `json:"baseScore"` // required - BaseSeverity CVSS3Severity `json:"baseSeverity"` // required + BaseScore *float64 `json:"baseScore"` // required + BaseSeverity *CVSS3Severity `json:"baseSeverity"` // required ExploitCodeMaturity *CVSS3ExploitCodeMaturity `json:"exploitCodeMaturity,omitempty"` RemediationLevel *CVSS3RemediationLevel `json:"remediationLevel,omitempty"` ReportConfidence *CVSS3Confidence `json:"reportConfidence,omitempty"` @@ -703,11 +704,11 @@ var csafThreatCategoryPattern = alternativesUnmarshal( // Threat contains information about a vulnerability that can change with time. type Threat struct { - Category ThreatCategory `json:"category"` // required - Date *string `json:"date,omitempty"` - Details string `json:"details"` // required - GroupIds *ProductGroups `json:"group_ids,omitempty"` - ProductIds *Products `json:"product_ids,omitempty"` + Category *ThreatCategory `json:"category"` // required + Date *string `json:"date,omitempty"` + Details *string `json:"details"` // required + GroupIds *ProductGroups `json:"group_ids,omitempty"` + ProductIds *Products `json:"product_ids,omitempty"` } // Vulnerability contains all fields that are related to a single vulnerability in the document. @@ -731,15 +732,147 @@ type Vulnerability struct { // Advisory represents a CSAF advisory. type Advisory struct { - Document Document `json:"document"` // required + Document *Document `json:"document"` // required ProductTree *ProductTree `json:"product_tree,omitempty"` Vulnerabilities []*Vulnerability `json:"vulnerabilities,omitempty"` } +func (adv *Advisory) ValidateDocument() error { + doc := adv.Document + + if doc.AggregateSeverity != nil { + if doc.AggregateSeverity.Text == nil { + return fmt.Errorf("the property 'aggregate_severity' is missing the property 'text'") + } + } + + if doc.Category == nil { + return fmt.Errorf("the property 'document' is missing the property 'category'") + } + + if doc.CSAFVersion == nil { + return fmt.Errorf("the property 'document' is missing the property 'csaf_version'") + } + + if doc.Distribution != nil { + if doc.Distribution.Text == nil && doc.Distribution.TLP == nil { + return fmt.Errorf("the property 'distribution' must at least contain one of the following properties:" + + "'text', 'tlp'") + } + } + + if doc.Notes != nil { + for index, note := range doc.Notes { + if note.NoteCategory == nil { + return fmt.Errorf("the %d. note in the property 'document' is missing the property 'note_category'", index) + } + if note.Text == nil { + return fmt.Errorf("the %d. note in the property 'document' is missing the property 'text'", index) + } + } + } + + if doc.Publisher == nil { + return fmt.Errorf("the property 'document' is missing the property 'publisher'") + } + + publisher := doc.Publisher + + if publisher.Category == nil { + return fmt.Errorf("the publisher in the property 'document' is missing the property 'category'") + } + + if publisher.Name == nil { + return fmt.Errorf("the publisher in the property 'document' is missing the property 'name'") + } + + if publisher.Namespace == nil { + return fmt.Errorf("the publisher in the property 'document' is missing the property 'namespace'") + } + + if doc.References != nil { + for index, ref := range doc.References { + if ref.Summary == nil { + return fmt.Errorf("the %d. reference in the property 'document' is missing the property 'summary'", index) + } + if ref.URL == nil { + return fmt.Errorf("the %d. reference in the property 'document' is missing the property 'url'", index) + } + } + } + + if doc.Title == nil { + return fmt.Errorf("the property 'document' is missing the property 'title'") + } + + if doc.Tracking == nil { + return fmt.Errorf("the property 'document' is missing the property 'tracking'") + } + + tracking := doc.Tracking + + if tracking.CurrentReleaseDate == nil { + return fmt.Errorf("the property 'tracking' is missing the property 'current_release_date'") + } + + if tracking.Generator != nil { + generator := tracking.Generator + if generator.Engine == nil { + return fmt.Errorf("the property 'generator' is missing the property 'engine'") + } + + if generator.Engine.Version == nil { + return fmt.Errorf("the property 'engine' is missing the property 'version'") + } + } + + if tracking.ID == nil { + return fmt.Errorf("the property 'tracking' is missing the property 'id'") + } + + if tracking.InitialReleaseDate == nil { + return fmt.Errorf("the property 'tracking' is missing the property 'initial_release_date'") + } + + if tracking.RevisionHistory == nil { + return fmt.Errorf("the property 'tracking' is missing the property 'revision_history'") + } + + for index, revision := range tracking.RevisionHistory { + if revision.Date == nil { + return fmt.Errorf("the %d. revision in the property 'document' is missing the property 'date'", index) + } + + if revision.Number == nil { + return fmt.Errorf("the %d. revision in the property 'document' is missing the property 'number'", index) + } + + if revision.Summary == nil { + return fmt.Errorf("the %d. revision in the property 'document' is missing the property 'summary'", index) + } + } + + if tracking.Status == nil { + return fmt.Errorf("the property 'tracking' is missing the property 'status'") + } + + if tracking.Version == nil { + return fmt.Errorf("the property 'tracking' is missing the property 'version'") + } + + return nil +} + // Validate checks if the advisory is valid. // Returns an error if the validation fails otherwise nil. func (adv *Advisory) Validate() error { - // TODO + if adv.Document == nil { + return fmt.Errorf("the advisory is missing the property 'document'") + } + + if validationError := adv.ValidateDocument(); validationError != nil { + return validationError + } return nil } @@ -754,6 +887,9 @@ func LoadAdvisory(fname string) (*Advisory, error) { if err := json.NewDecoder(f).Decode(&advisory); err != nil { return nil, err } + if validationError := advisory.Validate(); validationError != nil { + return nil, validationError + } return &advisory, nil } From ed42f193d13551345ae1da83ee2daaefd9fb820c Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Fri, 8 Sep 2023 20:04:04 +0200 Subject: [PATCH 15/24] added function to validate ProductTree --- csaf/advisory.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/csaf/advisory.go b/csaf/advisory.go index d00f997..f119c24 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -863,6 +863,81 @@ func (adv *Advisory) ValidateDocument() error { return nil } +func ValidateBranch(branches []*Branch) error { + for _, branch := range branches { + if branch.Category == nil { + return fmt.Errorf("element of property 'branches' is missing the property 'category'") + } + + if branch.Name == nil { + return fmt.Errorf("element of property 'branches' is missing the property 'name'") + } + + if branch.Product != nil { + if branch.Product.Name == nil { + return fmt.Errorf("property 'product' is missing the property 'name'") + } + + if branch.Product.ProductID == nil { + return fmt.Errorf("property 'product' is missing the property 'product_id'") + } + + if branch.Product.ProductIdentificationHelper != nil { + helper := branch.Product.ProductIdentificationHelper + + if helper.Hashes != nil { + if helper.Hashes.FileHashes == nil { + return fmt.Errorf("property 'hashes' is missing the property 'file_hashes'") + } + + for _, hash := range helper.Hashes.FileHashes { + if hash.Algorithm == nil { + return fmt.Errorf("element of property 'file_hashes' is missing the property 'algorithm'") + } + + if hash.Value == nil { + return fmt.Errorf("element of property 'file_hashes' is missing the property 'value'") + } + } + + if helper.Hashes.FileName == nil { + return fmt.Errorf("property 'hashes' is missing the property 'filename'") + } + } + + if helper.XGenericURIs != nil { + for _, uri := range helper.XGenericURIs { + if uri.Namespace == nil { + return fmt.Errorf("element of property 'x_generic_uris' is missing the property 'namespace'") + } + + if uri.URI == nil { + return fmt.Errorf("element of property 'x_generic_uris' is missing the property 'uri'") + } + } + } + } + } + + if branch.Branches != nil { + if validationError := ValidateBranch(branch.Branches); validationError != nil { + return validationError + } + } + } + return nil +} + +func (adv *Advisory) ValidateProductTree() error { + tree := adv.ProductTree + if tree.Branches != nil { + if validationError := ValidateBranch(tree.Branches); validationError != nil { + return validationError + } + } + return nil +} + // Validate checks if the advisory is valid. // Returns an error if the validation fails otherwise nil. func (adv *Advisory) Validate() error { @@ -873,6 +948,13 @@ func (adv *Advisory) Validate() error { if validationError := adv.ValidateDocument(); validationError != nil { return validationError } + + if adv.ProductTree != nil { + if validationError := adv.ValidateProductTree(); validationError != nil { + return validationError + } + } + return nil } From 4da9f67e2e9e32c4b285e9af9098372cda8fc158 Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Sat, 9 Sep 2023 21:15:25 +0200 Subject: [PATCH 16/24] Distribute the validation to the types to reduce the overall complexity. --- csaf/advisory.go | 505 +++++++++++++++++++++++++++++------------------ 1 file changed, 309 insertions(+), 196 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index f119c24..c4966bf 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -10,6 +10,7 @@ package csaf import ( "encoding/json" + "errors" "fmt" "io" "os" @@ -110,17 +111,20 @@ type XGenericURI struct { URI *string `json:"uri"` // required } +// XGenericURIs is a list of XGenericURI. +type XGenericURIs []*XGenericURI + // ProductIdentificationHelper bundles product identifier information. // Supported formats for SBOMs are SPDX, CycloneDX, and SWID type ProductIdentificationHelper struct { - CPE *CPE `json:"cpe,omitempty"` - Hashes *Hashes `json:"hashes,omitempty"` - ModelNumbers []*string `json:"model_numbers,omitempty"` // unique elements - PURL *PURL `json:"purl,omitempty"` - SBOMURLs []*string `json:"sbom_urls,omitempty"` - SerialNumbers []*string `json:"serial_numbers,omitempty"` // unique elements - SKUs []*string `json:"skus,omitempty"` - XGenericURIs []*XGenericURI `json:"x_generic_uris,omitempty"` + CPE *CPE `json:"cpe,omitempty"` + Hashes *Hashes `json:"hashes,omitempty"` + ModelNumbers []*string `json:"model_numbers,omitempty"` // unique elements + PURL *PURL `json:"purl,omitempty"` + SBOMURLs []*string `json:"sbom_urls,omitempty"` + SerialNumbers []*string `json:"serial_numbers,omitempty"` // unique elements + SKUs []*string `json:"skus,omitempty"` + XGenericURIs XGenericURIs `json:"x_generic_uris,omitempty"` } // FullProductName is the full name of a product. @@ -137,7 +141,7 @@ type FullProductName struct { // If the category is 'product_version_range' the name MUST contain // version ranges. type Branch struct { - Branches []*Branch `json:"branches,omitempty"` + Branches Branches `json:"branches,omitempty"` Category *BranchCategory `json:"category"` // required Name *string `json:"name"` // required Product *FullProductName `json:"product,omitempty"` @@ -293,6 +297,9 @@ var csafTrackingStatusPattern = alternativesUnmarshal( string(CSAFTrackingStatusFinal), string(CSAFTrackingStatusInterim)) +// Revisions is a list of Revision. +type Revisions []*Revision + // Tracking holds information that is necessary to track a CSAF document. type Tracking struct { Aliases []*string `json:"aliases,omitempty"` // unique elements @@ -300,7 +307,7 @@ type Tracking struct { Generator *Generator `json:"generator"` ID *TrackingID `json:"id"` // required InitialReleaseDate *string `json:"initial_release_date"` // required - RevisionHistory []*Revision `json:"revision_history"` // required + RevisionHistory Revisions `json:"revision_history"` // required Status *TrackingStatus `json:"status"` // required Version *RevisionNumber `json:"version"` // required } @@ -318,9 +325,9 @@ type Document struct { CSAFVersion *Version `json:"csaf_version"` // required Distribution *DocumentDistribution `json:"distribution,omitempty"` Lang *Lang `json:"lang,omitempty"` - Notes []*Note `json:"notes,omitempty"` + Notes Notes `json:"notes,omitempty"` Publisher *DocumentPublisher `json:"publisher"` // required - References []*Reference `json:"references,omitempty"` + References References `json:"references,omitempty"` SourceLang *Lang `json:"source_lang,omitempty"` Title *string `json:"title"` // required Tracking *Tracking `json:"tracking"` // required @@ -373,9 +380,12 @@ type Relationship struct { } +// Branches is a list of Branch. +type Branches []*Branch + // ProductTree contains product names that can be referenced elsewhere in the document. type ProductTree struct { - Branches []*Branch `json:"branches,omitempty"` + Branches Branches `json:"branches,omitempty"` FullProductNames []*FullProductName `json:"full_product_name,omitempty"` ProductGroups *ProductGroups `json:"product_groups,omitempty"` RelationShips []*Relationship `json:"relationships,omitempty"` @@ -711,6 +721,12 @@ type Threat struct { ProductIds *Products `json:"product_ids,omitempty"` } +// Notes is a list of Note. +type Notes []*Note + +// References is a list of Reference. +type References []*Reference + // Vulnerability contains all fields that are related to a single vulnerability in the document. type Vulnerability struct { Acknowledgements []*Acknowledgement `json:"acknowledgements,omitempty"` @@ -720,9 +736,9 @@ type Vulnerability struct { Flags []*Flag `json:"flags,omitempty"` Ids []*VulnerabilityID `json:"ids,omitempty"` // unique ID elements Involvements []*Involvement `json:"involvements,omitempty"` - Notes []*Note `json:"notes,omitempty"` + Notes Notes `json:"notes,omitempty"` ProductStatus *ProductStatus `json:"product_status,omitempty"` - References []*Reference `json:"references,omitempty"` + References References `json:"references,omitempty"` ReleaseDate *string `json:"release_date,omitempty"` Remediations []*Remediation `json:"remediations,omitempty"` Scores []*Score `json:"scores,omitempty"` @@ -737,224 +753,321 @@ type Advisory struct { Vulnerabilities []*Vulnerability `json:"vulnerabilities,omitempty"` } -func (adv *Advisory) ValidateDocument() error { - doc := adv.Document +// Validate validates a AggregateSeverity. +func (as *AggregateSeverity) Validate() error { + if as.Text == nil { + return errors.New("'text' is missing") + } + return nil +} - if doc.AggregateSeverity != nil { - if doc.AggregateSeverity.Text == nil { - return fmt.Errorf("the property 'aggregate_severity' is missing the property 'text'") +// Validate validates a DocumentDistribution. +func (dd *DocumentDistribution) Validate() error { + if dd.Text == nil && dd.TLP == nil { + return errors.New("needs at least properties 'text' or 'tlp'") + } + return nil +} + +// Validate validates a list of notes. +func (ns Notes) Validate() error { + for i, n := range ns { + if err := n.Validate(); err != nil { + return fmt.Errorf("%d. note is invalid: %w", i+1, err) } } + return nil +} - if doc.Category == nil { - return fmt.Errorf("the property 'document' is missing the property 'category'") +// Validate validates a single note. +func (n *Note) Validate() error { + switch { + case n == nil: + return errors.New("is nil") + case n.NoteCategory == nil: + return errors.New("'note_category' is missing") + case n.Text == nil: + return errors.New("'text' is missing") + default: + return nil } +} - if doc.CSAFVersion == nil { - return fmt.Errorf("the property 'document' is missing the property 'csaf_version'") +// Validate validates a DocumentPublisher. +func (p *DocumentPublisher) Validate() error { + switch { + case p.Category == nil: + return errors.New("'document' is missing") + case p.Name == nil: + return errors.New("'name' is missing") + case p.Namespace == nil: + return errors.New("'namespace' is missing") + default: + return nil } +} +// Validate validates a single reference. +func (r *Reference) Validate() error { + switch { + case r.Summary == nil: + return errors.New("summary' is missing") + case r.URL == nil: + return errors.New("'url' is missing") + default: + return nil + } +} + +// Validate validates a list of references. +func (rs References) Validate() error { + for i, r := range rs { + if err := r.Validate(); err != nil { + return fmt.Errorf("%d. reference is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates a single revision. +func (r *Revision) Validate() error { + switch { + case r.Date == nil: + return errors.New("'date' is missing") + case r.Number == nil: + return errors.New("'number' is missing") + case r.Summary == nil: + return errors.New("'summary' is missing") + default: + return nil + } +} + +// Validate validates a list of revisions. +func (rs Revisions) Validate() error { + for i, r := range rs { + if err := r.Validate(); err != nil { + return fmt.Errorf("%d. revision is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates an Engine. +func (e *Engine) Validate() error { + if e.Version == nil { + return errors.New("'version' is missing") + } + return nil +} + +// Validate validates a Generator. +func (g *Generator) Validate() error { + if g.Engine == nil { + return errors.New("'engine' is missing") + } + if err := g.Engine.Validate(); err != nil { + return fmt.Errorf("'engine' is invalid: %w", err) + } + return nil +} + +// Validate validates a single Tracking. +func (t *Tracking) Validate() error { + switch { + case t.CurrentReleaseDate == nil: + return errors.New("'current_release_date' is missing") + case t.ID == nil: + return errors.New("'id' is missing") + case t.InitialReleaseDate == nil: + return errors.New("'initial_release_date' is missing") + case t.RevisionHistory == nil: + return errors.New("'revision_history' is missing") + case t.Status == nil: + return errors.New("'status' is missing") + case t.Version == nil: + return errors.New("'version' is missing") + } + if err := t.RevisionHistory.Validate(); err != nil { + return fmt.Errorf("'revision_history' is invalid: %w", err) + } + if t.Generator != nil { + if err := t.Generator.Validate(); err != nil { + return fmt.Errorf("'generator' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a Document. +func (doc *Document) Validate() error { + switch { + case doc.Category == nil: + return errors.New("'category' is missing") + case doc.CSAFVersion == nil: + return errors.New("'csaf_version' is missing") + case doc.Publisher == nil: + return errors.New("'publisher' is missing") + case doc.Title == nil: + return errors.New("'title' is missing") + case doc.Tracking == nil: + return errors.New("'tracking' is missing") + } + if err := doc.Tracking.Validate(); err != nil { + return fmt.Errorf("'tracking' is invalid: %w", err) + } if doc.Distribution != nil { - if doc.Distribution.Text == nil && doc.Distribution.TLP == nil { - return fmt.Errorf("the property 'distribution' must at least contain one of the following properties:" + - "'text', 'tlp'") + if err := doc.Distribution.Validate(); err != nil { + return fmt.Errorf("'distribution' is invalid: %w", err) } } - - if doc.Notes != nil { - for index, note := range doc.Notes { - if note.NoteCategory == nil { - return fmt.Errorf("the %d. note in the property 'document' is missing the property 'note_category'", index) - } - if note.Text == nil { - return fmt.Errorf("the %d. note in the property 'document' is missing the property 'text'", index) - } + if doc.AggregateSeverity != nil { + if err := doc.AggregateSeverity.Validate(); err != nil { + return fmt.Errorf("'aggregate_severity' is invalid: %w", err) } } - - if doc.Publisher == nil { - return fmt.Errorf("the property 'document' is missing the property 'publisher'") + if err := doc.Publisher.Validate(); err != nil { + return fmt.Errorf("'publisher' is invalid: %w", err) } - - publisher := doc.Publisher - - if publisher.Category == nil { - return fmt.Errorf("the publisher in the property 'document' is missing the property 'category'") + if err := doc.References.Validate(); err != nil { + return fmt.Errorf("'references' is invalid: %w", err) } - - if publisher.Name == nil { - return fmt.Errorf("the publisher in the property 'document' is missing the property 'name'") + if err := doc.Notes.Validate(); err != nil { + return fmt.Errorf("'notes' is invalid: %w", err) } - - if publisher.Namespace == nil { - return fmt.Errorf("the publisher in the property 'document' is missing the property 'namespace'") - } - - if doc.References != nil { - for index, ref := range doc.References { - if ref.Summary == nil { - return fmt.Errorf("the %d. reference in the property 'document' is missing the property 'summary'", index) - } - if ref.URL == nil { - return fmt.Errorf("the %d. reference in the property 'document' is missing the property 'url'", index) - } - } - } - - if doc.Title == nil { - return fmt.Errorf("the property 'document' is missing the property 'title'") - } - - if doc.Tracking == nil { - return fmt.Errorf("the property 'document' is missing the property 'tracking'") - } - - tracking := doc.Tracking - - if tracking.CurrentReleaseDate == nil { - return fmt.Errorf("the property 'tracking' is missing the property 'current_release_date'") - } - - if tracking.Generator != nil { - generator := tracking.Generator - if generator.Engine == nil { - return fmt.Errorf("the property 'generator' is missing the property 'engine'") - } - - if generator.Engine.Version == nil { - return fmt.Errorf("the property 'engine' is missing the property 'version'") - } - } - - if tracking.ID == nil { - return fmt.Errorf("the property 'tracking' is missing the property 'id'") - } - - if tracking.InitialReleaseDate == nil { - return fmt.Errorf("the property 'tracking' is missing the property 'initial_release_date'") - } - - if tracking.RevisionHistory == nil { - return fmt.Errorf("the property 'tracking' is missing the property 'revision_history'") - } - - for index, revision := range tracking.RevisionHistory { - if revision.Date == nil { - return fmt.Errorf("the %d. revision in the property 'document' is missing the property 'date'", index) - } - - if revision.Number == nil { - return fmt.Errorf("the %d. revision in the property 'document' is missing the property 'number'", index) - } - - if revision.Summary == nil { - return fmt.Errorf("the %d. revision in the property 'document' is missing the property 'summary'", index) - } - } - - if tracking.Status == nil { - return fmt.Errorf("the property 'tracking' is missing the property 'status'") - } - - if tracking.Version == nil { - return fmt.Errorf("the property 'tracking' is missing the property 'version'") - } - return nil } -func ValidateBranch(branches []*Branch) error { - for _, branch := range branches { - if branch.Category == nil { - return fmt.Errorf("element of property 'branches' is missing the property 'category'") - } +// Validate validates a single FileHash. +func (fh *FileHash) Validate() error { + switch { + case fh == nil: + return errors.New("is nil") + case fh.Algorithm == nil: + return errors.New("'algorithm' is missing") + case fh.Value == nil: + return errors.New("'value' is missing") + default: + return nil + } +} - if branch.Name == nil { - return fmt.Errorf("element of property 'branches' is missing the property 'name'") - } - - if branch.Product != nil { - if branch.Product.Name == nil { - return fmt.Errorf("property 'product' is missing the property 'name'") - } - - if branch.Product.ProductID == nil { - return fmt.Errorf("property 'product' is missing the property 'product_id'") - } - - if branch.Product.ProductIdentificationHelper != nil { - helper := branch.Product.ProductIdentificationHelper - - if helper.Hashes != nil { - if helper.Hashes.FileHashes == nil { - return fmt.Errorf("property 'hashes' is missing the property 'file_hashes'") - } - - for _, hash := range helper.Hashes.FileHashes { - if hash.Algorithm == nil { - return fmt.Errorf("element of property 'file_hashes' is missing the property 'algorithm'") - } - - if hash.Value == nil { - return fmt.Errorf("element of property 'file_hashes' is missing the property 'value'") - } - } - - if helper.Hashes.FileName == nil { - return fmt.Errorf("property 'hashes' is missing the property 'filename'") - } - } - - if helper.XGenericURIs != nil { - for _, uri := range helper.XGenericURIs { - if uri.Namespace == nil { - return fmt.Errorf("element of property 'x_generic_uris' is missing the property 'namespace'") - } - - if uri.URI == nil { - return fmt.Errorf("element of property 'x_generic_uris' is missing the property 'uri'") - } - } - } - } - } - - if branch.Branches != nil { - if validationError := ValidateBranch(branch.Branches); validationError != nil { - return validationError - } +// Validate validates a list of file hashes. +func (hs *Hashes) Validate() error { + switch { + case hs.FileHashes == nil: + return errors.New("'hashes' is missing") + case hs.FileName == nil: + return errors.New("'filename' is missing") + } + for i, fh := range hs.FileHashes { + if err := fh.Validate(); err != nil { + return fmt.Errorf("%d. file hash is invalid: %w", i+1, err) } } return nil } -func (adv *Advisory) ValidateProductTree() error { - tree := adv.ProductTree - if tree.Branches != nil { - if validationError := ValidateBranch(tree.Branches); validationError != nil { - return validationError +// Validate validates a single XGenericURI. +func (xgu *XGenericURI) Validate() error { + switch { + case xgu == nil: + return errors.New("is nil") + case xgu.Namespace == nil: + return errors.New("'namespace' is missing") + case xgu.URI == nil: + return errors.New("'uri' is missing") + default: + return nil + } +} + +// Validate validates a list of XGenericURIs. +func (xgus XGenericURIs) Validate() error { + for i, xgu := range xgus { + if err := xgu.Validate(); err != nil { + return fmt.Errorf("%d. generic uri is invalid: %w", i+1, err) } } return nil } +// Validate validates a ProductIdentificationHelper. +func (pih *ProductIdentificationHelper) Validate() error { + if pih.Hashes != nil { + if err := pih.Hashes.Validate(); err != nil { + return fmt.Errorf("'hashes' is invalid: %w", err) + } + } + if pih.XGenericURIs != nil { + if err := pih.XGenericURIs.Validate(); err != nil { + return fmt.Errorf("'x_generic_uris' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a FullProductName. +func (fpn *FullProductName) Validate() error { + switch { + case fpn.Name == nil: + return errors.New("'name' is missing") + case fpn.ProductID == nil: + return errors.New("'product_id' is missing") + } + if fpn.ProductIdentificationHelper != nil { + if err := fpn.ProductIdentificationHelper.Validate(); err != nil { + return fmt.Errorf("'product_identification_helper' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a single Branch. +func (b *Branch) Validate() error { + switch { + case b.Category == nil: + return errors.New("'category' is missing") + case b.Name == nil: + return errors.New("'name' is missing") + } + if b.Product != nil { + if err := b.Product.Validate(); err != nil { + return fmt.Errorf("'product' is invalid: %w", err) + } + } + return b.Branches.Validate() +} + +// Validate validates a list of branches. +func (bs Branches) Validate() error { + for i, b := range bs { + if err := b.Validate(); err != nil { + return fmt.Errorf("%d. branch is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates a ProductTree. +func (pt *ProductTree) Validate() error { + return pt.Branches.Validate() +} + // Validate checks if the advisory is valid. // Returns an error if the validation fails otherwise nil. func (adv *Advisory) Validate() error { if adv.Document == nil { - return fmt.Errorf("the advisory is missing the property 'document'") + return errors.New("'document' is missing") } - - if validationError := adv.ValidateDocument(); validationError != nil { - return validationError + if err := adv.Document.Validate(); err != nil { + return fmt.Errorf("'document' is invalid: %w", err) } - if adv.ProductTree != nil { - if validationError := adv.ValidateProductTree(); validationError != nil { - return validationError + if err := adv.ProductTree.Validate(); err != nil { + return fmt.Errorf("'product_tree' is invalid: %w", err) } } - return nil } @@ -969,8 +1082,8 @@ func LoadAdvisory(fname string) (*Advisory, error) { if err := json.NewDecoder(f).Decode(&advisory); err != nil { return nil, err } - if validationError := advisory.Validate(); validationError != nil { - return nil, validationError + if err := advisory.Validate(); err != nil { + return nil, err } return &advisory, nil } From bdd7f24b317b8798352f1118c35dbb104d66a3c4 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Mon, 11 Sep 2023 21:31:45 +0200 Subject: [PATCH 17/24] fix: product tree properties --- csaf/advisory.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index f119c24..b334a31 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -376,8 +376,8 @@ type Relationship struct { // ProductTree contains product names that can be referenced elsewhere in the document. type ProductTree struct { Branches []*Branch `json:"branches,omitempty"` - FullProductNames []*FullProductName `json:"full_product_name,omitempty"` - ProductGroups *ProductGroups `json:"product_groups,omitempty"` + FullProductNames []*FullProductName `json:"full_product_names,omitempty"` + ProductGroups []*ProductGroup `json:"product_groups,omitempty"` RelationShips []*Relationship `json:"relationships,omitempty"` } From b5db976f053a8414e2302fad1eee4810d7d6e5f8 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Tue, 12 Sep 2023 16:21:00 +0200 Subject: [PATCH 18/24] completed validation of product tree --- csaf/advisory.go | 72 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index 14ed3fa..f98c2c0 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -134,6 +134,9 @@ type FullProductName struct { ProductIdentificationHelper *ProductIdentificationHelper `json:"product_identification_helper,omitempty"` } +// FullProductNames is a list of FullProductName. +type FullProductNames []FullProductName + // Branch reflects the 'branch' object in the list of branches. // It may contain either the property Branches OR Product. // If the category is 'product_version' the name MUST NOT contain @@ -380,15 +383,18 @@ type Relationship struct { } +// Relationships is a list of Relationship. +type Relationships []Relationship + // Branches is a list of Branch. type Branches []*Branch // ProductTree contains product names that can be referenced elsewhere in the document. type ProductTree struct { - Branches Branches `json:"branches,omitempty"` - FullProductNames []*FullProductName `json:"full_product_names,omitempty"` - ProductGroups *ProductGroups `json:"product_groups,omitempty"` - RelationShips []*Relationship `json:"relationships,omitempty"` + Branches Branches `json:"branches,omitempty"` + FullProductNames *FullProductNames `json:"full_product_names,omitempty"` + ProductGroups *ProductGroups `json:"product_groups,omitempty"` + RelationShips *Relationships `json:"relationships,omitempty"` } // CVE holds the MITRE standard Common Vulnerabilities and Exposures (CVE) tracking number for a vulnerability. @@ -746,11 +752,14 @@ type Vulnerability struct { Title *string `json:"title,omitempty"` } +// Vulnerabilities is a list of Vulnerability +type Vulnerabilities []*Vulnerability + // Advisory represents a CSAF advisory. type Advisory struct { Document *Document `json:"document"` // required ProductTree *ProductTree `json:"product_tree,omitempty"` - Vulnerabilities []*Vulnerability `json:"vulnerabilities,omitempty"` + Vulnerabilities *Vulnerabilities `json:"vulnerabilities,omitempty"` } // Validate validates a AggregateSeverity. @@ -1023,6 +1032,16 @@ func (fpn *FullProductName) Validate() error { return nil } +// Validate validates a list of Relationship elements. +func (fpns FullProductNames) Validate() error { + for i, f := range fpns { + if err := f.Validate(); err != nil { + return fmt.Errorf("%d. full product name is invalid: %w", i+1, err) + } + } + return nil +} + // Validate validates a single Branch. func (b *Branch) Validate() error { switch { @@ -1039,6 +1058,24 @@ func (b *Branch) Validate() error { return b.Branches.Validate() } +// Validate validates a single Relationship. +func (r *Relationship) Validate() error { + switch { + case r.Category == nil: + return errors.New("'category' is missing") + case r.ProductReference == nil: + return errors.New("'product_reference' is missing") + case r.RelatesToProductReference == nil: + return errors.New("'relates_to_product_reference' is missing") + } + if r.FullProductName != nil { + if err := r.FullProductName.Validate(); err != nil { + return fmt.Errorf("'product' is invalid: %w", err) + } + } + return nil +} + // Validate validates a list of branches. func (bs Branches) Validate() error { for i, b := range bs { @@ -1049,9 +1086,32 @@ func (bs Branches) Validate() error { return nil } +// Validate validates a list of Relationship elements. +func (rs Relationships) Validate() error { + for i, r := range rs { + if err := r.Validate(); err != nil { + return fmt.Errorf("%d. relationship is invalid: %w", i+1, err) + } + } + return nil +} + // Validate validates a ProductTree. func (pt *ProductTree) Validate() error { - return pt.Branches.Validate() + if err := pt.Branches.Validate(); err != nil { + return fmt.Errorf("'branches' is invalid: %w", err) + } + if pt.FullProductNames != nil { + if err := pt.FullProductNames.Validate(); err != nil { + return fmt.Errorf("'full_product_names is invalid: %w", err) + } + } + if pt.RelationShips != nil { + if err := pt.RelationShips.Validate(); err != nil { + return fmt.Errorf("'relationships' is invalid: %w", err) + } + } + return nil } // Validate checks if the advisory is valid. From c8f1361c52e769fdc23f9b426583be71de306e50 Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Tue, 12 Sep 2023 17:26:28 +0200 Subject: [PATCH 19/24] added validation for vulnerabilites --- csaf/advisory.go | 292 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 271 insertions(+), 21 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index f98c2c0..9ee219a 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -25,6 +25,9 @@ type Acknowledgement struct { URLs []*string `json:"urls,omitempty"` } +// Acknowledgements is a list of Acknowledgement elements. +type Acknowledgements []*Acknowledgement + // BranchCategory is the category of a branch. type BranchCategory string @@ -75,7 +78,7 @@ var csafBranchCategoryPattern = alternativesUnmarshal( type ProductID string // Products is a list of one or more unique ProductID elements. -type Products []ProductID +type Products []*ProductID // FileHashValue represents the value of a hash. type FileHashValue string @@ -135,7 +138,7 @@ type FullProductName struct { } // FullProductNames is a list of FullProductName. -type FullProductNames []FullProductName +type FullProductNames []*FullProductName // Branch reflects the 'branch' object in the list of branches. // It may contain either the property Branches OR Product. @@ -322,7 +325,7 @@ var langPattern = patternUnmarshal("^(([A-Za-z]{2,3}(-[A-Za-z]{3}(-[A-Za-z]{3}){ // Document contains meta-data about an advisory. type Document struct { - Acknowledgements []*Acknowledgement `json:"acknowledgements,omitempty"` + Acknowledgements *Acknowledgements `json:"acknowledgements,omitempty"` AggregateSeverity *AggregateSeverity `json:"aggregate_severity,omitempty"` Category *DocumentCategory `json:"category"` // required CSAFVersion *Version `json:"csaf_version"` // required @@ -348,7 +351,7 @@ type ProductGroup struct { // ProductGroups is a list of ProductGroupIDs type ProductGroups struct { - ProductGroupIDs []ProductGroupID `json:"product_group_ids"` // unique elements + ProductGroupIDs []*ProductGroupID `json:"product_group_ids"` // unique elements } // RelationshipCategory is the category of a relationship. @@ -384,7 +387,7 @@ type Relationship struct { } // Relationships is a list of Relationship. -type Relationships []Relationship +type Relationships []*Relationship // Branches is a list of Branch. type Branches []*Branch @@ -441,17 +444,23 @@ var csafFlagLabelPattern = alternativesUnmarshal( // code why a product is not affected. type Flag struct { Date *string `json:"date,omitempty"` - GroupIds *ProductGroups `json:"group_ids,omitempty"` + GroupIDs *ProductGroups `json:"group_ids,omitempty"` Label *FlagLabel `json:"label"` // required ProductIds *Products `json:"product_ids,omitempty"` } +// Flags is a list if Flag elements. +type Flags []*Flag + // VulnerabilityID is the identifier of a vulnerability. type VulnerabilityID struct { SystemName *string `json:"system_name"` // required Text *string `json:"text"` // required } +// VulneratilityIDs is a list of VulnerabilityID elements. +type VulnerabilityIDs []*VulnerabilityID + // InvolvementParty is the party of an involvement. type InvolvementParty string @@ -513,6 +522,9 @@ type Involvement struct { Summary *string `json:"summary,omitempty"` } +// Involvements is a list of Involvement elements. +type Involvements []*Involvement + // ProductStatus contains different lists of ProductIDs which provide details on // the status of the referenced product related to the current vulnerability. type ProductStatus struct { @@ -603,6 +615,9 @@ type Remediation struct { URL *string `json:"url,omitempty"` } +// Remediations is a list of Remediation elements. +type Remediations []*Remediation + // CVSSVersion2 is the version of a CVSS2 item. type CVSSVersion2 string @@ -701,6 +716,9 @@ type Score struct { Products *Products `json:"products"` // required } +// Scores is a list of Score elements. +type Scores []*Score + // ThreatCategory is the category of a threat. type ThreatCategory string @@ -727,6 +745,9 @@ type Threat struct { ProductIds *Products `json:"product_ids,omitempty"` } +// Threats is a list of Threat elements. +type Threats []*Threat + // Notes is a list of Note. type Notes []*Note @@ -735,21 +756,21 @@ type References []*Reference // Vulnerability contains all fields that are related to a single vulnerability in the document. type Vulnerability struct { - Acknowledgements []*Acknowledgement `json:"acknowledgements,omitempty"` - CVE *CVE `json:"cve,omitempty"` - CWE *CWE `json:"cwe,omitempty"` - DiscoveryDate *string `json:"discovery_date,omitempty"` - Flags []*Flag `json:"flags,omitempty"` - Ids []*VulnerabilityID `json:"ids,omitempty"` // unique ID elements - Involvements []*Involvement `json:"involvements,omitempty"` - Notes Notes `json:"notes,omitempty"` - ProductStatus *ProductStatus `json:"product_status,omitempty"` - References References `json:"references,omitempty"` - ReleaseDate *string `json:"release_date,omitempty"` - Remediations []*Remediation `json:"remediations,omitempty"` - Scores []*Score `json:"scores,omitempty"` - Threats []*Threat `json:"threats,omitempty"` - Title *string `json:"title,omitempty"` + Acknowledgements *Acknowledgements `json:"acknowledgements,omitempty"` + CVE *CVE `json:"cve,omitempty"` + CWE *CWE `json:"cwe,omitempty"` + DiscoveryDate *string `json:"discovery_date,omitempty"` + Flags *Flags `json:"flags,omitempty"` + IDs *VulnerabilityIDs `json:"ids,omitempty"` // unique ID elements + Involvements *Involvements `json:"involvements,omitempty"` + Notes Notes `json:"notes,omitempty"` + ProductStatus *ProductStatus `json:"product_status,omitempty"` + References References `json:"references,omitempty"` + ReleaseDate *string `json:"release_date,omitempty"` + Remediations *Remediations `json:"remediations,omitempty"` + Scores *Scores `json:"scores,omitempty"` + Threats *Threats `json:"threats,omitempty"` + Title *string `json:"title,omitempty"` } // Vulnerabilities is a list of Vulnerability @@ -1114,6 +1135,232 @@ func (pt *ProductTree) Validate() error { return nil } +// Validate validates a single Flag. +func (f *Flag) Validate() error { + if f.Label == nil { + return errors.New("'label' is missing") + } + return nil +} + +// Validate validates a list of Flag elements. +func (fs Flags) Validate() error { + for i, f := range fs { + if err := f.Validate(); err != nil { + return fmt.Errorf("%d. flag is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates a CWE. +func (cwe *CWE) Validate() error { + switch { + case cwe.ID == nil: + return errors.New("'id' is missing") + case cwe.Name == nil: + return errors.New("'name' is missing") + } + return nil +} + +// Validate validates a single VulnerabilityID. +func (id *VulnerabilityID) Validate() error { + switch { + case id.SystemName == nil: + return errors.New("'system_name' is missing") + case id.Text == nil: + return errors.New("'text' is missing") + } + return nil +} + +// Validate validates a list of VulnerabilityID elements. +func (ids VulnerabilityIDs) Validate() error { + for i, id := range ids { + if err := id.Validate(); err != nil { + return fmt.Errorf("%d. vulnerability id is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates a single Involvement. +func (iv *Involvement) Validate() error { + switch { + case iv.Party == nil: + return errors.New("'party' is missing") + case iv.Status == nil: + return errors.New("'status' is missing") + } + return nil +} + +// Validate validates a list of Involvement elements. +func (ivs Involvements) Validate() error { + for i, iv := range ivs { + if err := iv.Validate(); err != nil { + return fmt.Errorf("%d. involvement is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates a RestartRequired. +func (rr *RestartRequired) Validate() error { + if rr.Category == nil { + return errors.New("'category' is missing") + } + return nil +} + +// Validate validates a CVSS2 +func (c *CVSS2) Validate() error { + switch { + case c.Version == nil: + return errors.New("'version' is missing") + case c.VectorString == nil: + return errors.New("'vectorString' is missing") + case c.BaseScore == nil: + return errors.New("'baseScore' is missing") + } + return nil +} + +// Validate validates a CVSS3 +func (c *CVSS3) Validate() error { + switch { + case c.Version == nil: + return errors.New("'version' is missing") + case c.VectorString == nil: + return errors.New("'vectorString' is missing") + case c.BaseScore == nil: + return errors.New("'baseScore' is missing") + case c.BaseSeverity == nil: + return errors.New("'baseSeverity' is missing") + } + return nil +} + +// Validate validates a single Score. +func (s *Score) Validate() error { + if s.Products == nil { + return errors.New("'products' is missing") + } + if s.CVSS2 != nil { + if err := s.CVSS2.Validate(); err != nil { + return fmt.Errorf("'cvss_v2' is invalid: %w", err) + } + } + if s.CVSS3 != nil { + if err := s.CVSS3.Validate(); err != nil { + return fmt.Errorf("'cvss_v3' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a list of Score elements. +func (ss Scores) Validate() error { + for i, s := range ss { + if err := s.Validate(); err != nil { + return fmt.Errorf("%d. score is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates a single Remediation. +func (r *Remediation) Validate() error { + switch { + case r.Category == nil: + return errors.New("'category' is missing") + case r.Details == nil: + return errors.New("'details' is missing") + } + if r.RestartRequired != nil { + if err := r.RestartRequired.Validate(); err != nil { + return fmt.Errorf("'restart_required' is invalid: %w", err) + } + } + return nil +} + +// Validate validates a list of Remediation elements. +func (rms Remediations) Validate() error { + for i, r := range rms { + if err := r.Validate(); err != nil { + return fmt.Errorf("%d. remediation is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates a single Threat. +func (t *Threat) Validate() error { + switch { + case t.Category == nil: + return errors.New("'category' is missing") + case t.Details == nil: + return errors.New("'details' is missing") + } + return nil +} + +// Validate validates a list of Threat elements. +func (ts Threats) Validate() error { + for i, t := range ts { + if err := t.Validate(); err != nil { + return fmt.Errorf("%d. threat is invalid: %w", i+1, err) + } + } + return nil +} + +// Validate validates a single Vulnerability. +func (v *Vulnerability) Validate() error { + if v.CWE != nil { + if err := v.CWE.Validate(); err != nil { + return fmt.Errorf("'cwe' is invalid: %w", err) + } + } + if err := v.Flags.Validate(); err != nil { + return fmt.Errorf("'flags' is invalid: %w", err) + } + if err := v.IDs.Validate(); err != nil { + return fmt.Errorf("'ids' is invalid: %w", err) + } + if err := v.Involvements.Validate(); err != nil { + return fmt.Errorf("'involvements' is invalid: %w", err) + } + if err := v.Notes.Validate(); err != nil { + return fmt.Errorf("'notes' is invalid: %w", err) + } + if err := v.References.Validate(); err != nil { + return fmt.Errorf("'references' is invalid: %w", err) + } + if err := v.Remediations.Validate(); err != nil { + return fmt.Errorf("'remediations' is invalid: %w", err) + } + if err := v.Scores.Validate(); err != nil { + return fmt.Errorf("'scores' is invalid: %w", err) + } + if err := v.Threats.Validate(); err != nil { + return fmt.Errorf("'threats' is invalid: %w", err) + } + return nil +} + +// Validate validates a list of Vulnerability elements. +func (vs Vulnerabilities) Validate() error { + for i, v := range vs { + if err := v.Validate(); err != nil { + return fmt.Errorf("%d. vulnerability is invalid: %w", i+1, err) + } + } + return nil +} + // Validate checks if the advisory is valid. // Returns an error if the validation fails otherwise nil. func (adv *Advisory) Validate() error { @@ -1128,6 +1375,9 @@ func (adv *Advisory) Validate() error { return fmt.Errorf("'product_tree' is invalid: %w", err) } } + if err := adv.Vulnerabilities.Validate(); err != nil { + return fmt.Errorf("'vulnerabilities' is invalid: %w", err) + } return nil } From 37cdda7c42cdbe245d784819f37677b71b47a3bb Mon Sep 17 00:00:00 2001 From: Christoph Klassen Date: Wed, 13 Sep 2023 08:01:00 +0200 Subject: [PATCH 20/24] dont use pointer for lists of elements --- csaf/advisory.go | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index 9ee219a..5955b10 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -756,21 +756,21 @@ type References []*Reference // Vulnerability contains all fields that are related to a single vulnerability in the document. type Vulnerability struct { - Acknowledgements *Acknowledgements `json:"acknowledgements,omitempty"` - CVE *CVE `json:"cve,omitempty"` - CWE *CWE `json:"cwe,omitempty"` - DiscoveryDate *string `json:"discovery_date,omitempty"` - Flags *Flags `json:"flags,omitempty"` - IDs *VulnerabilityIDs `json:"ids,omitempty"` // unique ID elements - Involvements *Involvements `json:"involvements,omitempty"` - Notes Notes `json:"notes,omitempty"` - ProductStatus *ProductStatus `json:"product_status,omitempty"` - References References `json:"references,omitempty"` - ReleaseDate *string `json:"release_date,omitempty"` - Remediations *Remediations `json:"remediations,omitempty"` - Scores *Scores `json:"scores,omitempty"` - Threats *Threats `json:"threats,omitempty"` - Title *string `json:"title,omitempty"` + Acknowledgements Acknowledgements `json:"acknowledgements,omitempty"` + CVE *CVE `json:"cve,omitempty"` + CWE *CWE `json:"cwe,omitempty"` + DiscoveryDate *string `json:"discovery_date,omitempty"` + Flags Flags `json:"flags,omitempty"` + IDs VulnerabilityIDs `json:"ids,omitempty"` // unique ID elements + Involvements Involvements `json:"involvements,omitempty"` + Notes Notes `json:"notes,omitempty"` + ProductStatus *ProductStatus `json:"product_status,omitempty"` + References References `json:"references,omitempty"` + ReleaseDate *string `json:"release_date,omitempty"` + Remediations Remediations `json:"remediations,omitempty"` + Scores Scores `json:"scores,omitempty"` + Threats Threats `json:"threats,omitempty"` + Title *string `json:"title,omitempty"` } // Vulnerabilities is a list of Vulnerability @@ -778,9 +778,9 @@ type Vulnerabilities []*Vulnerability // Advisory represents a CSAF advisory. type Advisory struct { - Document *Document `json:"document"` // required - ProductTree *ProductTree `json:"product_tree,omitempty"` - Vulnerabilities *Vulnerabilities `json:"vulnerabilities,omitempty"` + Document *Document `json:"document"` // required + ProductTree *ProductTree `json:"product_tree,omitempty"` + Vulnerabilities Vulnerabilities `json:"vulnerabilities,omitempty"` } // Validate validates a AggregateSeverity. @@ -1375,8 +1375,10 @@ func (adv *Advisory) Validate() error { return fmt.Errorf("'product_tree' is invalid: %w", err) } } - if err := adv.Vulnerabilities.Validate(); err != nil { - return fmt.Errorf("'vulnerabilities' is invalid: %w", err) + if adv.Vulnerabilities != nil { + if err := adv.Vulnerabilities.Validate(); err != nil { + return fmt.Errorf("'vulnerabilities' is invalid: %w", err) + } } return nil } From 20b2bd27b35496f48296f8f47024ee90acb1bb36 Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Wed, 13 Sep 2023 14:35:22 +0200 Subject: [PATCH 21/24] Fix typo in comment. --- csaf/advisory.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csaf/advisory.go b/csaf/advisory.go index 5955b10..95a6821 100644 --- a/csaf/advisory.go +++ b/csaf/advisory.go @@ -458,7 +458,7 @@ type VulnerabilityID struct { Text *string `json:"text"` // required } -// VulneratilityIDs is a list of VulnerabilityID elements. +// VulnerabilityIDs is a list of VulnerabilityID elements. type VulnerabilityIDs []*VulnerabilityID // InvolvementParty is the party of an involvement. From 5f2596665a46ed735d65e327b30933e907d76523 Mon Sep 17 00:00:00 2001 From: JanHoefelmeyer Date: Thu, 12 Oct 2023 12:07:40 +0200 Subject: [PATCH 22/24] Add new binary, the searcher(, the main and docs) from https://github.com/cintek/csaf_advisory_example+ --- cmd/csaf_searcher/main.go | 126 ++++++++++++++++++++++++++++++++++++++ docs/csaf_searcher.md | 16 +++++ 2 files changed, 142 insertions(+) create mode 100644 cmd/csaf_searcher/main.go create mode 100644 docs/csaf_searcher.md diff --git a/cmd/csaf_searcher/main.go b/cmd/csaf_searcher/main.go new file mode 100644 index 0000000..871433d --- /dev/null +++ b/cmd/csaf_searcher/main.go @@ -0,0 +1,126 @@ +// Package main implements a simple demo program to +// work with the csaf_distribution library. +package main + +import ( + "flag" + "fmt" + "log" + "os" + "slices" + "strings" + + "github.com/csaf-poc/csaf_distribution/v2/csaf" +) + +func main() { + flag.Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), + "Usage:\n %s [OPTIONS] files...\n\nOptions:\n", os.Args[0]) + flag.PrintDefaults() + } + idsString := flag.String("p", "", "ID1,ID2,...") + flag.Parse() + + files := flag.Args() + if len(files) == 0 { + log.Println("No files given.") + return + } + if err := run(files, *idsString); err != nil { + log.Fatalf("error: %v\n", err) + } +} + +// run prints PURLs belonging to the given Product IDs. +func run(files []string, ids string) error { + + uf := newURLFinder(strings.Split(ids, ",")) + + for _, file := range files { + adv, err := csaf.LoadAdvisory(file) + if err != nil { + return fmt.Errorf("loading %q failed: %w", file, err) + } + uf.findURLs(adv) + uf.dumpURLs() + uf.clear() + } + + return nil +} + +// urlFinder helps to find the URLs of a set of product ids in advisories. +type urlFinder struct { + ids []csaf.ProductID + urls [][]csaf.PURL +} + +// newURLFinder creates a new urlFinder for given ids. +func newURLFinder(ids []string) *urlFinder { + uf := &urlFinder{ + ids: make([]csaf.ProductID, len(ids)), + urls: make([][]csaf.PURL, len(ids)), + } + for i := range uf.ids { + uf.ids[i] = csaf.ProductID(ids[i]) + } + return uf +} + +// clear resets the url finder after a run on an advisory. +func (uf *urlFinder) clear() { + clear(uf.urls) +} + +// dumpURLs dumps the found URLs to stdout. +func (uf *urlFinder) dumpURLs() { + for i, urls := range uf.urls { + if len(urls) == 0 { + continue + } + fmt.Printf("Found URLs for %s:\n", uf.ids[i]) + for j, url := range urls { + fmt.Printf("%d. %s\n", j+1, url) + } + } +} + +// findURLs find the URLs in an advisory. +func (uf *urlFinder) findURLs(adv *csaf.Advisory) { + tree := adv.ProductTree + if tree == nil { + return + } + + // If we have found it and we have a valid URL add unique. + add := func(idx int, h *csaf.ProductIdentificationHelper) { + if idx != -1 && h != nil && h.PURL != nil && + !slices.Contains(uf.urls[idx], *h.PURL) { + uf.urls[idx] = append(uf.urls[idx], *h.PURL) + } + } + + // First iterate over full product names. + if names := tree.FullProductNames; names != nil { + for _, name := range *names { + if name != nil && name.ProductID != nil { + add(slices.Index(uf.ids, *name.ProductID), name.ProductIdentificationHelper) + } + } + } + + // Second traverse the branches recursively. + var recBranch func(*csaf.Branch) + recBranch = func(b *csaf.Branch) { + if p := b.Product; p != nil && p.ProductID != nil { + add(slices.Index(uf.ids, *p.ProductID), p.ProductIdentificationHelper) + } + for _, c := range b.Branches { + recBranch(c) + } + } + for _, b := range tree.Branches { + recBranch(b) + } +} diff --git a/docs/csaf_searcher.md b/docs/csaf_searcher.md new file mode 100644 index 0000000..e821025 --- /dev/null +++ b/docs/csaf_searcher.md @@ -0,0 +1,16 @@ +# csaf_advisory_example + +This is a small searcher using the advisory model to search for PURLs belonging to a product ID in an advisory of the CSAF 2.0 standard. + +Usage: +``` + +csaf_advisory_example OPTIONS [files...] + +Application Options: +-p The Product ID + +Help Options: +-h, --help Show a help message + +``` From d9e579242b7b7bf567f4ee91549a07b484622980 Mon Sep 17 00:00:00 2001 From: JanHoefelmeyer Date: Wed, 18 Oct 2023 10:27:59 +0200 Subject: [PATCH 23/24] Added csaf_searcher to README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1dd0233..3a73283 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ Can be used for automated forwarding of CSAF documents. ### [csaf_validator](docs/csaf_validator.md) is a tool to validate local advisories files against the JSON Schema and an optional remote validator. +### [csaf_searcher](docs/csaf_searcher.md) +is a tool to search through local advisories. It finds PURLs based on the product ID of an advisory. + ## Tools for advisory providers ### [csaf_provider](docs/csaf_provider.md) From 5215d78331cb59380792312b5860054e8edee372 Mon Sep 17 00:00:00 2001 From: JanHoefelmeyer Date: Wed, 18 Oct 2023 11:22:32 +0200 Subject: [PATCH 24/24] Adjust requirement --- cmd/csaf_searcher/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/csaf_searcher/main.go b/cmd/csaf_searcher/main.go index 871433d..80c308e 100644 --- a/cmd/csaf_searcher/main.go +++ b/cmd/csaf_searcher/main.go @@ -10,7 +10,7 @@ import ( "slices" "strings" - "github.com/csaf-poc/csaf_distribution/v2/csaf" + "github.com/csaf-poc/csaf_distribution/v3/csaf" ) func main() {