vex

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 26, 2024 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// TypeURI is the type used to describe VEX documents, e.g. within [in-toto
	// statements].
	//
	// [in-toto statements]: https://github.com/in-toto/attestation/blob/main/spec/README.md#statement
	TypeURI = "https://openvex.dev/ns"

	// SpecVersion is the latest released version of the openvex. This constant
	// is used to form the context URL when generating new documents.
	SpecVersion = "0.2.0"

	// DefaultAuthor is the default value for a document's Author field.
	DefaultAuthor = "Unknown Author"

	// DefaultRole is the default value for a document's AuthorRole field.
	DefaultRole = ""

	// Context is the URL of the json-ld context definition
	Context = "https://openvex.dev/ns"

	// PublicNamespace is the public openvex namespace for common @ids
	PublicNamespace = "https://openvex.dev/docs"

	// NoActionStatementMsg is the action statement that informs that there is no action statement :/
	NoActionStatementMsg = "No action statement provided"
)

Variables

View Source
var DefaultNamespace = PublicNamespace

DefaultNamespace is the URL that will be used to generate new IRIs for generated documents and nodes. It is set to the OpenVEX public namespace by default.

Functions

func ContextLocator

func ContextLocator() string

ContextLocator returns the locator string for the current OpenVEX version.

func DateFromEnv

func DateFromEnv() (*time.Time, error)

DateFromEnv returns a time object representing the time specified in the `SOURCE_DATE_EPOCH` environment variable, whose value can be specified as either UNIX seconds or as a RFC3339 value.

func Justifications

func Justifications() []string

Justifications returns a list of the valid Justification values.

func PurlMatches

func PurlMatches(purl1, purl2 string) bool

PurlMatches returns true if purl1 matches the more specific purl2. It takes into account all segments of the pURL, including qualifiers. purl1 is considered to be more general and purl2 more specific and thus, the following considerations are made when matching:

  • If purl1 does not have a version, it will match any version in purl2
  • If purl1 has qualifers, purl2 must have the same set of qualifiers to match.
  • Inversely, purl2 can have any number of qualifiers not found on purl1 and still match.
  • If any of the purls is invalid, the function returns false.

Purl version ranges are not supported yet but they will be in a future version of this matching function.

func SortStatements

func SortStatements(stmts []Statement, documentTimestamp time.Time)

SortStatements does an "in-place" sort of the given slice of VEX statements.

The documentTimestamp parameter is needed because statements without timestamps inherit the timestamp of the document.

func Statuses

func Statuses() []string

Statuses returns a list of the valid Status values.

Types

type Algorithm

type Algorithm string
const (
	MD5        Algorithm = "md5"
	SHA1       Algorithm = "sha1"
	SHA256     Algorithm = "sha-256"
	SHA384     Algorithm = "sha-384"
	SHA512     Algorithm = "sha-512"
	SHA3224    Algorithm = "sha3-224"
	SHA3256    Algorithm = "sha3-256"
	SHA3384    Algorithm = "sha3-384"
	SHA3512    Algorithm = "sha3-512"
	BLAKE2S256 Algorithm = "blake2s-256"
	BLAKE2B256 Algorithm = "blake2b-256"
	BLAKE2B512 Algorithm = "blake2b-512"
	BLAKE3     Algorithm = "blake3"
)

The following list of algorithms follows and expands the IANA list at: https://www.iana.org/assignments/named-information/named-information.xhtml It expands it, trying to keep the naming pattern.

type Component

type Component struct {
	// ID is an IRI identifying the component. It is optional as the component
	// can also be identified using hashes or software identifiers.
	ID string `json:"@id,omitempty"`

	// Hashes is a map of hashes to identify the component using cryptographic
	// hashes.
	Hashes map[Algorithm]Hash `json:"hashes,omitempty"`

	// Identifiers is a list of software identifiers that describe the component.
	Identifiers map[IdentifierType]string `json:"identifiers,omitempty"`

	// Supplier is an optional machine-readable identifier for the supplier of
	// the component. Valid examples include email address or IRIs.
	Supplier string `json:"supplier,omitempty"`
}

Component abstracts the common construct shared by product and subcomponents allowing OpenVEX statements to point to a piece of software by referencing it by hash or identifier.

The ID should be an IRI uniquely identifying the product. Software can be referenced as a VEX product or subcomponent using only its IRI or it may be referenced by its crptographic hashes and/or other identifiers but, in no case, must an IRI describe two different pieces of software or used to describe a range of software.

func (*Component) Matches

func (c *Component) Matches(identifier string) bool

