✨ CPE Generation Examples
Sometimes you don't have a CPE string — you have a vendor, product, and version from an SBOM or package manifest, and you need to synthesize a CPE. The generator module offers five functions for this, from the strict GenerateCPE to the forgiving FuzzyGenerateCPE. This page shows when to reach for each.
GenerateCPE: Strict Four-Argument
GenerateCPE(part, vendor, product, version) builds a CPE and fills every other field with * (ANY). It does no normalization — what you pass is what you get.
package main
import (
"fmt"
"github.com/scagogogo/cpe-skills"
)
func main() {
cpe := cpeskills.GenerateCPE("a", "apache", "log4j", "2.14.0")
fmt.Println(cpe.Cpe23)
// cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:*
}GenerateFromTemplate: Override a Few Fields
When you have a base CPE and want a new one that differs in one or two attributes, pass the base as a template and a map of overrides:
base := cpeskills.MustParse("cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:*")
patched := cpeskills.GenerateFromTemplate(base, map[string]string{
cpeskills.AttrVersion: "2.17.1",
})
fmt.Println(patched.Cpe23)
// cpe:2.3:a:apache:log4j:2.17.1:*:*:*:*:*:*:*The map keys are WFN attribute constants (AttrPart, AttrVendor, AttrProduct, AttrVersion, etc.). Unset attributes are inherited from the template.
FillDefaults: Normalize Empty Fields
FillDefaults takes a partially-populated *CPE and fills every empty field with *, then regenerates the Cpe23 string. It also defaults an empty Part to a (Application).
c := &cpeskills.CPE{
Vendor: "google",
ProductName: "chrome",
Version: "120.0.6099.109",
}
filled := cpeskills.FillDefaults(c)
fmt.Println(filled.Cpe23)
// cpe:2.3:a:google:chrome:120.0.6099.109:*:*:*:*:*:*:*MergeCPEs: Combine Two Records
MergeCPEs(primary, secondary) keeps every non-empty field from primary and fills primary's gaps from secondary. Use it when two feeds disagree and you trust one more:
// Trust the SBOM for version, the advisory for everything else
sbom := cpeskills.GenerateCPE("a", "", "log4j", "2.14.0")
adv := cpeskills.MustParse("cpe:2.3:a:apache:log4j:*:*:*:*:*:*:*:*")
merged := cpeskills.MergeCPEs(adv, sbom)
fmt.Println(merged.Cpe23)
// cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:*Here primary (adv) supplies vendor and product; secondary (sbom) supplies the version that the primary left as *.
FuzzyGenerateCPE: Tolerant of Messy Input
FuzzyGenerateCPE runs NormalizeComponent on each argument — lowercasing, replacing spaces with underscores, stripping suffixes — so messy real-world strings still produce a valid CPE:
c := cpeskills.FuzzyGenerateCPE("Application", "Apache Software Foundation", "Log4j", "2.14.0")
fmt.Println(c.Cpe23)
// cpe:2.3:a:apache_software_foundation:log4j:2.14.0:*:*:*:*:*:*:*Compare with GenerateCPE, which would have left Apache Software Foundation untouched (and produced an invalid CPE with spaces).
RandomCPE: Test Fixture
RandomCPE emits a fixed dummy CPE for unit tests. It is not random in the cryptographic sense — it returns the same test vendor/product/version every call.
dummy := cpeskills.RandomCPE()
fmt.Println(dummy.Cpe23)
// cpe:2.3:a:test_vendor:test_product:1.0:*:*:*:*:*:*:*Summary
GenerateCPE— strict, four arguments, no normalization; use when input is already clean.FuzzyGenerateCPE— same shape, but normalizes each field; use for SBOM/manifest input.GenerateFromTemplate— clone a base CPE and override a few WFN attributes.FillDefaults— backfill*into a partial CPE and regenerateCpe23.MergeCPEs— combine two records, preferringprimary's non-empty fields.RandomCPE— a deterministic dummy for tests, not real randomness.
See the generator module page for the full API reference.