🎯 CPE Matching Examples
Matching answers one question: does this CPE pattern cover that CPE target? cpe-skills offers three increasing levels of power — QuickMatch, MatchCPE, and AdvancedMatchCPE — plus set-oriented helpers in the matching module. This page shows each in action.
Exact Match with QuickMatch
QuickMatch takes two raw strings, parses both, and returns whether they match. It's the simplest entry point — no structs, no options.
package main
import (
"fmt"
"log"
"github.com/scagogogo/cpe-skills"
)
func main() {
a := "cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:*"
b := "cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:*"
ok, err := cpeskills.QuickMatch(a, b)
if err != nil {
log.Fatal(err)
}
fmt.Println("exact match:", ok) // true
}ANY Wildcards
In CPE matching, * (ANY) on either side matches anything. A pattern with version=* covers every version of that product:
pattern := "cpe:2.3:a:apache:log4j:*:*:*:*:*:*:*:*"
target := "cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:*"
matched, _ := cpeskills.QuickMatch(pattern, target)
fmt.Println("any-version pattern covers 2.14.0:", matched) // true
// Different products don't match even with wildcard versions
other := "cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*"
matched, _ = cpeskills.QuickMatch(pattern, other)
fmt.Println("log4j pattern covers tomcat:", matched) // falseSubset and Superset
The relation functions in the matching module classify how two CPEs relate, per NISTIR 7696:
pat, _ := cpeskills.Parse("cpe:2.3:a:microsoft:windows:*:*:*:*:*:*:*:*")
win10, _ := cpeskills.Parse("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
fmt.Println("pattern is superset of win10:", cpeskills.CPESuperset(pat, win10)) // true
fmt.Println("win10 is subset of pattern:", cpeskills.CPESubset(win10, pat)) // true
fmt.Println("equal:", cpeskills.CPEEqual(pat, pat)) // true
fmt.Println("disjoint with linux:", cpeskills.CPEDisjoint(win10,
cpeskills.MustParse("cpe:2.3:o:linux:linux_kernel:5.15:*:*:*:*:*:*:*"))) // trueYou can also use the method form: pat.IsSupersetOf(win10).
MatchCPE with Options
MatchCPE adds an options struct so you can, for example, ignore version when you only care about vendor+product. The MatchOptions type lives in the matching module.
criteria, _ := cpeskills.Parse("cpe:2.3:a:microsoft:windows:*:*:*:*:*:*:*:*")
xp, _ := cpeskills.Parse("cpe:2.3:a:microsoft:windows:xp:*:*:*:*:*:*:*")
// Strict: version must match → windows:* vs windows:xp differs
fmt.Println(cpeskills.MatchCPE(criteria, xp, &cpeskills.MatchOptions{})) // false
// Ignore version → matches
opts := &cpeskills.MatchOptions{IgnoreVersion: true}
fmt.Println(cpeskills.MatchCPE(criteria, xp, opts)) // trueBatch Matching
When you have many criteria against many targets, build a CPEIndex once and let BatchMatchCPEs reuse it (the batch module):
targets := cpeskills.StringsToCPEs([]string{
"cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:log4j:2.15.0:*:*:*:*:*:*:*",
"cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*",
})
criteria := cpeskills.StringsToCPEs([]string{
"cpe:2.3:a:apache:log4j:*:*:*:*:*:*:*:*", // all log4j
"cpe:2.3:a:apache:tomcat:*:*:*:*:*:*:*:*", // all tomcat
})
results := cpeskills.BatchMatchCPEs(criteria, targets)
for _, r := range results {
fmt.Printf("%s matched %d\n", r.Criteria.ProductName, r.Count)
}Advanced Fuzzy Matching
AdvancedMatchCPE (from the advanced-matching module) handles regex, case-insensitivity, version ranges, and a similarity score threshold:
crit, _ := cpeskills.Parse("cpe:2.3:a:apache:log4j:*:*:*:*:*:*:*:*")
opts := cpeskills.NewAdvancedMatchOptions()
opts.MatchMode = "exact"
opts.IgnoreCase = true
opts.VersionCompareMode = "range"
opts.VersionLower = "2.0.0"
opts.VersionUpper = "2.17.0"
target, _ := cpeskills.Parse("cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:*")
fmt.Println("advanced match:", cpeskills.AdvancedMatchCPE(crit, target, opts)) // trueSummary
QuickMatch— two strings in, one bool out. Best for one-off checks.MatchCPE— addMatchOptions{IgnoreVersion:true,...}for vendor/product-only logic.AdvancedMatchCPE— regex, case folding, version ranges, similarity scores.CPESubset/CPESuperset/CPEEqual/CPEDisjoint— the NISTIR 7696 relation.BatchMatchCPEs— scale to thousands of criteria/targets via an index.
See the matching, advanced-matching, and batch module pages for the full API reference.