Matches returns true if one of the components identifiers match a string. All types except purl are checked string vs string. Purls are a special case and can match from more generic to more specific. Note that a future iterarion of this function will treat CPEs in the same way.

type Hash

type Hash string

type IdentifierLocator

type IdentifierLocator string

type IdentifierType

type IdentifierType string
const (
	PURL  IdentifierType = "purl"
	CPE22 IdentifierType = "cpe22"
	CPE23 IdentifierType = "cpe23"
)

type Justification

type Justification string

Justification describes why a given component is not affected by a vulnerability.

const (
	// ComponentNotPresent means the vulnerable component is not included in the artifact.
	//
	// ComponentNotPresent is a strong justification that the artifact is not affected.
	ComponentNotPresent Justification = "component_not_present"

	// VulnerableCodeNotPresent means the vulnerable component is included in
	// artifact, but the vulnerable code is not present. Typically, this case occurs
	// when source code is configured or built in a way that excluded the vulnerable
	// code.
	//
	// VulnerableCodeNotPresent is a strong justification that the artifact is not affected.
	VulnerableCodeNotPresent Justification = "vulnerable_code_not_present"

	// VulnerableCodeNotInExecutePath means the vulnerable code (likely in
	// [subcomponent_id]) can not be executed as it is used by [product_id].
	// Typically, this case occurs when [product_id] includes the vulnerable
	// [subcomponent_id] and the vulnerable code but does not call or use the
	// vulnerable code.
	VulnerableCodeNotInExecutePath Justification = "vulnerable_code_not_in_execute_path"

	// VulnerableCodeCannotBeControlledByAdversary means the vulnerable code cannot
	// be controlled by an attacker to exploit the vulnerability.
	//
	// This justification could be difficult to prove conclusively.
	VulnerableCodeCannotBeControlledByAdversary Justification = "vulnerable_code_cannot_be_controlled_by_adversary"

	// InlineMitigationsAlreadyExist means [product_id] includes built-in protections
	// or features that prevent exploitation of the vulnerability. These built-in
	// protections cannot be subverted by the attacker and cannot be configured or
	// disabled by the user. These mitigations completely prevent exploitation based
	// on known attack vectors.
	//
	// This justification could be difficult to prove conclusively. History is
	// littered with examples of mitigation bypasses, typically involving minor
	// modifications of existing exploit code.
	InlineMitigationsAlreadyExist Justification = "inline_mitigations_already_exist"
)

func (Justification) Valid

func (j Justification) Valid() bool

Valid returns a bool indicating whether the Justification value is equal to one of the enumerated allowed values for Justification.

type MergeOptions

type MergeOptions struct {
	DocumentID      string   // ID to use in the new document
	Author          string   // Author to use in the new document
	AuthorRole      string   // Role of the document author
	Products        []string // Product IDs to consider
	Vulnerabilities []string // IDs of vulnerabilities to merge
}

type Metadata

type Metadata struct {
	// Context is the URL pointing to the jsonld context definition
	Context string `json:"@context"`

	// ID is the identifying string for the VEX document. This should be unique per
	// document.
	ID string `json:"@id"`

	// Author is the identifier for the author of the VEX statement, ideally a common
	// name, may be a URI. [author] is an individual or organization. [author]
	// identity SHOULD be cryptographically associated with the signature of the VEX
	// statement or document or transport.
	Author string `json:"author"`

	// AuthorRole describes the role of the document Author.
	AuthorRole string `json:"role,omitempty"`

	// Timestamp defines the time at which the document was issued.
	Timestamp *time.Time `json:"timestamp"`

	// LastUpdated marks the time when the document had its last update. When the
	// document changes both version and this field should be updated.
	LastUpdated *time.Time `json:"last_updated,omitempty"`

	// Version is the document version. It must be incremented when any content
	// within the VEX document changes, including any VEX statements included within
	// the VEX document.
	Version int `json:"version"`

	// Tooling expresses how the VEX document and contained VEX statements were
	// generated. It's optional. It may specify tools or automated processes used in
	// the document or statement generation.
	Tooling string `json:"tooling,omitempty"`

	// Supplier is an optional field.
	Supplier string `json:"supplier,omitempty"`
}

The Metadata type represents the metadata associated with a VEX document.

type Product

type Product struct {
	Component
	Subcomponents []Subcomponent `json:"subcomponents,omitempty"`
}

Product abstracts the VEX product into a struct that can identify software through various means. The main one is the ID field which contains an IRI identifying the product, possibly pointing to another document with more data, like an SBOM. The Product struct also supports naming software using its identifiers and/or cryptographic hashes.

func (*Product) Matches

func (p *Product) Matches(identifier, subIdentifier string) bool

