Skip to content

CVE Validation Processing

This example demonstrates how to use CVE Utils to implement a robust CVE validation and processing system, including user input validation, batch data processing, error handling, and performance optimization best practices.

Scenario Description

As a web application or API developer, you need to:

  • Validate user-input CVE formats
  • Handle various exceptions and errors
  • Implement high-performance batch validation
  • Provide friendly error messages and suggestions
  • Ensure system stability and reliability

Complete Example

1. CVE Validator

go
package main

import (
    "fmt"
    "strings"
    "time"
    "github.com/scagogogo/cve"
)

// ValidationResult validation result
type ValidationResult struct {
    IsValid     bool      `json:"is_valid"`
    CVE         string    `json:"cve,omitempty"`
    ErrorType   string    `json:"error_type,omitempty"`
    ErrorMsg    string    `json:"error_message,omitempty"`
    Suggestions []string  `json:"suggestions,omitempty"`
    ProcessTime time.Duration `json:"process_time_ns"`
}

// CVEValidator CVE validator
type CVEValidator struct {
    strictMode        bool
    maxYearOffset     int
    enableSuggestions bool
}

func NewCVEValidator() *CVEValidator {
    return &CVEValidator{
        strictMode:        false,
        maxYearOffset:     10,
        enableSuggestions: true,
    }
}

// SetStrictMode enable/disable strict validation mode
func (v *CVEValidator) SetStrictMode(enabled bool) *CVEValidator {
    v.strictMode = enabled
    return v
}

// SetMaxYearOffset set maximum year offset for validation
func (v *CVEValidator) SetMaxYearOffset(years int) *CVEValidator {
    v.maxYearOffset = years
    return v
}

// SetSuggestions enable/disable error suggestions
func (v *CVEValidator) SetSuggestions(enabled bool) *CVEValidator {
    v.enableSuggestions = enabled
    return v
}

// ValidateInput validate single CVE input
func (v *CVEValidator) ValidateInput(input string) ValidationResult {
    start := time.Now()
    result := ValidationResult{
        ProcessTime: 0,
    }

    defer func() {
        result.ProcessTime = time.Since(start)
    }()

    // Remove leading/trailing spaces
    trimmed := strings.TrimSpace(input)
    if trimmed == "" {
        result.ErrorType = "empty_input"
        result.ErrorMsg = "Input cannot be empty"
        if v.enableSuggestions {
            result.Suggestions = []string{
                "Please provide a CVE identifier",
                "Example: CVE-2022-12345",
            }
        }
        return result
    }

    // Format CVE
    formatted := cve.Format(trimmed)

    // Basic format validation
    if !cve.IsCve(formatted) {
        result.ErrorType = "invalid_format"
        result.ErrorMsg = fmt.Sprintf("Invalid CVE format: %s", input)
        if v.enableSuggestions {
            result.Suggestions = v.generateFormatSuggestions(input)
        }
        return result
    }

    // Comprehensive validation in strict mode
    if v.strictMode {
        if !cve.ValidateCve(formatted) {
            result.ErrorType = "validation_failed"
            result.ErrorMsg = fmt.Sprintf("CVE validation failed: %s", formatted)
            if v.enableSuggestions {
                result.Suggestions = v.generateValidationSuggestions(formatted)
            }
            return result
        }

        // Year range validation
        year := cve.ExtractCveYearAsInt(formatted)
        currentYear := time.Now().Year()
        if year > currentYear+v.maxYearOffset {
            result.ErrorType = "future_year"
            result.ErrorMsg = fmt.Sprintf("CVE year %d is too far in the future", year)
            return result
        }
    }

    // Validation successful
    result.IsValid = true
    result.CVE = formatted
    return result
}

// generateFormatSuggestions generate format correction suggestions
func (v *CVEValidator) generateFormatSuggestions(input string) []string {
    if !v.enableSuggestions {
        return nil
    }

    var suggestions []string

    // Check if CVE prefix is missing
    if strings.Contains(input, "-") && !strings.HasPrefix(strings.ToUpper(input), "CVE-") {
        suggestions = append(suggestions, "Try adding 'CVE-' prefix: CVE-"+input)
    }

    // Check for common format errors
    if strings.Contains(input, "/") {
        fixed := strings.ReplaceAll(input, "/", "-")
        suggestions = append(suggestions, "Try replacing '/' with '-': "+fixed)
    }

    // Check for spaces
    if strings.Contains(input, " ") {
        fixed := strings.ReplaceAll(input, " ", "-")
        suggestions = append(suggestions, "Try replacing spaces with '-': "+fixed)
    }

    // Provide standard format example
    suggestions = append(suggestions, "Standard format example: CVE-2022-12345")

    return suggestions
}

// generateValidationSuggestions generate validation suggestions
func (v *CVEValidator) generateValidationSuggestions(cveId string) []string {
    if !v.enableSuggestions {
        return nil
    }

    var suggestions []string

    year := cve.ExtractCveYearAsInt(cveId)
    seq := cve.ExtractCveSeqAsInt(cveId)

    currentYear := time.Now().Year()

    if year < 1970 {
        suggestions = append(suggestions, "Year cannot be earlier than 1970")
    }

    if year > currentYear {
        suggestions = append(suggestions, fmt.Sprintf("Year cannot be later than current year %d", currentYear))
    }

    if seq <= 0 {
        suggestions = append(suggestions, "Sequence number must be a positive integer")
    }

    return suggestions
}

Released under the MIT License.