Validation
The CPE library provides comprehensive validation functions to ensure CPE data integrity and compliance with CPE specifications.
Component Validation
ValidateComponent
func ValidateComponent(component string) error
Validates a single CPE component (vendor, product, version, etc.) for compliance with CPE naming rules.
Parameters:
component
- Component string to validate
Returns:
error
- Error if validation fails,nil
if valid
Validation Rules:
- Must not contain illegal characters (control characters, etc.)
- Special values
*
(ANY) and-
(NA) are allowed - Empty strings are allowed
- Must follow CPE character encoding rules
Example:
// Valid components
err := cpe.ValidateComponent("microsoft")
if err != nil {
fmt.Printf("Invalid: %v\n", err)
} else {
fmt.Println("Valid component")
}
// Test special values
err = cpe.ValidateComponent("*") // ANY value
if err == nil {
fmt.Println("Wildcard is valid")
}
err = cpe.ValidateComponent("-") // NA value
if err == nil {
fmt.Println("NA value is valid")
}
// Invalid component with control characters
err = cpe.ValidateComponent("invalid\x00component")
if err != nil {
fmt.Printf("Invalid component: %v\n", err)
}
ValidateVendor
func ValidateVendor(vendor string) error
Validates a vendor name specifically.
Parameters:
vendor
- Vendor name to validate
Returns:
error
- Error if validation fails
ValidateProduct
func ValidateProduct(product string) error
Validates a product name specifically.
Parameters:
product
- Product name to validate
Returns:
error
- Error if validation fails
ValidateVersion
func ValidateVersion(version string) error
Validates a version string with additional version-specific rules.
Parameters:
version
- Version string to validate
Returns:
error
- Error if validation fails
Example:
// Validate different components
components := map[string]string{
"vendor": "microsoft",
"product": "windows",
"version": "10.0.19041",
}
for name, value := range components {
var err error
switch name {
case "vendor":
err = cpe.ValidateVendor(value)
case "product":
err = cpe.ValidateProduct(value)
case "version":
err = cpe.ValidateVersion(value)
}
if err != nil {
fmt.Printf("Invalid %s '%s': %v\n", name, value, err)
} else {
fmt.Printf("Valid %s: %s\n", name, value)
}
}
CPE Validation
ValidateCPE
func ValidateCPE(cpe *CPE) error
Validates a complete CPE object for correctness and compliance.
Parameters:
cpe
- CPE object to validate
Returns:
error
- Error if validation fails
Validation Checks:
- All components are valid
- Part is one of the allowed values
- CPE 2.3 string format is correct (if present)
- Required fields are not empty
- Field relationships are consistent
Example:
// Create and validate a CPE
cpeObj := &cpe.CPE{
Part: *cpe.PartApplication,
Vendor: cpe.Vendor("microsoft"),
ProductName: cpe.Product("windows"),
Version: cpe.Version("10"),
}
err := cpe.ValidateCPE(cpeObj)
if err != nil {
fmt.Printf("CPE validation failed: %v\n", err)
} else {
fmt.Println("CPE is valid")
}
// Test invalid CPE
invalidCPE := &cpe.CPE{
Part: cpe.Part{ShortName: "x"}, // Invalid part
Vendor: cpe.Vendor("microsoft"),
ProductName: cpe.Product("windows"),
}
err = cpe.ValidateCPE(invalidCPE)
if err != nil {
fmt.Printf("Expected validation error: %v\n", err)
}
ValidateCPEString
func ValidateCPEString(cpeString string) error
Validates a CPE string without parsing it into a structure.
Parameters:
cpeString
- CPE string to validate
Returns:
error
- Error if validation fails
Example:
// Valid CPE strings
validCPEs := []string{
"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*",
"cpe:/a:apache:tomcat:8.5.0",
"cpe:2.3:o:linux:kernel:5.4.0:*:*:*:*:*:*:*",
}
for _, cpeStr := range validCPEs {
err := cpe.ValidateCPEString(cpeStr)
if err != nil {
fmt.Printf("Invalid CPE '%s': %v\n", cpeStr, err)
} else {
fmt.Printf("Valid CPE: %s\n", cpeStr)
}
}
// Invalid CPE string
err := cpe.ValidateCPEString("invalid:format")
if err != nil {
fmt.Printf("Expected error for invalid format: %v\n", err)
}
Format Validation
ValidateCPE23Format
func ValidateCPE23Format(cpe23 string) error
Validates CPE 2.3 format specifically.
Parameters:
cpe23
- CPE 2.3 string to validate
Returns:
error
- Error if format is invalid
Validation Rules:
- Must start with "cpe:2.3:"
- Must have exactly 13 colon-separated parts
- Part field must be "a", "h", "o", or "*"
- All components must be properly escaped
Example:
// Test CPE 2.3 format validation
cpe23Examples := []string{
"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*", // Valid
"cpe:2.3:a:microsoft:windows:10", // Invalid - too few parts
"cpe:2.2:a:microsoft:windows:10:*:*:*:*:*:*:*", // Invalid - wrong version
}
for _, example := range cpe23Examples {
err := cpe.ValidateCPE23Format(example)
if err != nil {
fmt.Printf("Invalid CPE 2.3 format '%s': %v\n", example, err)
} else {
fmt.Printf("Valid CPE 2.3 format: %s\n", example)
}
}
ValidateCPE22Format
func ValidateCPE22Format(cpe22 string) error
Validates CPE 2.2 format specifically.
Parameters:
cpe22
- CPE 2.2 string to validate
Returns:
error
- Error if format is invalid
Validation Rules:
- Must start with "cpe:/"
- Part field must be "a", "h", or "o"
- Components must be properly escaped
- Extended format with tildes is supported
Example:
// Test CPE 2.2 format validation
cpe22Examples := []string{
"cpe:/a:apache:tomcat:8.5.0", // Valid
"cpe:/a:apache:tomcat:8.5.0:beta", // Valid with update
"invalid:/a:apache:tomcat:8.5.0", // Invalid prefix
}
for _, example := range cpe22Examples {
err := cpe.ValidateCPE22Format(example)
if err != nil {
fmt.Printf("Invalid CPE 2.2 format '%s': %v\n", example, err)
} else {
fmt.Printf("Valid CPE 2.2 format: %s\n", example)
}
}
Normalization
NormalizeComponent
func NormalizeComponent(component string) string
Normalizes a CPE component according to CPE specification rules.
Parameters:
component
- Component to normalize
Returns:
string
- Normalized component
Normalization Rules:
- Convert to lowercase
- Replace spaces with underscores
- Preserve special values (
*
and-
) - Remove leading/trailing whitespace
Example:
// Test component normalization
components := []string{
"Microsoft", // -> "microsoft"
"Windows 10", // -> "windows_10"
" Apache ", // -> "apache"
"*", // -> "*" (unchanged)
"-", // -> "-" (unchanged)
}
for _, comp := range components {
normalized := cpe.NormalizeComponent(comp)
fmt.Printf("'%s' -> '%s'\n", comp, normalized)
}
NormalizeCPE
func NormalizeCPE(cpe *CPE) *CPE
Normalizes all components of a CPE object.
Parameters:
cpe
- CPE to normalize
Returns:
*CPE
- New CPE with normalized components
Example:
// Create CPE with non-normalized components
originalCPE := &cpe.CPE{
Part: *cpe.PartApplication,
Vendor: cpe.Vendor("Microsoft"),
ProductName: cpe.Product("Windows 10"),
Version: cpe.Version("Build 19041"),
}
// Normalize the CPE
normalizedCPE := cpe.NormalizeCPE(originalCPE)
fmt.Printf("Original vendor: %s\n", originalCPE.Vendor)
fmt.Printf("Normalized vendor: %s\n", normalizedCPE.Vendor)
fmt.Printf("Original product: %s\n", originalCPE.ProductName)
fmt.Printf("Normalized product: %s\n", normalizedCPE.ProductName)
Validation Options
ValidationOptions
type ValidationOptions struct {
StrictMode bool // Enable strict validation rules
AllowEmpty bool // Allow empty components
NormalizeFirst bool // Normalize before validation
CheckReferences bool // Validate reference URLs
}
ValidateCPEWithOptions
func ValidateCPEWithOptions(cpe *CPE, options *ValidationOptions) error
Validates a CPE with custom validation options.
Parameters:
cpe
- CPE to validateoptions
- Validation options
Returns:
error
- Error if validation fails
Example:
// Create validation options
options := &cpe.ValidationOptions{
StrictMode: true,
AllowEmpty: false,
NormalizeFirst: true,
}
cpeObj, _ := cpe.ParseCpe23("cpe:2.3:a:Microsoft:Windows:10:*:*:*:*:*:*:*")
err := cpe.ValidateCPEWithOptions(cpeObj, options)
if err != nil {
fmt.Printf("Validation with options failed: %v\n", err)
} else {
fmt.Println("CPE passed strict validation")
}
Batch Validation
ValidateCPEList
func ValidateCPEList(cpes []*CPE) []error
Validates a list of CPE objects and returns any validation errors.
Parameters:
cpes
- Array of CPEs to validate
Returns:
[]error
- Array of validation errors (nil entries for valid CPEs)
Example:
// Create list of CPEs to validate
cpeList := []*CPE{
{Part: *cpe.PartApplication, Vendor: "microsoft", ProductName: "windows"},
{Part: cpe.Part{ShortName: "x"}, Vendor: "invalid"}, // Invalid part
{Part: *cpe.PartApplication, Vendor: "apache", ProductName: "tomcat"},
}
errors := cpe.ValidateCPEList(cpeList)
for i, err := range errors {
if err != nil {
fmt.Printf("CPE %d validation failed: %v\n", i, err)
} else {
fmt.Printf("CPE %d is valid\n", i)
}
}
Complete Example
package main
import (
"fmt"
"log"
"github.com/scagogogo/cpe"
)
func main() {
// Component validation
fmt.Println("=== Component Validation ===")
components := []string{
"microsoft", // Valid
"windows_10", // Valid
"*", // Valid (wildcard)
"-", // Valid (NA)
"invalid\x00", // Invalid (control character)
}
for _, comp := range components {
err := cpe.ValidateComponent(comp)
if err != nil {
fmt.Printf("Invalid component '%s': %v\n", comp, err)
} else {
fmt.Printf("Valid component: %s\n", comp)
}
}
// CPE string validation
fmt.Println("\n=== CPE String Validation ===")
cpeStrings := []string{
"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*",
"cpe:/a:apache:tomcat:8.5.0",
"invalid:format",
}
for _, cpeStr := range cpeStrings {
err := cpe.ValidateCPEString(cpeStr)
if err != nil {
fmt.Printf("Invalid CPE string '%s': %v\n", cpeStr, err)
} else {
fmt.Printf("Valid CPE string: %s\n", cpeStr)
}
}
// CPE object validation
fmt.Println("\n=== CPE Object Validation ===")
validCPE := &cpe.CPE{
Part: *cpe.PartApplication,
Vendor: cpe.Vendor("microsoft"),
ProductName: cpe.Product("windows"),
Version: cpe.Version("10"),
}
err := cpe.ValidateCPE(validCPE)
if err != nil {
fmt.Printf("CPE validation failed: %v\n", err)
} else {
fmt.Println("CPE object is valid")
}
// Component normalization
fmt.Println("\n=== Component Normalization ===")
unnormalizedComponents := []string{
"Microsoft",
"Windows 10",
" Apache ",
"Product Name",
}
for _, comp := range unnormalizedComponents {
normalized := cpe.NormalizeComponent(comp)
fmt.Printf("'%s' -> '%s'\n", comp, normalized)
}
// CPE normalization
fmt.Println("\n=== CPE Normalization ===")
unnormalizedCPE := &cpe.CPE{
Part: *cpe.PartApplication,
Vendor: cpe.Vendor("Microsoft"),
ProductName: cpe.Product("Windows 10"),
Version: cpe.Version("Build 19041"),
}
normalizedCPE := cpe.NormalizeCPE(unnormalizedCPE)
fmt.Printf("Original: %s %s %s\n",
unnormalizedCPE.Vendor, unnormalizedCPE.ProductName, unnormalizedCPE.Version)
fmt.Printf("Normalized: %s %s %s\n",
normalizedCPE.Vendor, normalizedCPE.ProductName, normalizedCPE.Version)
// Validation with options
fmt.Println("\n=== Validation with Options ===")
options := &cpe.ValidationOptions{
StrictMode: true,
AllowEmpty: false,
NormalizeFirst: true,
}
err = cpe.ValidateCPEWithOptions(unnormalizedCPE, options)
if err != nil {
fmt.Printf("Strict validation failed: %v\n", err)
} else {
fmt.Println("CPE passed strict validation")
}
}