Product returns true if an identifier and subcomponent identifier match any of the identifiers in the product and subcomponents.

type Statement

type Statement struct {
	// ID is an optional identifier for the statement. It takes an IRI and must
	// be unique for each statement in the document.
	ID string `json:"@id,omitempty"`

	// [vul_id] SHOULD use existing and well known identifiers, for example:
	// CVE, the Global Security Database (GSD), or a supplier’s vulnerability
	// tracking system. It is expected that vulnerability identification systems
	// are external to and maintained separately from VEX.
	//
	// [vul_id] MAY be URIs or URLs.
	// [vul_id] MAY be arbitrary and MAY be created by the VEX statement [author].
	Vulnerability Vulnerability `json:"vulnerability,omitempty"`

	// Timestamp is the time at which the information expressed in the Statement
	// was known to be true.
	Timestamp *time.Time `json:"timestamp,omitempty"`

	// LastUpdated records the time when the statement last had a modification
	LastUpdated *time.Time `json:"last_updated,omitempty"`

	// Product
	// Product details MUST specify what Status applies to.
	// Product details MUST include [product_id] and MAY include [subcomponent_id].
	Products []Product `json:"products,omitempty"`

	// A VEX statement MUST provide Status of the vulnerabilities with respect to the
	// products and components listed in the statement. Status MUST be one of the
	// Status const values, some of which have further options and requirements.
	Status Status `json:"status"`

	// [status_notes] MAY convey information about how [status] was determined
	// and MAY reference other VEX information.
	StatusNotes string `json:"status_notes,omitempty"`

	// For ”not_affected” status, a VEX statement MUST include a status Justification
	// that further explains the status.
	Justification Justification `json:"justification,omitempty"`

	// For ”not_affected” status, a VEX statement MAY include an ImpactStatement
	// that contains a description why the vulnerability cannot be exploited.
	ImpactStatement string `json:"impact_statement,omitempty"`

	// For "affected" status, a VEX statement MUST include an ActionStatement that
	// SHOULD describe actions to remediate or mitigate [vul_id].
	ActionStatement          string     `json:"action_statement,omitempty"`
	ActionStatementTimestamp *time.Time `json:"action_statement_timestamp,omitempty"`
}

A Statement is a declaration conveying a single [status] for a single [vul_id] for one or more [product_id]s. A VEX Statement exists within a VEX Document.

func (*Statement) MarshalJSON

func (stmt *Statement) MarshalJSON() ([]byte, error)

MarshalJSON the document object overrides its marshaling function to normalize the timezones in all dates to Zulu.

func (*Statement) Matches

func (stmt *Statement) Matches(vuln, product string, subcomponents []string) bool

Matches returns true if the statement matches the specified vulnerability identifier, the VEX product and any of the identifiers from the received list.

func (*Statement) MatchesProduct

func (stmt *Statement) MatchesProduct(identifier, subidentifier string) bool

MatchesProduct returns true if the statement matches the identifier string with an optional subcomponent identifier

func (Statement) Validate

func (stmt Statement) Validate() error

Validate checks to see whether the given Statement is valid. If it's not, an error is returned explaining the reason the Statement is invalid. Otherwise, nil is returned.

type Status

type Status string

Status describes the exploitability status of a component with respect to a vulnerability.

const (
	// StatusNotAffected means no remediation or mitigation is required.
	StatusNotAffected Status = "not_affected"

	// StatusAffected means actions are recommended to remediate or mitigate.
	StatusAffected Status = "affected"

	// StatusFixed means the listed products or components have been remediated (by including fixes).
	StatusFixed Status = "fixed"

	// StatusUnderInvestigation means the author of the VEX statement is investigating.
	StatusUnderInvestigation Status = "under_investigation"
)

func StatusFromCSAF

func StatusFromCSAF(csafStatus string) Status

StatusFromCSAF returns a vex status from the CSAF status

func (Status) Valid

func (s Status) Valid() bool

Valid returns a bool indicating whether the Status value is equal to one of the enumerated allowed values for Status.

type Subcomponent

type Subcomponent struct {
	Component
}

Subcomponents are nested entries that list the product's components that are related to the statement's vulnerability. The main difference with Product and Subcomponent objects is that a Subcomponent cannot nest components.

type VEX

type VEX struct {
	Metadata
	Statements []Statement `json:"statements"`
}

The VEX type represents a VEX document and all of its contained information.

func Load

func Load(path string) (*VEX, error)

Load reads the VEX document file at the given path and returns a decoded VEX object. If Load is unable to read the file or decode the document, it returns an error.

func MergeDocuments

func MergeDocuments(docs []*VEX) (*VEX, error)

