Documentation
¶
Overview ¶
Package normalize provides utilities for normalizing package identifiers. This file handles mapping binary package names to their source package names for Linux distributions (Debian, Alpine), enabling vulnerability matching against security advisories that reference source packages.
Index ¶
- Constants
- Variables
- func ArtifactPurl(scanner string, assetName string) string
- func BeautifyPURL(pURL string) (string, error)
- func BomIsSBOM(bom *cdx.BOM) bool
- func CheckVersion(exactVersion, introduced, fixed *string, ...) (bool, error)
- func ConvertToSemver(originalVersion string) (string, error)
- func DeepSort(el any) any
- func EncodeCanonical(obj interface{}) (out []byte, err error)
- func FixFixedVersion(purl string, fixedVersion *string) *string
- func PURLToString(purl packageurl.PackageURL) (string, error)
- func ParseGraphNodeID(id string) (prefix, name string)
- func Purlify(artifactName string, assetVersionName string) string
- func QualifiersMapToString(qualifiers map[string]string) string
- func SanitizeExternalReferencesURL(url string) string
- func SemverCompare(v1, v2 string) int
- func SemverSort(versions []string)
- func SortStringsSlice(slice []string) []string
- func StructuralCompareCdxBoms(a, b *cdx.BOM) error
- func ToPurlWithoutVersion(purl packageurl.PackageURL) string
- func UppercaseCVEID(cveID string) string
- type BOMMetadata
- type FlatGraph
- type GraphComponent
- type GraphDiff
- type GraphNode
- type GraphNodeType
- type InfoSourceType
- type Path
- type PurlMatchContext
- type SBOMGraph
- func NewSBOMGraph() *SBOMGraph
- func SBOMGraphFromComponents[T GraphComponent](components []T, licenseOverwrites map[string]string) (*SBOMGraph, error)
- func SBOMGraphFromCycloneDX(bom *cdx.BOM, artifactName, infoSourceID string, ...) (*SBOMGraph, error)
- func SBOMGraphFromVulnerabilities(vulns []cdx.Vulnerability) *SBOMGraph
- func (g *SBOMGraph) AddArtifact(name string) string
- func (g *SBOMGraph) AddComponent(comp cdx.Component) string
- func (g *SBOMGraph) AddEdge(parentID, childID string)
- func (g *SBOMGraph) AddInfoSource(artifactID, sourceID string, sourceType InfoSourceType) string
- func (g *SBOMGraph) AddVulnerability(vuln cdx.Vulnerability)
- func (g *SBOMGraph) Artifacts() iter.Seq[*GraphNode]
- func (g *SBOMGraph) Children(nodeID string) iter.Seq[*GraphNode]
- func (g *SBOMGraph) ChildrenOfType(nodeID string, nodeType GraphNodeType) iter.Seq[*GraphNode]
- func (g *SBOMGraph) ClearScope()
- func (g *SBOMGraph) Clone() *SBOMGraph
- func (g *SBOMGraph) ComponentEdges() iter.Seq2[string, string]
- func (g *SBOMGraph) Components() iter.Seq[*GraphNode]
- func (g *SBOMGraph) ComponentsWithMultipleSources() []string
- func (g *SBOMGraph) CountInfoSourcesPerComponent() map[string]map[InfoSourceType]int
- func (g *SBOMGraph) CurrentScopeID() string
- func (g *SBOMGraph) DeleteArtifactFromGraph(artifactName string) GraphDiff
- func (g *SBOMGraph) Edges() iter.Seq2[string, string]
- func (g *SBOMGraph) FindAllComponentOnlyPathsToPURL(purl string, limit int) []Path
- func (g *SBOMGraph) GetArtifactIDs() []string
- func (g *SBOMGraph) GetInfoSourceIDs(artifactID string) []string
- func (g *SBOMGraph) GetInfoSourceNode(infoSourceID string) *GraphNode
- func (g *SBOMGraph) GetParentIDs(nodeID string) []string
- func (g *SBOMGraph) GetRootID() string
- func (g *SBOMGraph) HasInfoSource(infoSourceID string) bool
- func (g *SBOMGraph) InfoSources() iter.Seq[*GraphNode]
- func (g *SBOMGraph) IsScoped() bool
- func (g *SBOMGraph) LicenseDistribution() map[string]int
- func (g *SBOMGraph) MergeGraph(other *SBOMGraph) GraphDiff
- func (g *SBOMGraph) MinimalTreeToPURL(purl string, maxDepth int) minimalTree
- func (g *SBOMGraph) Node(id string) *GraphNode
- func (g *SBOMGraph) NodeIDsAndEdges() FlatGraph
- func (g *SBOMGraph) NodesOfType(nodeType GraphNodeType) iter.Seq[*GraphNode]
- func (g *SBOMGraph) Scope(id string) error
- func (g *SBOMGraph) ScopeToArtifact(artifactName string) error
- func (g *SBOMGraph) ScopeToInfoSource(infoSource string, t InfoSourceType) error
- func (g *SBOMGraph) ToCycloneDX(metadata BOMMetadata) *cdx.BOM
- func (g *SBOMGraph) ToMinimalTree() minimalTree
- func (g *SBOMGraph) Vulnerabilities() iter.Seq[*cdx.Vulnerability]
- type VersionInterpretationType
- type VexReport
Constants ¶
const GraphRootNodeID = "ROOT"
Variables ¶
var ErrNodeNotReachable = fmt.Errorf("node not reachable from current scope")
var PURLEcosystems = map[string]string{
"Alpine": "apk",
"crates.io": "cargo",
"Debian": "deb",
"Go": "golang",
"Hackage": "hackage",
"Hex": "hex",
"Maven": "maven",
"npm": "npm",
"NuGet": "nuget",
"OSS-Fuzz": "generic",
"Packagist": "composer",
"Pub": "pub",
"PyPI": "pypi",
"RubyGems": "gem",
}
PURL conversion utilities
var ValidSemverRegex = regexp.MustCompile(`^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
Regex for validating a correct semver.
Functions ¶
func ArtifactPurl ¶
func BeautifyPURL ¶
function to make purl look more visually appealing
func CheckVersion ¶
func ConvertToSemver ¶
ConvertToSemver converts various version formats to semantic versioning format. It handles: - Epoch prefixes (e.g., "2:1.2.3" -> "1.2.3") - "v" prefixes (e.g., "v1.2.3" -> "1.2.3") - Pre-release identifiers with "-" (e.g., "1.2.3-rc1") - Build metadata with "+" (e.g., "1.2.3+build1") - Tilde versions "~" (e.g., "1.2.3~rc1" -> "1.2.3-rc1") - Missing version segments (e.g., "1.2" -> "1.2.0")
Returns an error if: - Version contains invalid characters (only 0-9 and . allowed in version part) - Version has more than 3 numeric segments
func DeepSort ¶
this is a deep sort function that sorts all maps and slices recursively it is REALLY expensive, so use it wisely! it treats any arrays as sets and sorts them by their canonical JSON representation
func EncodeCanonical ¶
EncodeCanonical JSON canonicalizes the passed object and returns it as a byte slice. It uses the OLPC canonical JSON specification (see http://wiki.laptop.org/go/Canonical_JSON). If canonicalization fails the byte slice is nil and the second return value contains the error.
func FixFixedVersion ¶
func PURLToString ¶
func PURLToString(purl packageurl.PackageURL) (string, error)
func ParseGraphNodeID ¶
ParseGraphNodeID extracts the type prefix and name from a node ID. e.g., "artifact:my-app" -> ("artifact", "my-app")
func QualifiersMapToString ¶
func SemverCompare ¶
func SemverSort ¶
func SemverSort(versions []string)
func SortStringsSlice ¶
func ToPurlWithoutVersion ¶
func ToPurlWithoutVersion(purl packageurl.PackageURL) string
func UppercaseCVEID ¶
Types ¶
type BOMMetadata ¶
type GraphComponent ¶
type GraphComponent interface {
GetID() string
GetDependentID() *string
ToCdxComponent(componentLicenseOverwrites map[string]string) (cdx.Component, error)
}
GraphComponent represents a component that can be loaded from the database.
type GraphDiff ¶
type GraphDiff struct {
AddedNodes []*GraphNode // nodes added
RemovedNodes []*GraphNode // nodes removed
AddedEdges [][2]string // edges added [parent, child] - ROOT will be replaced by nil so that it matches the db schema
RemovedEdges [][2]string // edges removed [parent, child] - ROOT will be replaced by nil so that it matches the db schema
}
GraphDiff represents differences between two graph states.
func (GraphDiff) AddedNodeIDs ¶
AddedNodeIDs returns just the IDs of added nodes.
func (GraphDiff) RemovedNodeIDs ¶
RemovedNodeIDs returns just the IDs of removed nodes.
type GraphNode ¶
type GraphNode struct {
BOMRef string // Unique identifier
Type GraphNodeType // What kind of node this is
// For components, this holds the full CycloneDX component data
Component *cdx.Component
// InfoSource-specific fields (only set for GraphNodeTypeInfoSource)
InfoType InfoSourceType
}
GraphNode represents any node in the SBOM graph. All nodes (root, artifacts, info sources, components) share this structure.
type GraphNodeType ¶
type GraphNodeType string
GraphNodeType identifies what kind of node this is in the graph.
const ( GraphNodeTypeRoot GraphNodeType = "root" GraphNodeTypeArtifact GraphNodeType = "artifact" GraphNodeTypeInfoSource GraphNodeType = "infosource" GraphNodeTypeComponent GraphNodeType = "component" )
type InfoSourceType ¶
type InfoSourceType string
InfoSourceType indicates where component information came from.
const (
InfoSourceSBOM InfoSourceType = "sbom"
)
func RemoveInformationSourcePrefixIfExists ¶
func RemoveInformationSourcePrefixIfExists(origin string) (InfoSourceType, string)
type Path ¶
type Path []string
Path represents a vulnerability path through the dependency graph. It can contain both structural nodes (root, artifact, info sources) and component nodes (PURLs).
func (Path) ToStringSlice ¶
ToStringSlice returns all nodes in the path, including fake/structural nodes.
type PurlMatchContext ¶
type PurlMatchContext struct {
SearchPurl string
NormalizedVersion string
HowToInterpretVersionString VersionInterpretationType
Qualifiers packageurl.Qualifiers
Namespace string
}
PurlMatchContext holds the parsed purl information for matching
func ParsePurlForMatching ¶
func ParsePurlForMatching(purl packageurl.PackageURL) *PurlMatchContext
ParsePurlForMatching parses a purl and version into a context for database matching
type SBOMGraph ¶
type SBOMGraph struct {
// contains filtered or unexported fields
}
SBOMGraph is a directed graph representing a software bill of materials.
Structure:
ROOT
└── artifact:my-app
└── sbom:package-lock.json
└── pkg:npm/lodash@4.17.21
└── pkg:npm/some-dep@1.0.0
All nodes live in the same graph. Scoping is done by traversing from a specific node.
func NewSBOMGraph ¶
func NewSBOMGraph() *SBOMGraph
NewSBOMGraph creates an empty graph with a root node.
func SBOMGraphFromComponents ¶
func SBOMGraphFromComponents[T GraphComponent](components []T, licenseOverwrites map[string]string) (*SBOMGraph, error)
SBOMGraphFromComponents builds an SBOMGraph from database components. The components include artifact nodes, information source nodes, and regular components. This function reconstructs the full graph structure from the flat component list. Uses generics to avoid slice type conversion and reduce memory allocations.
func SBOMGraphFromCycloneDX ¶
func SBOMGraphFromCycloneDX(bom *cdx.BOM, artifactName, infoSourceID string, keepOriginalSbomRootComponent bool) (*SBOMGraph, error)
SBOMGraphFromCycloneDX creates an SBOMGraph from a CycloneDX BOM.
func SBOMGraphFromVulnerabilities ¶
func SBOMGraphFromVulnerabilities(vulns []cdx.Vulnerability) *SBOMGraph
func (*SBOMGraph) AddArtifact ¶
AddArtifact adds an artifact node as a child of root.
func (*SBOMGraph) AddComponent ¶
AddComponent adds a component node.
func (*SBOMGraph) AddInfoSource ¶
func (g *SBOMGraph) AddInfoSource(artifactID, sourceID string, sourceType InfoSourceType) string
AddInfoSource adds an information source node as a child of an artifact. The info source ID is unique per artifact to prevent conflicts when merging graphs.
func (*SBOMGraph) AddVulnerability ¶
func (g *SBOMGraph) AddVulnerability(vuln cdx.Vulnerability)
AddVulnerability adds a vulnerability with deduplication. When the same CVE+Affects combination exists, state priority determines which one to keep: exploitable > in_triage > false_positive
func (*SBOMGraph) ChildrenOfType ¶
ChildrenOfType returns children of a specific type.
func (*SBOMGraph) ClearScope ¶
func (g *SBOMGraph) ClearScope()
func (*SBOMGraph) ComponentEdges ¶
ComponentEdges returns edges between components only.
func (*SBOMGraph) Components ¶
Components returns all component nodes reachable from scope.
func (*SBOMGraph) ComponentsWithMultipleSources ¶
ComponentsWithMultipleSources returns component IDs that appear in multiple SBOMs or have VEX/CSAF. These cannot be automatically marked as "fixed".
func (*SBOMGraph) CountInfoSourcesPerComponent ¶
func (g *SBOMGraph) CountInfoSourcesPerComponent() map[string]map[InfoSourceType]int
CountInfoSourcesPerComponent returns how many info sources each component appears under. Key insight: traverse from each info source and count how many times each component is reached.
func (*SBOMGraph) CurrentScopeID ¶
func (*SBOMGraph) DeleteArtifactFromGraph ¶
DeleteArtifactFromGraph removes an artifact and all its subtree from the graph. Returns a GraphDiff representing what was removed. DeleteArtifactFromGraph removes an artifact and all its subtree from the graph. Returns a GraphDiff representing what was removed. Only deletes nodes that are exclusively reachable through this artifact.
func (*SBOMGraph) FindAllComponentOnlyPathsToPURL ¶
func (*SBOMGraph) GetArtifactIDs ¶
GetArtifactIDs returns all artifact IDs in the graph.
func (*SBOMGraph) GetInfoSourceIDs ¶
GetInfoSourceIDs returns all info source IDs for a given artifact.
func (*SBOMGraph) GetInfoSourceNode ¶
GetInfoSourceNode returns the info source node by ID, or nil if not found.
func (*SBOMGraph) GetParentIDs ¶
GetParentIDs returns all parent node IDs for a given node.
func (*SBOMGraph) HasInfoSource ¶
HasInfoSource checks if an info source exists in the graph.
func (*SBOMGraph) InfoSources ¶
InfoSources returns all information source nodes reachable from scope.
func (*SBOMGraph) LicenseDistribution ¶
func (*SBOMGraph) MergeGraph ¶
MergeGraph merges another graph into this one, returning the diff. Artifacts from the other graph are added/merged under this graph's root. When an info source with the same ID exists, it replaces the entire subtree.
func (*SBOMGraph) MinimalTreeToPURL ¶
MinimalTreeToPURL returns a minimal tree structure containing only the subgraph of nodes that lead to the specified PURL. This collects all ancestor nodes without enumerating individual paths, avoiding combinatorial explosion. The maxDepth parameter limits how far back we traverse (0 = unlimited).
func (*SBOMGraph) NodeIDsAndEdges ¶
NodeIDsAndEdges returns all node IDs and edges reachable from the current scope.
func (*SBOMGraph) NodesOfType ¶
func (g *SBOMGraph) NodesOfType(nodeType GraphNodeType) iter.Seq[*GraphNode]
NodesOfType returns all reachable nodes of a specific type.
func (*SBOMGraph) ScopeToArtifact ¶
func (*SBOMGraph) ScopeToInfoSource ¶
func (g *SBOMGraph) ScopeToInfoSource(infoSource string, t InfoSourceType) error
func (*SBOMGraph) ToCycloneDX ¶
func (g *SBOMGraph) ToCycloneDX(metadata BOMMetadata) *cdx.BOM
ToCycloneDX exports the scoped view as a CycloneDX BOM.
func (*SBOMGraph) ToMinimalTree ¶
func (g *SBOMGraph) ToMinimalTree() minimalTree
func (*SBOMGraph) Vulnerabilities ¶
func (g *SBOMGraph) Vulnerabilities() iter.Seq[*cdx.Vulnerability]
Vulnerabilities returns all vulnerabilities. Deduplication with state priority is handled in AddVulnerability.
type VersionInterpretationType ¶
type VersionInterpretationType string
const ( ExactVersionString VersionInterpretationType = "exact" SemanticVersionString VersionInterpretationType = "semver_range" EmptyVersion VersionInterpretationType = "empty_version" EcosystemSpecificVersion VersionInterpretationType = "ecosystem_specific" )