Matching
The CPE library provides sophisticated matching capabilities for comparing CPE objects, including basic matching, advanced matching with various algorithms, and version comparison.
The flowchart below shows the advanced matching flow: two CPEs are compared under one of four modes, and the selected mode determines whether a boolean verdict or a similarity score is returned.
Basic Matching
CPE.Match
func (c *CPE) Match(other *CPE) boolPerforms basic CPE matching according to the CPE Name Matching specification.
Parameters:
other- The CPE to match against
Returns:
bool-trueif the CPEs match,falseotherwise
Matching Rules:
- If CPE URIs are identical, return
true - Part must match exactly
- For other attributes:
- If either value is wildcard (
*), they match - If both values are "not applicable" (
-), they match - Otherwise, values must be exactly equal
- If either value is wildcard (
Example:
// Create CPEs
windows10, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
windowsPattern, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:*:*:*:*:*:*:*:*")
// Test matching
if windowsPattern.Match(windows10) {
fmt.Println("Windows 10 matches the Windows pattern")
}
// Test non-matching
office, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:office:2019:*:*:*:*:*:*:*")
if !windowsPattern.Match(office) {
fmt.Println("Office does not match the Windows pattern")
}MatchCPE
func MatchCPE(criteria *CPE, target *CPE, options *MatchOptions) boolPerforms CPE matching with configurable options.
Parameters:
criteria- CPE pattern to match againsttarget- CPE to test for matchingoptions- Matching options (can benilfor defaults)
Returns:
bool-trueif the CPEs match according to the options
MatchOptions
type MatchOptions struct {
IgnoreVersion bool // Ignore version field in matching
AllowSubVersions bool // Allow sub-version matching (e.g., "1.0" matches "1.0.1")
UseRegex bool // Use regular expressions for string fields
VersionRange bool // Match against a version range instead of exact value
MinVersion string // Lower bound of the version range (inclusive)
MaxVersion string // Upper bound of the version range (inclusive)
}Example:
// Create match options
options := &cpeskills.MatchOptions{
IgnoreVersion: true,
}
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:11:*:*:*:*:*:*:*")
// Match ignoring version
if cpeskills.MatchCPE(cpe1, cpe2, options) {
fmt.Println("CPEs match when ignoring version")
}DefaultMatchOptions
func DefaultMatchOptions() *MatchOptionsReturns default matching options (IgnoreVersion: false, AllowSubVersions: true, UseRegex: false, VersionRange: false).
Returns:
*MatchOptions- Default matching options
Advanced Matching
AdvancedMatchCPE
func AdvancedMatchCPE(criteria *CPE, target *CPE, options *AdvancedMatchOptions) boolPerforms advanced CPE matching with sophisticated algorithms.
Parameters:
criteria- CPE pattern to match againsttarget- CPE to test for matchingoptions- Advanced matching options
Returns:
bool-trueif the target matches the criteria
AdvancedMatchOptions
type AdvancedMatchOptions struct {
UseRegex bool // Enable regex matching
IgnoreCase bool // Case-insensitive matching
UseFuzzyMatch bool // Enable fuzzy matching
MatchCommonOnly bool // Match only common fields
PartialMatch bool // Enable partial matching
MatchMode string // Matching mode
VersionCompareMode string // Version comparison mode
VersionLower string // Version lower bound
VersionUpper string // Version upper bound
FieldOptions map[string]FieldMatchOption // Field-specific options
ScoreThreshold float64 // Minimum match score (0.0-1.0)
}FieldMatchOption
type FieldMatchOption struct {
Weight float64 // Field weight (0.0-1.0)
Required bool // Whether field must match
MatchMethod string // Matching method for this field
}NewAdvancedMatchOptions
func NewAdvancedMatchOptions() *AdvancedMatchOptionsCreates default advanced matching options.
Returns:
*AdvancedMatchOptions- Default advanced options
Example:
// Create advanced matching options
options := cpeskills.NewAdvancedMatchOptions()
options.MatchMode = "distance"
options.ScoreThreshold = 0.8
options.IgnoreCase = true
// Set field-specific options
options.FieldOptions = map[string]cpeskills.FieldMatchOption{
"vendor": {
Weight: 1.0,
Required: true,
},
"product": {
Weight: 1.0,
Required: true,
},
"version": {
Weight: 0.7,
Required: false,
},
}
criteria, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:*:*:*:*:*:*:*:*:*")
target, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
if cpeskills.AdvancedMatchCPE(criteria, target, options) {
fmt.Println("Advanced match successful")
}Match Modes
Exact Mode
Performs exact field matching with special value handling.
options := cpeskills.NewAdvancedMatchOptions()
options.MatchMode = "exact"Subset Mode
Checks if the target is a subset of the criteria.
options := cpeskills.NewAdvancedMatchOptions()
options.MatchMode = "subset"Superset Mode
Checks if the target is a superset of the criteria.
options := cpeskills.NewAdvancedMatchOptions()
options.MatchMode = "superset"Distance Mode
Uses similarity scoring to determine matches.
options := cpeskills.NewAdvancedMatchOptions()
options.MatchMode = "distance"
options.ScoreThreshold = 0.7 // Require 70% similarityVersion Comparison
CompareVersions
func CompareVersions(v1, v2 string) intCompares two version strings.
Parameters:
v1- First version stringv2- Second version string
Returns:
int--1if v1 < v2,0if v1 == v2,1if v1 > v2
Example:
result := cpeskills.CompareVersions("1.0.0", "1.0.1")
fmt.Printf("Comparison result: %d\n", result) // -1
result = cpeskills.CompareVersions("2.0", "1.9.9")
fmt.Printf("Comparison result: %d\n", result) // 1
result = cpeskills.CompareVersions("1.0", "1.0.0")
fmt.Printf("Comparison result: %d\n", result) // 0Version Range Matching
Advanced matching supports version range comparisons:
options := cpeskills.NewAdvancedMatchOptions()
options.VersionCompareMode = "range"
options.VersionLower = "1.0"
options.VersionUpper = "2.0"
// This will match versions between 1.0 and 2.0
criteria, _ := cpeskills.ParseCpe23("cpe:2.3:a:vendor:product:*:*:*:*:*:*:*:*")
target, _ := cpeskills.ParseCpe23("cpe:2.3:a:vendor:product:1.5:*:*:*:*:*:*:*")
if cpeskills.AdvancedMatchCPE(criteria, target, options) {
fmt.Println("Version is within range")
}Regex Matching
Enable regular expression matching for flexible pattern matching:
options := cpeskills.NewAdvancedMatchOptions()
options.UseRegex = true
// Use regex patterns in CPE fields
criteria, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:.*office.*:*:*:*:*:*:*:*:*")
target, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:ms_office:2019:*:*:*:*:*:*:*")
if cpeskills.AdvancedMatchCPE(criteria, target, options) {
fmt.Println("Regex match successful")
}Fuzzy Matching
Enable fuzzy matching for approximate string matching:
options := cpeskills.NewAdvancedMatchOptions()
options.UseFuzzyMatch = true
options.ScoreThreshold = 0.8
// This might match even with slight spelling differences
criteria, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:*:*:*:*:*:*:*:*")
target, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomkat:8.5:*:*:*:*:*:*:*") // Note: "tomkat" vs "tomcat"
if cpeskills.AdvancedMatchCPE(criteria, target, options) {
fmt.Println("Fuzzy match successful")
}Complete Example
package main
import (
"fmt"
"github.com/scagogogo/cpe-skills"
)
func main() {
// Parse CPEs
pattern, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:*:*:*:*:*:*:*:*:*")
windows10, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
office2019, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:office:2019:*:*:*:*:*:*:*")
// Basic matching
fmt.Println("=== Basic Matching ===")
fmt.Printf("Pattern matches Windows 10: %t\n", pattern.Match(windows10))
fmt.Printf("Pattern matches Office 2019: %t\n", pattern.Match(office2019))
// Advanced matching with distance mode
fmt.Println("\n=== Advanced Matching ===")
options := cpeskills.NewAdvancedMatchOptions()
options.MatchMode = "distance"
options.ScoreThreshold = 0.7
fmt.Printf("Advanced match Windows 10: %t\n",
cpeskills.AdvancedMatchCPE(pattern, windows10, options))
fmt.Printf("Advanced match Office 2019: %t\n",
cpeskills.AdvancedMatchCPE(pattern, office2019, options))
// Version comparison
fmt.Println("\n=== Version Comparison ===")
fmt.Printf("1.0 vs 1.1: %d\n", cpeskills.CompareVersions("1.0", "1.1"))
fmt.Printf("2.0 vs 1.9: %d\n", cpeskills.CompareVersions("2.0", "1.9"))
fmt.Printf("1.0 vs 1.0: %d\n", cpeskills.CompareVersions("1.0", "1.0"))
// Regex matching
fmt.Println("\n=== Regex Matching ===")
regexOptions := cpeskills.NewAdvancedMatchOptions()
regexOptions.UseRegex = true
regexPattern, _ := cpeskills.ParseCpe23("cpe:2.3:a:.*soft.*:.*:*:*:*:*:*:*:*:*")
fmt.Printf("Regex pattern matches Windows: %t\n",
cpeskills.AdvancedMatchCPE(regexPattern, windows10, regexOptions))
}