MergeDocuments is a convenience wrapper over MergeDocumentsWithOptions that does not take options.

func MergeDocumentsWithOptions

func MergeDocumentsWithOptions(mergeOpts *MergeOptions, docs []*VEX) (*VEX, error)

Merge combines the statements from a number of documents into a new one, preserving time context from each of them.

func MergeFiles

func MergeFiles(filePaths []string) (*VEX, error)

MergeFiles is a convenience wrapper around MergeFilesWithOptions that does not take options but performs the merge using the default options

func MergeFilesWithOptions

func MergeFilesWithOptions(mergeOpts *MergeOptions, filePaths []string) (*VEX, error)

MergeFilesWithOptions opens a list of vex documents and after parsing them merges them into a single file using the specified merge options.

func New

func New() VEX

New returns a new, initialized VEX document.

func Open

func Open(path string) (*VEX, error)

Open tries to autodetect the vex format and open it

func OpenCSAF

func OpenCSAF(path string, products []string) (*VEX, error)

OpenCSAF opens a CSAF document and builds a VEX object from it.

func OpenJSON

func OpenJSON(path string) (*VEX, error)

OpenJSON opens an OpenVEX file in JSON format.

func OpenYAML

func OpenYAML(path string) (*VEX, error)

OpenYAML opens a VEX file in YAML format.

func Parse

func Parse(data []byte) (*VEX, error)

Parse parses an OpenVEX document in the latest version from the data byte array.

func SortDocuments

func SortDocuments(docs []*VEX) []*VEX

SortDocuments sorts and returns a slice of documents based on their date. VEXes should be applied sequentially in chronological order as they capture knowledge about an artifact as it changes over time.

func (*VEX) CanonicalHash

func (vexDoc *VEX) CanonicalHash() (string, error)

CanonicalHash returns a hash representing the state of impact statements expressed in it. This hash should be constant as long as the impact statements are not modified. Changes in extra information and metadata will not alter the hash.

func (*VEX) EffectiveStatement

func (vexDoc *VEX) EffectiveStatement(product, vulnID string) (s *Statement)

EffectiveStatement returns the latest VEX statement for a given product and vulnerability, that is the statement that contains the latest data about impact to a given product.

func (*VEX) GenerateCanonicalID

func (vexDoc *VEX) GenerateCanonicalID() (string, error)

GenerateCanonicalID generates an ID for the document. The ID will be based on the canonicalization hash. This means that documents with the same impact statements will always get the same ID. Trying to generate the id of a doc with an existing ID will not do anything.

func (*VEX) MarshalJSON

func (vexDoc *VEX) MarshalJSON() ([]byte, error)

MarshalJSON the document object overrides its marshaling function to normalize the timezones in all dates to Zulu.

func (*VEX) Matches

func (vexDoc *VEX) Matches(vulnID, product string, subcomponents []string) []Statement

Matches returns the latest VEX statement for a given product and vulnerability. That is, the statement that contains the latest data with impact data of a vulnerability on a given product.

func (*VEX) StatementFromID deprecated

func (vexDoc *VEX) StatementFromID(id string) *Statement

StatementFromID returns a statement for a given vulnerability if there is one.

Deprecated: vex.StatementFromID is deprecated and will be removed in an upcoming version

func (*VEX) StatementsByVulnerability

func (vexDoc *VEX) StatementsByVulnerability(id string) []Statement

StatementsByVulnerability returns a list of statements that apply to a vulnerability ID. These are guaranteed to be ordered according to the VEX history.

func (*VEX) ToJSON

func (vexDoc *VEX) ToJSON(w io.Writer) error

ToJSON serializes the VEX document to JSON and writes it to the passed writer.

type Vulnerability

type Vulnerability struct {
	//  ID is an IRI to reference the vulnerability in the statement.
	ID string `json:"@id,omitempty"`

	// Name is the main vulnerability identifier.
	Name VulnerabilityID `json:"name,omitempty"`

	// Description is a short free form text description of the vulnerability.
	Description string `json:"description,omitempty"`

	// Aliases is a list of other vulnerability identifier strings that
	// locate the vulnerability in other tracking systems.
	Aliases []VulnerabilityID `json:"aliases,omitempty"`
}

Vulnerability is a struct that captures the vulnerability identifier and its aliases. When defined, the ID field should be an IRI.

func (*Vulnerability) Matches

func (v *Vulnerability) Matches(identifier string) bool

Matches returns true if the vulnerability's name or aliases matches the identifier string.

type VulnerabilityID

type VulnerabilityID string

VulnerabilityID is a string that captures a vulnerability identifier. It is a free form string but it is intended to capture the identifiers used by tracking systems.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL