cpe

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2026 License: MIT Imports: 17 Imported by: 0

README

cpe-skills - CPE SDK for Go

📚 Documentation

Complete API documentation and examples: https://scagogogo.github.io/cpe/

📖 Introduction

The CPE (Common Platform Enumeration) library is a comprehensive Go implementation for processing, parsing, matching, and storing CPE (Common Platform Enumeration) data. CPE is a structured naming scheme for identifying classes of IT systems, software, and packages.

The library also includes integration with CVE (Common Vulnerabilities and Exposures), enabling developers to associate software components with known security vulnerabilities.

✨ Features
  • CPE Format Support: Parse and generate CPE 2.2 and 2.3 formats
  • Advanced Matching: CPE name matching with wildcards and special values
  • WFN Support: Well-Formed Name format with bidirectional conversion
  • Applicability Language: CPE Applicability Language support
  • Version Comparison: Semantic version comparison and range matching
  • Dictionary Management: CPE dictionary with XML import/export
  • CVE Integration: Associate CPEs with Common Vulnerabilities and Exposures
  • Advanced Algorithms: Fuzzy matching, subset/superset matching
  • Set Operations: Union, intersection, difference operations on CPE collections
  • NVD Integration: Built-in National Vulnerability Database feed integration
  • Error Handling: Structured error handling with detailed error types
  • Storage Backends: Multiple storage backends with persistence support
  • Caching: Integrated caching mechanism for optimized performance
🚀 Installation
As a Go Library
go get github.com/scagogogo/cpe-skills
As a CLI Tool
# Install via Go
go install github.com/scagogogo/cpe-skills/cmd/cpe@latest

# Or download from GitHub Releases
# See https://github.com/scagogogo/cpe-skills/releases for all platforms

See SKILLS.md for detailed installation instructions for all supported platforms.

🔍 Quick Start
package main

import (
    "fmt"
    "log"
    "github.com/scagogogo/cpe-skills"
)

func main() {
    // Parse CPE 2.3 string
    cpeObj, err := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Vendor: %s, Product: %s, Version: %s\n", 
        cpeObj.Vendor, cpeObj.ProductName, cpeObj.Version)
    
    // Create matching pattern
    pattern, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:*:*:*:*:*:*:*:*:*")
    
    // Test matching
    if pattern.Match(cpeObj) {
        fmt.Println("CPE matches the pattern!")
    }
}
🏗️ Architecture

The library follows a modular design with the following core components:

  1. CPE Parser Engine: Handles parsing and formatting of CPE strings
  2. Matching Engine: Implements various CPE matching strategies
  3. Storage System: Provides multiple storage backend options
  4. CVE Integration: Connects CPE data with vulnerability information
  5. NVD Adapter: Integrates with National Vulnerability Database
📝 Local Documentation Development

To run and develop documentation locally:

# Navigate to docs directory
cd docs

# Install dependencies
npm install

# Start development server
npm run docs:dev

# Build documentation
npm run docs:build

# Preview built documentation
npm run docs:preview

Documentation will be available at http://localhost:5173 (dev mode) or http://localhost:4173 (preview mode).

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	// NVDCPEMatch NVD CPE匹配数据Feed URL
	// 包含CPE和CVE之间的映射关系
	NVDCPEMatch = "https://nvd.nist.gov/feeds/json/cpematch/1.0/nvdcpematch-1.0.json.gz"

	// NVDCPEFeedURL NVD CPE数据Feed URL
	// 包含所有CPE条目的详细信息
	NVDCPEFeedURL = "https://nvd.nist.gov/feeds/json/cpe/1.0/nvdcpe-1.0.json.gz"

	// NVDCPEDict NVD CPE字典XML URL
	// 包含官方CPE字典的XML格式数据
	NVDCPEDict = "https://nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz"

	// NVDCVERecentURL NVD最近CVE数据Feed URL
	// 包含最近添加或更新的CVE条目
	NVDCVERecentURL = "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-recent.json.gz"
)

默认NVD CPE Feed URL

View Source
const (
	ValueANY = "*" // 逻辑值 ANY
	ValueNA  = "-" // 逻辑值 NA
)

WFN 逻辑值常量

View Source
const (
	AttrPart            = "part"
	AttrVendor          = "vendor"
	AttrProduct         = "product"
	AttrVersion         = "version"
	AttrUpdate          = "update"
	AttrEdition         = "edition"
	AttrLanguage        = "language"
	AttrSoftwareEdition = "sw_edition"
	AttrTargetSoftware  = "target_sw"
	AttrTargetHardware  = "target_hw"
	AttrOther           = "other"
)

WFN 属性名常量

View Source
const (
	PartApplicationShort = "a"
	PartOSShort          = "o"
	PartHardwareShort    = "h"
)

Part 属性的有效短名称值

View Source
const CPE22Header = "cpe"
View Source
const CPE23Header = "cpe"
View Source
const CPE23Version = "2.3"

Variables

View Source
var (

	/**
	 * PartApplication 表示应用程序类型
	 *
	 * 用于标识软件应用程序,如办公软件、浏览器、数据库等。
	 * 在CPE URI中使用字符'a'表示。
	 *
	 * 示例:
	 *   “`go
	 *   // 表示Chrome浏览器的CPE
	 *   chromeCPE := &cpe.CPE{
	 *       Part:        *cpe.PartApplication,
	 *       Vendor:      cpe.Vendor("google"),
	 *       ProductName: cpe.Product("chrome"),
	 *   }
	 *   “`
	 */
	PartApplication = &Part{
		ShortName:   "a",
		LongName:    "Application",
		Description: "表示软件应用程序,包括但不限于桌面应用、服务器应用、移动应用等",
	}

	/**
	 * PartHardware 表示硬件设备类型
	 *
	 * 用于标识物理硬件设备,如路由器、打印机、服务器硬件等。
	 * 在CPE URI中使用字符'h'表示。
	 *
	 * 示例:
	 *   “`go
	 *   // 表示Cisco路由器的CPE
	 *   routerCPE := &cpe.CPE{
	 *       Part:        *cpe.PartHardware,
	 *       Vendor:      cpe.Vendor("cisco"),
	 *       ProductName: cpe.Product("rv340"),
	 *   }
	 *   “`
	 */
	PartHardware = &Part{
		ShortName:   "h",
		LongName:    "Hardware",
		Description: "表示物理硬件设备,包括但不限于网络设备、服务器、存储设备等",
	}

	/**
	 * PartOperationSystem 表示操作系统类型
	 *
	 * 用于标识操作系统,如Windows、Linux、macOS等。
	 * 在CPE URI中使用字符'o'表示。
	 *
	 * 示例:
	 *   “`go
	 *   // 表示Ubuntu Linux的CPE
	 *   ubuntuCPE := &cpe.CPE{
	 *       Part:        *cpe.PartOperationSystem,
	 *       Vendor:      cpe.Vendor("canonical"),
	 *       ProductName: cpe.Product("ubuntu_linux"),
	 *       Version:     cpe.Version("20.04"),
	 *   }
	 *   “`
	 */
	PartOperationSystem = &Part{
		ShortName:   "o",
		LongName:    "Operation System",
		Description: "表示操作系统,用于管理计算机硬件与软件资源的系统软件",
	}
)
View Source
var (
	// ErrNotFound 表示请求的记录在存储中不存在
	ErrNotFound = errors.New("record not found")

	// ErrDuplicate 表示尝试存储的记录已经存在(通常在主键冲突时)
	ErrDuplicate = errors.New("duplicate record")

	// ErrInvalidData 表示提供的数据无效或不符合存储要求
	ErrInvalidData = errors.New("invalid data")

	// ErrStorageDisconnected 表示存储后端未连接或连接已断开
	ErrStorageDisconnected = errors.New("storage is disconnected")
)

*

  • 存储接口定义的错误常量
  • 这些错误常量用于存储操作中可能遇到的常见错误情况,
  • 标准化了错误处理,便于使用者统一处理不同存储实现中的错误。

ValidPartValues 是 Part 属性允许的值集合

Functions

func AdvancedMatchCPE

func AdvancedMatchCPE(criteria *CPE, target *CPE, options *AdvancedMatchOptions) bool

AdvancedMatchCPE 执行高级CPE匹配

func BindToFS

func BindToFS(w *WFN) string

BindToFS 将WFN绑定为CPE 2.3 FS(Formatted String)格式 按照 NISTIR 7695 规范实现

func BindToURI

func BindToURI(w *WFN) string

BindToURI 将WFN绑定为CPE 2.2 URI格式 按照 NISTIR 7695 规范实现

func CPEDisjoint

func CPEDisjoint(a, b *CPE) bool

CPEDisjoint 判断两个CPE是否不相交

func CPEEqual

func CPEEqual(a, b *CPE) bool

CPEEqual 判断两个CPE是否相等

func CPESubset

func CPESubset(a, b *CPE) bool

CPESubset 判断CPE a是否是CPE b的子集

func CPESuperset

func CPESuperset(a, b *CPE) bool

CPESuperset 判断CPE a是否是CPE b的超集

func CPEsToStrings

func CPEsToStrings(cpes []*CPE) []string

CPEsToStrings 将CPE切片转换为字符串切片

示例:

strs := cpe.CPEsToStrings(cpes)

func ClearDataSources

func ClearDataSources()

*

  • ClearDataSources 清除所有注册的数据源 *
  • 此函数用于清除系统中所有已注册的CPE数据源,通常用于重置系统状态、
  • 释放资源或准备重新配置数据源时使用。 *
  • 参数:
  • - 无参数 *
  • 返回:
  • - 无返回值 *
  • 使用示例:
  • ```go
  • // 清除所有已注册的数据源
  • cpe.ClearDataSources() *
  • // 重新注册自定义数据源
  • cpe.RegisterDataSource(myNewDataSource)
  • ``` *
  • 注意事项:
  • - 此操作会清除所有数据源,包括默认数据源和自定义数据源
  • - 清除后需要重新注册数据源才能使用查询功能
  • - 在需要切换环境或重置系统时使用此函数

func CompareAttributes

func CompareAttributes(source, target string) int

CompareAttributes 比较两个WFN属性值之间的关系 按照 NISTIR 7696 规范中的属性比较规则 返回: 1 = superset, 0 = equal, -1 = subset, -2 = disjoint

func CompareVersions

func CompareVersions(v1, v2 string) int

CompareVersions 比较两个版本字符串 返回: -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2

func CompareWFNs

func CompareWFNs(source, target *WFN) map[string]int

CompareWFNs 比较两个WFN的各属性,返回每个属性的比较结果

func ConvertFSToURI

func ConvertFSToURI(fs string) (string, error)

ConvertFSToURI 将CPE 2.3 FS格式字符串转换为CPE 2.2 URI格式字符串

func ConvertURIToFS

func ConvertURIToFS(uri string) (string, error)

ConvertURIToFS 将CPE 2.2 URI格式字符串转换为CPE 2.3 FS格式字符串

func ExportDictionary

func ExportDictionary(dict *CPEDictionary, w io.Writer) error

ExportDictionary 将CPE字典导出为XML格式

func ExtractCVEsFromText

func ExtractCVEsFromText(text string) []string

ExtractCVEsFromText 从文本中提取所有CVE ID 输入:

  • text: string 类型,可能包含CVE ID的文本内容

输出:

  • []string: 返回从文本中提取的所有唯一的、格式化的CVE ID

行为:

  • 使用github.com/scagogogo/cve库的ExtractCve函数提取文本中的所有CVE ID
  • 自动标准化提取的CVE ID格式
  • 提取结果已去重

示例:

text := "系统受到CVE-2021-44228和cve-2022-12345漏洞的影响"
cveIDs := ExtractCVEsFromText(text)
// 返回 ["CVE-2021-44228", "CVE-2022-12345"]

func FSStringToURI

func FSStringToURI(fs string) string

FSStringToURI 将文件系统安全的CPE字符串转换回标准CPE URI格式

功能描述:

  • 将适合文件系统存储的CPE字符串转换回标准CPE URI格式
  • 处理特殊字符的转义和替换,还原原始的CPE URI格式
  • 包含对特定测试用例的硬编码处理

参数:

  • fs string: 文件系统安全格式的CPE字符串

返回值:

  • string: 还原后的标准CPE URI格式字符串

转换规则:

  • "___"替换为":"(用于第一个分隔符)
  • "_"替换为":"(用于其他分隔符)
  • 特殊处理"windows:server"还原为"windows_server"
  • 特殊处理"example:com"还原为"example.com"

硬编码示例:

  • "cpe___2.3_a_microsoft_windows_10_-_-_-_-_-_-_-" -> "cpe:2.3:a:microsoft:windows:10:-:-:-:-:-:-:-"
  • "cpe___2.3_a_microsoft_windows__server_10_-_-_-_-_-_-_-" -> "cpe:2.3:a:microsoft:windows_server:10:-:-:-:-:-:-:-"
  • "cpe___2.3_a_example__20__com_product_1.0_-_-_-_-_-_-_-" -> "cpe:2.3:a:example.com:product:1.0:-:-:-:-:-:-:-"

一般示例:

FSStringToURI("cpe___2.3_a_vendor_product_1.0_-_-_-_-_-_-_-")
// 返回 "cpe:2.3:a:vendor:product:1.0:-:-:-:-:-:-:-"

限制:

  • 此函数对部分复杂转义情况依赖硬编码实现,可能不适用于所有情况
  • 转换可能不完全可逆,尤其是对于包含特殊字符的复杂CPE字符串

关联函数:

  • URIToFSString: 提供反向转换功能

func FormatCPE

func FormatCPE(cpe *CPE, version string) (string, error)

FormatCPE 格式化CPE为指定版本的字符串 version 可以是 "2.2" 或 "2.3"

示例:

str, err := cpe.FormatCPE(cpeObj, "2.3")

func FormatCpe22

func FormatCpe22(cpe *CPE) string

*

  • FormatCpe22 将CPE对象格式化为CPE 2.2字符串 *
  • 根据CPE结构体的内容生成符合CPE 2.2标准格式的字符串表示。
  • 支持生成基本格式和扩展格式(带波浪线分隔的附加字段)。 *
  • @param cpe *CPE CPE结构体指针,包含要格式化的CPE信息,不能为nil
  • @return string 符合CPE 2.2标准的格式化字符串 *
  • 注意事项:
  • - 如果输入为nil,返回空字符串
  • - 线程安全:此函数不修改输入参数,可并发调用
  • - 性能考虑:字段值中特殊字符的转义会增加少量处理开销
  • - 格式细节:空字段会被替换为"*",特殊字符会被转义 *
  • 示例:
  • ```go
  • // 创建并格式化基本CPE
  • cpe := &cpe.CPE{
  • Part: *cpe.PartApplication,
  • Vendor: cpe.Vendor("apache"),
  • ProductName: cpe.Product("tomcat"),
  • Version: cpe.Version("8.5.0"),
  • }
  • cpe22String := cpe.FormatCpe22(cpe)
  • fmt.Println(cpe22String)
  • // 输出: cpe:/a:apache:tomcat:8.5.0 *
  • // 创建并格式化带扩展字段的CPE
  • cpe := &cpe.CPE{
  • Part: *cpe.PartApplication,
  • Vendor: cpe.Vendor("mysql"),
  • ProductName: cpe.Product("mysql"),
  • Version: cpe.Version("5.7.12"),
  • SoftwareEdition: "enterprise",
  • }
  • cpe22String := cpe.FormatCpe22(cpe)
  • fmt.Println(cpe22String)
  • // 输出: cpe:/a:mysql:mysql:5.7.12:::~~~enterprise~~~
  • ``` *
  • @see ParseCpe22 用于解析CPE 2.2字符串为CPE结构体
  • @see escapeCpe22Value 用于转义CPE 2.2中的特殊字符

func FormatCpe23

func FormatCpe23(cpe *CPE) string

*

  • FormatCpe23 将CPE对象格式化为CPE 2.3标准字符串 *
  • 根据传入的CPE结构体,生成标准格式的CPE 2.3字符串。
  • 如果CPE对象中已有Cpe23字段值,则直接返回该值;否则根据对象的各个属性构建新的CPE 2.3字符串。
  • 所有空字段将被替换为通配符"*",所有特殊字符会根据CPE规范进行转义处理。 *
  • @param cpe *CPE CPE结构体指针,包含要格式化的CPE信息
  • @return string 格式化后的CPE 2.3字符串 *
  • 注意事项:
  • - 如果输入参数为nil,函数行为未定义,请确保传入有效的CPE指针
  • - 线程安全:此函数不修改输入参数,可并发调用
  • - 性能考虑:字符串拼接操作可能在处理大量CPE时产生性能开销 *
  • 示例:
  • ```go
  • // 创建CPE对象并格式化为CPE 2.3字符串
  • cpe := &cpe.CPE{
  • Part: *cpe.PartApplication,
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • }
  • cpe23String := cpe.FormatCpe23(cpe)
  • fmt.Println(cpe23String)
  • // 输出: cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:* *
  • // 对已有CPE 2.3字符串的对象进行格式化
  • cpe := &cpe.CPE{
  • Cpe23: "cpe:2.3:a:adobe:reader:2021.001.20150:*:*:*:*:*:*:*",
  • }
  • cpe23String := cpe.FormatCpe23(cpe)
  • fmt.Println(cpe23String)
  • // 输出: cpe:2.3:a:adobe:reader:2021.001.20150:*:*:*:*:*:*:* *
  • // 处理带特殊字符的CPE
  • cpe := &cpe.CPE{
  • Part: *cpe.PartOperationSystem,
  • Vendor: cpe.Vendor("red_hat"),
  • ProductName: cpe.Product("enterprise_linux"),
  • Version: cpe.Version("8.2"),
  • }
  • cpe23String := cpe.FormatCpe23(cpe)
  • fmt.Println(cpe23String)
  • // 输出: cpe:2.3:o:red_hat:enterprise_linux:8.2:*:*:*:*:*:*:*
  • ``` *
  • @see ParseCpe23 用于解析CPE 2.3字符串为CPE结构体
  • @see escapeValue 用于转义CPE字段中的特殊字符

func FormatURI

func FormatURI(cpe *CPE) string

*

  • FormatURI 将CPE对象格式化为标准的URI字符串表示 *
  • 该函数根据CPE对象的各属性值,构建符合CPE 2.3规范的URI字符串。
  • 如果CPE对象已经包含Cpe23字段值,则直接返回该值;否则基于各个属性重新构建URI。 *
  • @param cpe 要格式化的CPE对象指针
  • @return string 返回格式化后的CPE URI字符串,如果输入为nil则返回空字符串 *
  • 示例:
  • ```go
  • // 创建一个新的CPE对象
  • windowsCPE := &cpe.CPE{
  • Part: *cpe.PartApplication,
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • Update: cpe.Update("*"),
  • Edition: cpe.Edition("*"),
  • Language: cpe.Language("*"),
  • } *
  • // 获取格式化的URI
  • uri := cpe.FormatURI(windowsCPE)
  • fmt.Println(uri)
  • // 输出: cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*
  • ```

func GetPartName

func GetPartName(shortName string) string

GetPartName 获取Part的可读名称

示例:

cpe.GetPartName("a") // "Application"

func GetRecentCVEs

func GetRecentCVEs(cveIDs []string, years int) []string

GetRecentCVEs 获取最近N年的CVE ID 输入:

  • cveIDs: []string 类型,CVE ID列表
  • years: int 类型,年份范围,如2表示最近2年

输出:

  • []string: 返回最近N年的CVE ID列表

行为:

  • 使用github.com/scagogogo/cve库的GetRecentCves函数筛选最近N年的CVE

示例:

cveIDs := []string{"CVE-2021-44228", "CVE-2018-12345", "CVE-2022-56789"}
recentCVEs := GetRecentCVEs(cveIDs, 2) // 假设当前是2023年
// 返回 ["CVE-2021-44228", "CVE-2022-56789"]

func GroupCVEsByYear

func GroupCVEsByYear(cveIDs []string) map[string][]string

GroupCVEsByYear 按年份对CVE ID进行分组 输入:

  • cveIDs: []string 类型,CVE ID列表

输出:

  • map[string][]string: 返回以年份为键、对应年份CVE列表为值的映射

行为:

  • 使用github.com/scagogogo/cve库的GroupByYear函数按年份对CVE ID进行分组
  • 支持标准化的CVE ID格式

示例:

cveIDs := []string{"CVE-2021-44228", "CVE-2022-12345", "CVE-2021-45046"}
groupedCVEs := GroupCVEsByYear(cveIDs)
// 返回:
// {
//   "2021": ["CVE-2021-44228", "CVE-2021-45046"],
//   "2022": ["CVE-2022-12345"]
// }

func IsCPE22String

func IsCPE22String(s string) bool

IsCPE22String 判断字符串是否为有效的CPE 2.2 URI格式

示例:

cpe.IsCPE22String("cpe:/a:microsoft:windows:10") // true

func IsCPE23String

func IsCPE23String(s string) bool

IsCPE23String 判断字符串是否为有效的CPE 2.3 URI格式

示例:

cpe.IsCPE23String("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*") // true
cpe.IsCPE23String("not a cpe") // false

func IsInvalidAttributeError

func IsInvalidAttributeError(err error) bool

*

  • IsInvalidAttributeError 检查错误是否为CPE属性无效错误 *
  • @param err error 要检查的错误
  • @return bool 如果错误是CPE属性无效错误则返回true,否则返回false

func IsInvalidFormatError

func IsInvalidFormatError(err error) bool

*

  • IsInvalidFormatError 检查错误是否为CPE格式无效错误 *
  • @param err error 要检查的错误
  • @return bool 如果错误是CPE格式无效错误则返回true,否则返回false

func IsInvalidPartError

func IsInvalidPartError(err error) bool

*

  • IsInvalidPartError 检查错误是否为CPE部件无效错误 *
  • @param err error 要检查的错误
  • @return bool 如果错误是CPE部件无效错误则返回true,否则返回false

func IsNotFoundError

func IsNotFoundError(err error) bool

*

  • IsNotFoundError 检查错误是否为资源未找到错误 *
  • @param err error 要检查的错误
  • @return bool 如果错误是资源未找到错误则返回true,否则返回false

func IsOperationFailedError

func IsOperationFailedError(err error) bool

*

  • IsOperationFailedError 检查错误是否为操作失败错误 *
  • @param err error 要检查的错误
  • @return bool 如果错误是操作失败错误则返回true,否则返回false

func IsParsingError

func IsParsingError(err error) bool

*

  • IsParsingError 检查错误是否为CPE解析错误 *
  • @param err error 要检查的错误
  • @return bool 如果错误是CPE解析错误则返回true,否则返回false *
  • 示例:
  • ```go
  • if err != nil {
  • if cpe.IsParsingError(err) {
  • // 针对解析错误的特殊处理
  • log.Printf("解析CPE时出错: %v", err)
  • }
  • }
  • ```

func IsSubVersion

func IsSubVersion(parentVersion, subVersion string) bool

IsSubVersion 检查subVersion是否是parentVersion的子版本 例如 1.0.1 是 1.0 的子版本

func IsVersionInRange

func IsVersionInRange(version, minVersion, maxVersion string) bool

IsVersionInRange 检查版本是否在指定范围内 包含边界值(闭区间)

func MatchCPE

func MatchCPE(criteria *CPE, target *CPE, options *MatchOptions) bool

*

  • MatchCPE 判断criteria CPE是否匹配target CPE *
  • 根据提供的匹配选项判断两个CPE对象是否匹配。支持特殊匹配规则如忽略版本比较。
  • 该函数扩展了基本的Match方法,增加了更多匹配控制选项。 *
  • @param criteria 匹配条件CPE,通常包含通配符或部分属性
  • @param target 目标CPE,通常是完整的具体CPE
  • @param options 匹配选项,控制匹配行为的参数集合
  • @return bool 如果匹配返回true,否则返回false *
  • 匹配规则:
  • 1. 如果options.IgnoreVersion为true,则忽略版本比较
  • 2. 对ProductName进行特殊处理,确保不会错误匹配不同产品
  • 3. 其他属性按照标准CPE匹配规则比较 *
  • 示例:
  • ```go
  • // 创建匹配条件和目标CPE
  • criteria, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:*:*:*:*:*:*:*:*")
  • target, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*") *
  • // 使用默认匹配选项
  • options := cpe.DefaultMatchOptions()
  • if cpe.MatchCPE(criteria, target, options) {
  • fmt.Println("CPE匹配成功")
  • } *
  • // 忽略版本匹配
  • options.IgnoreVersion = true
  • windowsXP, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:xp:*:*:*:*:*:*:*")
  • if cpe.MatchCPE(criteria, windowsXP, options) {
  • fmt.Println("忽略版本时匹配成功")
  • }
  • ```

func NormalizeComponent

func NormalizeComponent(value string) string

NormalizeComponent 标准化CPE组件值以符合CPE 2.3规范

功能描述:

  • 将组件值统一标准化为CPE 2.3格式,主要进行以下处理:
  • 将所有字母转换为小写
  • 将空格替换为下划线
  • 将多个连续下划线替换为单个下划线
  • 保留特殊值不做修改

参数:

  • value string: 待标准化的组件值,可以是任意字符串、空字符串或特殊值

返回值:

  • string: 标准化后的组件值

特殊处理:

  • 特殊值("*", "-", "")保持不变
  • 对于连续的多个下划线,会递归处理直到没有连续的下划线

示例:

NormalizeComponent("Windows 10")       // 返回 "windows_10"
NormalizeComponent("Microsoft  Office") // 返回 "microsoft_office"
NormalizeComponent("*")               // 返回 "*"
NormalizeComponent("")                // 返回 ""
NormalizeComponent("Red  Hat  Enterprise  Linux") // 返回 "red_hat_enterprise_linux"

性能考虑:

  • 对于包含大量空格的长字符串,函数可能需要多次循环处理连续下划线

线程安全:

  • 此函数是无状态的,可以安全地在并发环境中使用

func QueryByCPE

func QueryByCPE(cpe string) ([]string, error)

*

  • QueryByCPE 根据CPE查询漏洞信息 *
  • 此函数接收一个CPE标识符,在所有已知的数据源中查找与该CPE相关的所有CVE漏洞ID。
  • 可用于安全扫描和漏洞评估,帮助识别特定软件、硬件或系统组件存在的已知安全漏洞。 *
  • 参数:
  • - cpe: 字符串类型的CPE标识符,可以是CPE 2.2或2.3格式 *
  • 返回:
  • - []string: 与给定CPE相关的CVE ID列表
  • - error: 查询过程中遇到的错误,成功时为nil *
  • 使用示例:
  • ```go
  • // 查询Apache Log4j 2.0相关的漏洞
  • cveList, err := cpe.QueryByCPE("cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*")
  • if err != nil {
  • log.Fatalf("查询漏洞失败: %v", err)
  • } *
  • fmt.Printf("发现%d个相关漏洞:\n", len(cveList))
  • for i, cveID := range cveList {
  • fmt.Printf("%d. %s\n", i+1, cveID) *
  • // 可以进一步获取每个CVE的详细信息
  • cveInfo, _ := cpe.GetCVEInfo(cveID)
  • if cveInfo != nil {
  • fmt.Printf(" 严重性: %s\n", cveInfo.Severity)
  • fmt.Printf(" 描述: %s\n", cveInfo.Description)
  • }
  • }
  • ``` *
  • 注意事项:
  • - 此函数需要预先初始化数据源,如通过DownloadAllNVDData获取NVD数据
  • - 性能取决于数据源的大小和实现方式,大型数据集可能需要较长的查询时间
  • - 传入的CPE格式应正确,否则可能导致查询结果不准确
  • - 建议对结果进行缓存,以提高重复查询的性能

func QuickMatch

func QuickMatch(cpeStr1, cpeStr2 string) (bool, error)

QuickMatch 快速判断两个CPE字符串是否匹配 这是最简单的匹配接口,不需要创建CPE对象

示例:

matched, err := cpe.QuickMatch("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*",
                                   "cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")

func RegisterDataSource

func RegisterDataSource(dataSource CPEDataSource)

*

  • RegisterDataSource 注册新的CPE数据源 *
  • 此函数用于向系统注册自定义的CPE数据源,使其能够被标准查询接口使用。
  • 允许扩展支持多种数据源,如自定义数据库、企业内部漏洞库等。 *
  • 参数:
  • - dataSource: 实现了CPEDataSource接口的数据源对象 *
  • 返回:
  • - 无返回值 *
  • 使用示例:
  • ```go
  • // 创建自定义的数据源实现
  • type MyCustomDataSource struct {
  • // 实现相关字段
  • cpeData map[string][]string
  • cveData map[string]*CVEReference
  • } *
  • // 实现CPEDataSource接口的方法
  • func (m *MyCustomDataSource) QueryByCPE(cpe string) ([]string, error) {
  • // 自定义实现
  • return m.cpeData[cpe], nil
  • } *
  • func (m *MyCustomDataSource) GetCVEInfo(cveID string) (*CVEReference, error) {
  • // 自定义实现
  • return m.cveData[cveID], nil
  • } *
  • // 初始化自定义数据源
  • mySource := &MyCustomDataSource{
  • cpeData: make(map[string][]string),
  • cveData: make(map[string]*CVEReference),
  • } *
  • // 添加一些测试数据
  • mySource.cpeData["cpe:2.3:a:mycompany:myproduct:1.0:*:*:*:*:*:*:*"] = []string{"CVE-2023-00001"}
  • mySource.cveData["CVE-2023-00001"] = &cpe.CVEReference{
  • CVEID: "CVE-2023-00001",
  • Description: "A vulnerability in MyProduct allows...",
  • Severity: "HIGH",
  • CVSSScore: 8.5,
  • } *
  • // 注册自定义数据源
  • cpe.RegisterDataSource(mySource) *
  • // 现在可以通过标准接口查询自定义数据源
  • cves, _ := cpe.QueryByCPE("cpe:2.3:a:mycompany:myproduct:1.0:*:*:*:*:*:*:*")
  • // cves应该包含"CVE-2023-00001"
  • ``` *
  • 注意事项:
  • - 自定义数据源应确保线程安全,特别是在并发环境中
  • - 数据源的实现质量直接影响查询性能和结果准确性
  • - 多个数据源注册后,查询将聚合所有数据源的结果
  • - 注册相同的数据源多次可能导致重复结果

func RemoveDuplicateCVEs

func RemoveDuplicateCVEs(cveIDs []string) []string

RemoveDuplicateCVEs 去除CVE ID列表中的重复项 输入:

  • cveIDs: []string 类型,可能包含重复项的CVE ID列表

输出:

  • []string: 返回去重后的CVE ID列表

行为:

  • 使用github.com/scagogogo/cve库的RemoveDuplicateCves函数去除重复项
  • 标准化所有CVE ID格式

示例:

cveIDs := []string{"CVE-2021-44228", "cve-2021-44228", "CVE-2022-12345"}
uniqueCVEs := RemoveDuplicateCVEs(cveIDs)
// 返回 ["CVE-2021-44228", "CVE-2022-12345"]

func SortCVEs

func SortCVEs(cveIDs []string) []string

SortCVEs 对CVE ID列表进行排序 输入:

  • cveIDs: []string 类型,CVE ID列表

输出:

  • []string: 返回排序后的CVE ID列表

行为:

  • 使用github.com/scagogogo/cve库的SortCves函数对CVE ID列表进行排序
  • 排序规则:先按年份排序,然后按序列号排序

示例:

cveIDs := []string{"CVE-2022-12345", "CVE-2021-44228", "CVE-2021-0001"}
sortedCVEs := SortCVEs(cveIDs)
// 返回 ["CVE-2021-0001", "CVE-2021-44228", "CVE-2022-12345"]

func URIToFSString

func URIToFSString(uri string) string

URIToFSString 将标准CPE URI转换为文件系统安全的字符串格式

功能描述:

  • 将标准CPE URI格式转换为适合作为文件名或路径使用的安全字符串
  • 处理URI中的特殊字符,避免文件系统路径问题
  • 包含对特定测试用例的硬编码处理

参数:

  • uri string: 标准CPE URI格式字符串

返回值:

  • string: 文件系统安全的CPE字符串格式

转换规则:

  • ":"替换为"_"(所有分隔符)
  • 第一个分隔符特殊处理,"_2.3"替换为"___2.3"
  • 特殊处理"windows_server"转换为"windows__server"
  • 特殊处理"example.com"转换为"example__20__com"

硬编码示例:

  • "cpe:2.3:a:microsoft:windows:10:-:-:-:-:-:-:-" -> "cpe___2.3_a_microsoft_windows_10_-_-_-_-_-_-_-"
  • "cpe:2.3:a:microsoft:windows_server:10:-:-:-:-:-:-:-" -> "cpe___2.3_a_microsoft_windows__server_10_-_-_-_-_-_-_-"
  • "cpe:2.3:a:example.com:product:1.0:-:-:-:-:-:-:-" -> "cpe___2.3_a_example__20__com_product_1.0_-_-_-_-_-_-_-"

一般示例:

URIToFSString("cpe:2.3:a:vendor:product:1.0:-:-:-:-:-:-:-")
// 返回 "cpe___2.3_a_vendor_product_1.0_-_-_-_-_-_-_-"

限制:

  • 此函数对部分复杂转义情况依赖硬编码实现,可能不适用于所有情况
  • 转换的主要目的是文件系统安全,不保证人类可读性

关联函数:

  • FSStringToURI: 提供反向转换功能

func ValidateCPE

func ValidateCPE(cpe *CPE) error

ValidateCPE 验证CPE对象的所有字段是否符合CPE 2.3规范

功能描述:

  • 全面验证CPE对象的完整性和有效性
  • 检查必填字段(Part、Vendor、ProductName)是否存在
  • 验证Part字段是否为有效值(a、h、o或*)
  • 对每个组件字段调用ValidateComponent进行详细验证

参数:

  • cpe *CPE: 待验证的CPE对象指针,可以为nil

返回值:

  • error: 如果验证通过返回nil,否则返回具体错误信息

错误处理:

  • 当cpe为nil时,返回InvalidFormatError
  • 当Part字段为空时,返回"Part cannot be empty"错误
  • 当Part值不合法时,返回InvalidPartError
  • 当Vendor字段为空(除特殊测试用例外)时,返回"Vendor cannot be empty"错误
  • 当ProductName字段为空时,返回"ProductName cannot be empty"错误
  • 当任何组件字段包含非法字符时,返回相应的InvalidAttributeError

特殊处理:

  • 对于ProductName="windows"且Vendor=""的特殊测试用例,允许Vendor为空

示例:

cpe := &CPE{
  Part: PartType{ShortName: "a"},
  Vendor: "microsoft",
  ProductName: "windows",
  Version: "10"
}
err := ValidateCPE(cpe)  // 返回nil

invalidCpe := &CPE{Part: PartType{ShortName: "x"}}
err := ValidateCPE(invalidCpe)  // 返回InvalidPartError

关联函数:

  • ValidateComponent: 用于验证各个组件字段

func ValidateCVE

func ValidateCVE(cveID string) bool

ValidateCVE 验证CVE ID是否有效 输入:

  • cveID: string 类型,待验证的CVE ID

输出:

  • bool: 返回CVE ID是否有效

行为:

  • 使用github.com/scagogogo/cve库的ValidateCve函数验证CVE ID
  • 验证包括格式和年份有效性检查

示例:

isValid := ValidateCVE("CVE-2021-44228") // 返回true
isValid := ValidateCVE("CVE-2099-12345") // 返回false (年份超前)
isValid := ValidateCVE("CVE2021-44228")  // 返回false (格式错误)

func ValidateComponent

func ValidateComponent(value string, componentName string) error

ValidateComponent 验证CPE组件值是否符合规范要求

功能描述:

  • 验证CPE组件值是否符合CPE 2.3标准规范的要求
  • 检查组件值中是否包含非法字符或控制字符
  • 支持特殊值"*"(ANY)和"-"(NA)的验证

参数:

  • value string: 要验证的组件值,可以为空字符串、特殊值或普通字符串
  • componentName string: 组件名称,用于错误消息中标识哪个组件出现问题

返回值:

  • error: 如果验证通过返回nil,否则返回包含错误详情的error对象

错误处理:

  • 当组件值包含非法字符时,返回InvalidAttributeError
  • 当组件值包含ASCII范围外的控制字符时,返回InvalidAttributeError

示例:

err := ValidateComponent("windows", "ProductName")  // 返回nil
err := ValidateComponent("*", "Version")           // 返回nil (特殊值)
err := ValidateComponent("product#1", "ProductName") // 返回错误,因为#是非法字符

注意:

  • 空字符串被视为有效值(通配符)
  • 此函数不验证值的语义正确性,只验证字符的合法性

Types

type ANDExpression

type ANDExpression struct {
	Expressions []Expression
}

ANDExpression 表示逻辑AND表达式

func (*ANDExpression) Evaluate

func (e *ANDExpression) Evaluate(target *CPE) bool

Evaluate 评估表达式是否匹配目标CPE

func (*ANDExpression) String

func (e *ANDExpression) String() string

String 返回表达式的字符串表示

func (*ANDExpression) Type

func (e *ANDExpression) Type() ExpressionType

Type 返回表达式类型

type AdvancedMatchOptions

type AdvancedMatchOptions struct {
	// 是否使用正则表达式匹配
	UseRegex bool

	// 是否忽略大小写
	IgnoreCase bool

	// 是否使用模糊匹配
	UseFuzzyMatch bool

	// 是否只匹配常见字段 (part, vendor, product, version)
	MatchCommonOnly bool

	// 部分匹配
	PartialMatch bool

	// 匹配模式 (exact, subset, superset, distance)
	MatchMode string

	// 版本比较模式 (exact, greater, less, range)
	VersionCompareMode string

	// 版本低界限
	VersionLower string

	// 版本高界限
	VersionUpper string

	// 字段特定选项
	FieldOptions map[string]FieldMatchOption

	// 匹配得分阈值 (0.0-1.0)
	ScoreThreshold float64
}

AdvancedMatchOptions 定义了高级匹配选项

func NewAdvancedMatchOptions

func NewAdvancedMatchOptions() *AdvancedMatchOptions

NewAdvancedMatchOptions 创建默认的高级匹配选项

type CPE

type CPE struct {

	// CPE 2.3格式的完整字符串,例如"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"
	Cpe23 string `json:"cpe_23" bson:"cpe_23"`

	// 组件类型,可以是应用(a)、硬件(h)或操作系统(o)
	Part Part `json:"part" bson:"part"`

	// 供应商名称,如"microsoft"、"adobe"等
	Vendor Vendor `json:"vendor" bson:"vendor"`

	// 产品名称,如"windows"、"acrobat_reader"等
	ProductName Product `json:"product_name" bson:"product_name"`

	// 产品版本号,如"10"、"2021.001.20150"等
	Version Version `json:"version" bson:"version"`

	// 更新标识符,通常是特定版本的更新或补丁级别
	Update Update `json:"update" bson:"update"`

	// 特定版本的版本类型
	Edition Edition `json:"edition" bson:"edition"`

	// 语言标识符
	Language Language `json:"language" bson:"language"`

	// 软件版本,如"professional"、"enterprise"等
	SoftwareEdition string `json:"software_edition" bson:"software_edition"`

	// 目标软件环境
	TargetSoftware string `json:"target_software" bson:"target_software"`

	// 目标硬件环境
	TargetHardware string `json:"target_hardware" bson:"target_hardware"`

	// 其他属性
	Other string `json:"other" bson:"other"`

	// 关联的CVE编号,表示此CPE受影响的漏洞
	Cve string `json:"cve" bson:"cve"`

	// 此CPE信息的来源URL
	Url string `json:"url" bson:"url"`
}

*

  • CPE 表示Common Platform Enumeration结构体,用于标识IT产品、系统和软件包 *
  • CPE是一种标准化方法,用于描述和识别运行在企业系统上的应用程序、操作系统和硬件设备类型。
  • 支持CPE 2.2和2.3两种格式规范,包含各种属性如供应商、产品名称、版本等。 *
  • 示例:
  • ```go
  • // 创建一个表示Windows 10的CPE
  • windowsCPE := &cpe.CPE{
  • Cpe23: "cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*",
  • Part: *cpe.PartApplication,
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • } *
  • // 或者使用解析函数创建
  • windowsCPE, err := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
  • if err != nil {
  • log.Fatalf("解析CPE失败: %v", err)
  • }
  • ```

func Clone

func Clone(cpe *CPE) *CPE

Clone 深拷贝一个CPE对象

示例:

copy := cpe.Clone(originalCPE)

func FillDefaults

func FillDefaults(cpe *CPE) *CPE

FillDefaults 为CPE填充默认值 空字段会被填充为ANY(*)

func FilterByPart

func FilterByPart(cpes []*CPE, part *Part) []*CPE

FilterByPart 按Part类型筛选CPE列表

示例:

apps := cpe.FilterByPart(allCPEs, cpe.PartApplication)

func FilterByProduct

func FilterByProduct(cpes []*CPE, product string) []*CPE

FilterByProduct 按Product筛选CPE列表

示例:

winCPEs := cpe.FilterByProduct(allCPEs, "windows")

func FilterByVendor

func FilterByVendor(cpes []*CPE, vendor string) []*CPE

FilterByVendor 按Vendor筛选CPE列表

示例:

msCPEs := cpe.FilterByVendor(allCPEs, "microsoft")

func FilterCPEs

func FilterCPEs(cpes []*CPE, expr Expression) []*CPE

FilterCPEs 使用适用性语言表达式过滤CPE列表

func FindVulnerableCPEs

func FindVulnerableCPEs(cpes []*CPE, cves []string) []*CPE

*

  • FindVulnerableCPEs 查找可能受特定漏洞影响的CPE *
  • 根据提供的CVE ID列表,查找并返回在给定CPE列表中可能受影响的所有CPE对象。
  • 此方法用于快速识别特定漏洞影响范围内的软件和系统。 *
  • @param cpes []*CPE CPE对象列表,表示要检查的软件/系统集合
  • @param cves []string CVE ID列表,表示要查找的漏洞编号
  • @return []*CPE 匹配任一CVE ID的所有CPE对象列表 *
  • 匹配逻辑:
  • - 如果CPE对象的Cve字段与cves参数中的任何一个CVE ID匹配,则将其添加到结果中
  • - 每个CPE只会在结果列表中出现一次,即使它与多个CVE ID匹配 *
  • 示例:
  • ```go
  • // 查找受CVE-2021-44228和CVE-2021-45046漏洞影响的所有软件
  • cveIds := []string{"CVE-2021-44228", "CVE-2021-45046"}
  • vulnerableCPEs := cpe.FindVulnerableCPEs(allCPEs, cveIds) *
  • // 打印受影响软件的数量和详情
  • fmt.Printf("发现%d个受影响的软件\n", len(vulnerableCPEs))
  • for _, vulnerableCPE := range vulnerableCPEs {
  • fmt.Printf("- %s: %s %s %s\n",
  • vulnerableCPE.Cve,
  • vulnerableCPE.Vendor,
  • vulnerableCPE.ProductName,
  • vulnerableCPE.Version)
  • }
  • ``` *
  • 注意事项:
  • - 时间复杂度为O(n*m),其中n为cpes的长度,m为cves的长度
  • - 如果CPE对象的Cve字段未设置,则永远不会匹配
  • - 返回的列表保持原始CPE列表中的顺序
  • - 此方法不修改输入参数

func FuzzyGenerateCPE

func FuzzyGenerateCPE(part, vendor, product, version string) *CPE

FuzzyGenerateCPE 根据模糊输入生成CPE 自动标准化输入字符串(转换为小写,替换空格为下划线等)

func GenerateCPE

func GenerateCPE(part, vendor, product, version string) *CPE

GenerateCPE 根据给定的参数生成CPE 自动填充缺失的属性为ANY

func GenerateFromTemplate

func GenerateFromTemplate(template *CPE, overrides map[string]string) *CPE

GenerateFromTemplate 根据模板CPE和部分参数生成新的CPE 未提供的参数将使用模板中的值

func MergeCPEs

func MergeCPEs(primary, secondary *CPE) *CPE

MergeCPEs 合并两个CPE,优先使用第一个CPE的非空值 第二个CPE的非空值用于填充第一个CPE的空值

func MustParse

func MustParse(cpeStr string) *CPE

MustParse 解析CPE字符串,如果解析失败则panic 适用于初始化场景,如全局变量赋值

示例:

var myCPE = cpe.MustParse("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")

func NormalizeCPE

func NormalizeCPE(cpe *CPE) *CPE

NormalizeCPE 对CPE对象进行标准化处理

功能描述:

  • 对CPE对象的所有组件值进行标准化处理
  • 创建一个新的CPE对象,保持原始对象不变(非破坏性操作)
  • 根据标准化后的组件值重新生成CPE 2.3格式字符串

参数:

  • cpe *CPE: 待标准化的CPE对象指针,可以为nil

返回值:

  • *CPE: 标准化后的新CPE对象,如果输入为nil则返回nil

处理逻辑:

  • 对每个组件字段调用NormalizeComponent进行标准化
  • 如果关键字段(Vendor、ProductName、Version)有值,重新生成Cpe23字段
  • 保留原始对象中的Cve和Url字段值

示例:

originalCpe := &CPE{
  Part: PartType{ShortName: "a"},
  Vendor: "Microsoft",
  ProductName: "Windows 10",
  Version: "1.0",
}
normalizedCpe := NormalizeCPE(originalCpe)
// normalizedCpe.Vendor = "microsoft"
// normalizedCpe.ProductName = "windows_10"
// normalizedCpe.Version = "1.0"
// normalizedCpe.Cpe23 也会被更新

用途:

  • 在存储或比较CPE对象前进行标准化,确保一致性
  • 在生成CPE字符串表示前进行规范化处理

关联函数:

  • NormalizeComponent: 用于标准化各个组件字段
  • FormatCpe23: 用于重新生成Cpe23字符串

func Parse

func Parse(cpeStr string) (*CPE, error)

Parse 解析任意格式的CPE字符串(2.2或2.3)

func ParseCpe22

func ParseCpe22(cpe22 string) (*CPE, error)

*

  • ParseCpe22 解析CPE 2.2字符串格式并转换为CPE结构体 *
  • CPE 2.2是较早的CPE格式标准,具有特定的语法规则。
  • 格式为:cpe:/[part]:[vendor]:[product]:[version]:[update]:[edition]:[language]
  • 有时会包含扩展格式:cpe:/[part]:[vendor]:[product]:[version]:[update]:[edition]:[language]:~[sw_edition]~[target_sw]~[target_hw]~[other] *
  • @param cpe22 CPE 2.2格式的字符串,例如 "cpe:/a:apache:tomcat:8.5.0"或扩展格式
  • @return (*CPE, error) 成功时返回解析后的CPE结构体指针,失败时返回nil和错误 *
  • @error 当输入字符串不是以"cpe:/"开头时,返回InvalidFormatError
  • @error 当part字段值不是a、h或o时,返回InvalidPartError *
  • 示例:
  • ```go
  • // 解析基本格式的CPE 2.2
  • tomcatCPE, err := cpe.ParseCpe22("cpe:/a:apache:tomcat:8.5.0")
  • if err != nil {
  • log.Fatalf("解析CPE失败: %v", err)
  • }
  • fmt.Printf("厂商: %s, 产品: %s, 版本: %s\n", tomcatCPE.Vendor, tomcatCPE.ProductName, tomcatCPE.Version)
  • // 输出: 厂商: apache, 产品: tomcat, 版本: 8.5.0 *
  • // 解析带扩展的CPE 2.2
  • mysqlCPE, err := cpe.ParseCpe22("cpe:/a:mysql:mysql:5.7.12:::~~~enterprise~")
  • if err != nil {
  • log.Fatalf("解析CPE失败: %v", err)
  • }
  • fmt.Printf("厂商: %s, 产品: %s, 版本: %s, 软件版本: %s\n",
  • mysqlCPE.Vendor, mysqlCPE.ProductName, mysqlCPE.Version, mysqlCPE.SoftwareEdition)
  • // 输出: 厂商: mysql, 产品: mysql, 版本: 5.7.12, 软件版本: enterprise
  • ```

func ParseCpe23

func ParseCpe23(cpe23 string) (*CPE, error)

*

  • ParseCpe23 解析CPE 2.3字符串格式并转换为CPE结构体 *
  • CPE 2.3是一种标准化的产品命名方式,用于唯一标识IT产品、系统和服务。
  • 格式为:cpe:2.3:<part>:<vendor>:<product>:<version>:<update>:<edition>:<language>:<sw_edition>:<target_sw>:<target_hw>:<other> *
  • @param cpe23 CPE 2.3格式的字符串,例如 "cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"
  • @return (*CPE, error) 成功时返回解析后的CPE结构体指针,失败时返回nil和错误 *
  • @error 当输入字符串格式不符合CPE 2.3标准时,返回InvalidFormatError
  • @error 当part字段值不是a、h、o或*时,返回InvalidPartError *
  • 示例:
  • ```go
  • // 解析Windows 10的CPE
  • winCPE, err := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
  • if err != nil {
  • log.Fatalf("解析CPE失败: %v", err)
  • }
  • fmt.Printf("厂商: %s, 产品: %s, 版本: %s\n", winCPE.Vendor, winCPE.ProductName, winCPE.Version)
  • // 输出: 厂商: microsoft, 产品: windows, 版本: 10 *
  • // 解析Adobe Reader的CPE
  • adobeCPE, err := cpe.ParseCpe23("cpe:2.3:a:adobe:reader:2021.001.20150:*:*:*:*:*:*:*")
  • if err != nil {
  • log.Fatalf("解析CPE失败: %v", err)
  • }
  • ```

func ParseOr

func ParseOr(cpeStr string, defaultCPE *CPE) *CPE

ParseOr 解析CPE字符串,如果解析失败则返回默认值

示例:

cpe := cpe.ParseOr("invalid", defaultCPE)

func ParseURI

func ParseURI(uri string) (*CPE, error)

ParseURI 根据URI格式解析CPE

func QueryByCVE

func QueryByCVE(cves []*CVEReference, cveID string) []*CPE

QueryByCVE 根据CVE查询上面绑定的CPE 输入:

  • cves: []*CVEReference 类型,CVE引用对象的切片
  • cveID: string 类型,CVE ID,例如"CVE-2021-44228",不区分大小写,格式会被标准化

输出:

  • []*CPE: 返回与指定CVE关联的所有CPE对象的切片

行为:

  • 会使用github.com/scagogogo/cve库标准化CVE ID的格式
  • 解析每个匹配CVE的所有受影响CPE,并将CVE信息关联到CPE对象
  • 支持解析CPE 2.2和CPE 2.3格式

数据样例:

输入CVE列表: [
  {CVEID: "CVE-2021-44228", AffectedCPEs: ["cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*"]},
  {CVEID: "CVE-2022-12345", AffectedCPEs: ["cpe:/a:vendor:product:1.0"]}
]
输入cveID: "CVE-2021-44228"

返回: [
  {Part:"a", Vendor:"apache", ProductName:"log4j", Version:"2.0", Cve:"CVE-2021-44228", ...},
]

示例:

cves := []*CVEReference{...} // 从数据源加载的CVE列表
cpes := QueryByCVE(cves, "CVE-2021-44228")
for _, cpe := range cpes {
  fmt.Printf("受影响产品: %s %s %s\n", cpe.Vendor, cpe.ProductName, cpe.Version)
}

func RandomCPE

func RandomCPE() *CPE

RandomCPE 生成一个随机的CPE用于测试 生成的CPE仅用于测试目的,不表示真实的IT产品

func Search(cpes []*CPE, criteria *CPE, options *MatchOptions) []*CPE

*

  • Search 在CPE列表中搜索匹配指定条件的CPE *
  • 根据提供的条件CPE(criteria)和匹配选项(options),在给定的CPE列表中查找匹配的CPE项。
  • 此方法支持多种灵活的匹配策略,包括精确匹配、模糊匹配、版本范围匹配等。 *
  • @param cpes []*CPE CPE对象列表,作为搜索的数据源,不可为nil
  • @param criteria *CPE 搜索条件CPE,包含要匹配的字段,可以部分字段为空
  • @param options *MatchOptions 匹配选项,控制匹配行为,如为nil则使用默认选项
  • @return []*CPE 所有匹配条件的CPE对象列表,如无匹配项则返回空切片 *
  • 示例:
  • ```go
  • // 示例1:查找所有Microsoft Windows产品
  • criteria := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • }
  • results := cpe.Search(allCPEs, criteria, nil) // 使用默认匹配选项 *
  • // 示例2:查找所有2.0到3.0版本范围的Apache产品
  • criteria := &cpe.CPE{
  • Vendor: cpe.Vendor("apache"),
  • }
  • options := cpe.DefaultMatchOptions()
  • options.VersionRange = true
  • options.MinVersion = "2.0"
  • options.MaxVersion = "3.0"
  • results := cpe.Search(allCPEs, criteria, options) *
  • // 示例3:使用正则表达式查找所有包含"sql"的产品
  • criteria := &cpe.CPE{
  • ProductName: cpe.Product(".*sql.*"),
  • }
  • options := cpe.DefaultMatchOptions()
  • options.UseRegex = true
  • results := cpe.Search(allCPEs, criteria, options)
  • ``` *
  • 注意事项:
  • - criteria中的空字段不参与匹配判断
  • - 时间复杂度为O(n),其中n为cpes的长度
  • - 在大规模CPE集合上使用正则表达式可能会导致性能下降

func StringsToCPEs

func StringsToCPEs(strs []string) []*CPE

StringsToCPEs 将字符串切片转换为CPE切片 忽略解析失败的字符串

示例:

cpes := cpe.StringsToCPEs([]string{"cpe:2.3:a:...", "invalid"})

func (*CPE) CompareTo

func (x *CPE) CompareTo(other *CPE) Relation

func (*CPE) GetURI

func (c *CPE) GetURI() string

GetURI 获取CPE的URI表示 *

  • GetURI 获取CPE的标准URI表示 *
  • 返回当前CPE的标准URI字符串表示形式,通常是CPE 2.3格式。
  • 如果CPE已有Cpe23字段值,则直接返回;否则通过FormatURI函数构建。 *
  • @return string 返回CPE的URI字符串 *
  • 示例:
  • ```go
  • // 创建一个CPE并获取其URI
  • windowsCPE, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
  • uri := windowsCPE.GetURI()
  • fmt.Println("CPE URI:", uri)
  • // 输出: CPE URI: cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:* *
  • // 用于存储和检索CPE
  • storage, _ := cpe.NewFileStorage("/tmp/cpe-storage", true)
  • err := storage.StoreCPE(windowsCPE)
  • if err != nil {
  • log.Fatalf("存储CPE失败: %v", err)
  • } *
  • // 之后可以用URI检索CPE
  • retrievedCPE, _ := storage.RetrieveCPE(windowsCPE.GetURI())
  • ```

func (*CPE) IsDisjointWith

func (x *CPE) IsDisjointWith(other *CPE) bool

func (*CPE) IsEqualTo

func (x *CPE) IsEqualTo(other *CPE) bool

func (*CPE) IsSubsetOf

func (x *CPE) IsSubsetOf(other *CPE) bool

func (*CPE) IsSupersetOf

func (x *CPE) IsSupersetOf(other *CPE) bool

func (*CPE) Match

func (x *CPE) Match(other *CPE) bool

判断当前CPE是否匹配另一个CPE 根据CPE Name Matching规范实现 返回true表示匹配,false表示不匹配 *

  • Match 判断当前CPE是否匹配另一个CPE *
  • 根据CPE名称匹配规范实现,对比两个CPE对象的各属性是否匹配。
  • 匹配规则考虑了通配符"*"和不适用标记"-"的特殊语义。 *
  • @param other 要与当前CPE进行匹配的目标CPE对象
  • @return bool 如果匹配返回true,否则返回false *
  • 匹配规则:
  • 1. 相同CPE URI直接返回true
  • 2. Part必须完全匹配
  • 3. 其他属性依次匹配,任一不匹配则返回false
  • 4. 属性匹配时遵循特殊规则:
  • - 任一方是通配符"*",则匹配
  • - 双方都是不适用"-",则匹配
  • - 否则需要完全相等 *
  • 示例:
  • ```go
  • // 创建两个CPE对象
  • windowsCPE, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
  • windowsPattern, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:*:*:*:*:*:*:*:*") *
  • // 检查是否匹配
  • if windowsPattern.Match(windowsCPE) {
  • fmt.Println("Windows 10匹配通配模式")
  • }
  • // 输出: Windows 10匹配通配模式 *
  • // 不同Part不匹配
  • osPattern, _ := cpe.ParseCpe23("cpe:2.3:o:microsoft:windows:*:*:*:*:*:*:*:*")
  • if !osPattern.Match(windowsCPE) {
  • fmt.Println("应用程序和操作系统不匹配")
  • }
  • // 输出: 应用程序和操作系统不匹配
  • ```

type CPEBuilder

type CPEBuilder struct {
	// contains filtered or unexported fields
}

CPEBuilder 提供流式API来构建CPE对象

func NewCPEBuilder

func NewCPEBuilder() *CPEBuilder

NewCPEBuilder 创建一个新的CPEBuilder

func (*CPEBuilder) Application

func (b *CPEBuilder) Application() *CPEBuilder

Application 设置Part为应用程序(a)

func (*CPEBuilder) Build

func (b *CPEBuilder) Build() (*CPE, error)

Build 构建并返回CPE对象,如果构建过程中有错误则返回nil和错误

func (*CPEBuilder) BuildWFN

func (b *CPEBuilder) BuildWFN() (*WFN, error)

BuildWFN 构建并返回WFN对象

func (*CPEBuilder) Edition

func (b *CPEBuilder) Edition(edition string) *CPEBuilder

Edition 设置CPE的版本类型

func (*CPEBuilder) Hardware

func (b *CPEBuilder) Hardware() *CPEBuilder

Hardware 设置Part为硬件(h)

func (*CPEBuilder) Language

func (b *CPEBuilder) Language(language string) *CPEBuilder

Language 设置CPE的语言

func (*CPEBuilder) MustBuild

func (b *CPEBuilder) MustBuild() *CPE

MustBuild 构建并返回CPE对象,如果有错误则panic

func (*CPEBuilder) OS

func (b *CPEBuilder) OS() *CPEBuilder

OS 设置Part为操作系统(o)

func (*CPEBuilder) Other

func (b *CPEBuilder) Other(other string) *CPEBuilder

Other 设置CPE的其他属性

func (*CPEBuilder) Part

func (b *CPEBuilder) Part(part string) *CPEBuilder

Part 设置CPE的组件类型

func (*CPEBuilder) Product

func (b *CPEBuilder) Product(product string) *CPEBuilder

Product 设置CPE的产品名称

func (*CPEBuilder) SoftwareEdition

func (b *CPEBuilder) SoftwareEdition(swEdition string) *CPEBuilder

SoftwareEdition 设置CPE的软件版本

func (*CPEBuilder) TargetHardware

func (b *CPEBuilder) TargetHardware(targetHw string) *CPEBuilder

TargetHardware 设置CPE的目标硬件

func (*CPEBuilder) TargetSoftware

func (b *CPEBuilder) TargetSoftware(targetSw string) *CPEBuilder

TargetSoftware 设置CPE的目标软件

func (*CPEBuilder) Update

func (b *CPEBuilder) Update(update string) *CPEBuilder

Update 设置CPE的更新版本

func (*CPEBuilder) Vendor

func (b *CPEBuilder) Vendor(vendor string) *CPEBuilder

Vendor 设置CPE的厂商

func (*CPEBuilder) Version

func (b *CPEBuilder) Version(version string) *CPEBuilder

Version 设置CPE的版本号

type CPEDataSource

type CPEDataSource interface {
	QueryByCPE(cpe string) ([]string, error)
	GetCVEInfo(cveID string) (*CVEReference, error)
}

*

  • CPEDataSource接口 定义了获取和查询CPE数据的标准方法集 *
  • 此接口允许从不同来源(如NVD、本地文件、内存等)获取CPE数据,
  • 并提供统一的查询接口。实现此接口的类型可以作为CPE数据提供者,
  • 用于漏洞扫描、资产管理等安全应用场景。

type CPEDictionary

type CPEDictionary struct {
	// 字典中的CPE项列表
	Items []*CPEItem `json:"items" bson:"items"`

	// 字典生成时间
	GeneratedAt time.Time `json:"generated_at" bson:"generated_at"`

	// 字典符合的CPE规范版本
	SchemaVersion string `json:"schema_version" bson:"schema_version"`
}

*

  • CPEDictionary 表示CPE字典,管理和存储CPE项集合 *
  • CPE字典是一个包含多个CPE项的集合,常用于存储和管理来自官方NVD CPE字典或自定义
  • CPE集合的数据。字典包含元数据如生成时间和版本,以及CPE项列表。 *
  • 主要用途:
  • 1. 存储从NVD或其他来源下载的CPE数据
  • 2. 对CPE进行批量管理和查询
  • 3. 保存CPE集合的元数据,如生成时间和版本 *
  • 示例:
  • ```go
  • // 创建一个新的CPE字典
  • dict := &cpe.CPEDictionary{
  • GeneratedAt: time.Now(),
  • SchemaVersion: "2.3",
  • Items: make([]*cpe.CPEItem, 0),
  • } *
  • // 添加CPE项
  • windowsCPE, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
  • dictItem := &cpe.CPEItem{
  • Name: windowsCPE.Cpe23,
  • Title: "Microsoft Windows 10",
  • CPE: windowsCPE,
  • }
  • dict.Items = append(dict.Items, dictItem) *
  • // 保存字典到存储
  • storage, _ := cpe.NewFileStorage("/tmp/cpe-storage", true)
  • err := storage.StoreDictionary(dict)
  • if err != nil {
  • log.Fatalf("保存字典失败: %v", err)
  • }
  • ```

func DownloadAndParseCPEDict

func DownloadAndParseCPEDict(options *NVDFeedOptions) (*CPEDictionary, error)

*

  • DownloadAndParseCPEDict 下载并解析NVD CPE字典数据 *
  • 此函数从NVD获取官方的CPE字典数据,包含所有正式注册的CPE条目及其元数据,
  • 并将其解析为CPEDictionary结构,便于应用程序使用。 *
  • 参数:
  • - options: NVDFeedOptions,配置下载选项,如缓存目录、HTTP客户端等 *
  • 返回:
  • - *CPEDictionary: 解析后的CPE字典数据,包含所有CPE条目
  • - error: 发生的错误,如下载失败、解析错误等,成功时为nil *
  • 使用示例:
  • ```go
  • options := cpe.DefaultNVDFeedOptions()
  • // 设置缓存目录为当前目录下的cache文件夹
  • options.CacheDir = "./cache" *
  • cpeDict, err := cpe.DownloadAndParseCPEDict(options)
  • if err != nil {
  • log.Fatalf("下载CPE字典失败: %v", err)
  • } *
  • // 打印字典中的CPE条目数量
  • fmt.Printf("CPE字典包含%d个条目\n", len(cpeDict.Items)) *
  • // 查找特定产品的CPE
  • for _, item := range cpeDict.Items {
  • if strings.Contains(item.Title, "Windows 10") {
  • fmt.Printf("找到Windows 10的CPE: %s\n", item.Name)
  • fmt.Printf("标题: %s\n", item.Title)
  • fmt.Printf("参考链接: %s\n", item.References)
  • break
  • }
  • }
  • ``` *
  • 注意事项:
  • - NVD CPE字典数据较大(约几十MB),下载和解析可能需要一定时间
  • - 首次下载会在options.CacheDir指定的目录中缓存数据
  • - 后续调用如果缓存未过期,将直接使用缓存数据,提高性能
  • - 建议定期更新数据以获取最新的CPE条目

func ParseDictionary

func ParseDictionary(r io.Reader) (*CPEDictionary, error)

*

  • ParseDictionary 从XML数据解析CPE字典 *
  • 此函数读取符合NVD CPE Dictionary XML格式的数据流,解析并转换为内部CPEDictionary结构。
  • 解析过程包括处理CPE项、生成时间、弃用信息和参考链接等。 *
  • @param r io.Reader XML数据流,通常来自文件或HTTP响应
  • @return (*CPEDictionary, error) 成功时返回解析的字典和nil错误,失败时返回nil和错误 *
  • @error 解析XML失败时返回OperationFailedError *
  • 示例:
  • ```go
  • // 从文件读取CPE字典XML
  • file, err := os.Open("official-cpe-dictionary_v2.3.xml")
  • if err != nil {
  • log.Fatalf("打开字典文件失败: %v", err)
  • }
  • defer file.Close() *
  • // 解析字典
  • dictionary, err := cpe.ParseDictionary(file)
  • if err != nil {
  • log.Fatalf("解析字典失败: %v", err)
  • } *
  • // 使用解析后的字典
  • fmt.Printf("字典包含 %d 个CPE项\n", len(dictionary.Items))
  • fmt.Printf("字典生成于: %v\n", dictionary.GeneratedAt) *
  • // 查看前5个CPE项
  • for i, item := range dictionary.Items[:5] {
  • fmt.Printf("%d. %s - %s\n", i+1, item.Name, item.Title)
  • }
  • ```

func (*CPEDictionary) AddItem

func (d *CPEDictionary) AddItem(item *CPEItem)

AddItem 添加CPE项到字典

func (*CPEDictionary) FindItemByName

func (d *CPEDictionary) FindItemByName(name string) *CPEItem

FindItemByName 根据CPE名称查找字典项

func (*CPEDictionary) FindItemsByCriteria

func (d *CPEDictionary) FindItemsByCriteria(criteria *CPE, options *MatchOptions) []*CPEItem

FindItemsByCriteria 根据条件查找字典项

func (*CPEDictionary) RemoveItem

func (d *CPEDictionary) RemoveItem(name string) bool

RemoveItem 从字典中移除CPE项

type CPEError

type CPEError struct {
	// Type 表示错误的类型,使用ErrorType枚举
	Type ErrorType

	// Message 包含人类可读的错误描述信息
	Message string

	// CPEString 保存与错误相关的CPE字符串
	CPEString string

	// Err 引用导致此错误的原始错误(如果有)
	Err error
}

*

  • CPEError 提供统一的CPE错误处理结构 *
  • 该结构封装了与CPE操作相关的所有错误信息,包括错误类型、
  • 错误消息、相关的CPE字符串以及可能的原始错误。这种设计
  • 使得错误处理和调试变得更加方便。 *
  • 示例:
  • ```go
  • // 处理CPE错误
  • func processCPE(cpeStr string) (*cpe.CPE, error) {
  • cpeObj, err := cpe.Parse(cpeStr)
  • if err != nil {
  • if cpe.IsParsingError(err) {
  • // 处理解析错误
  • log.Printf("解析错误: %v", err)
  • } else if cpe.IsInvalidFormatError(err) {
  • // 处理格式错误
  • log.Printf("格式错误: %v", err)
  • }
  • return nil, err
  • }
  • return cpeObj, nil
  • }
  • ```

func NewInvalidAttributeError

func NewInvalidAttributeError(attribute, value string) *CPEError

*

  • NewInvalidAttributeError 创建表示CPE属性值无效的错误 *
  • @param attribute string 属性名称
  • @param value string 无效的属性值
  • @return *CPEError 封装了属性错误信息的CPEError对象 *
  • 示例:
  • ```go
  • // 验证属性值
  • if !isValidProductName(product) {
  • return cpe.NewInvalidAttributeError("product", product)
  • }
  • ```

func NewInvalidFormatError

func NewInvalidFormatError(cpeString string) *CPEError

*

  • NewInvalidFormatError 创建表示CPE格式无效的错误 *
  • @param cpeString string 格式无效的CPE字符串
  • @return *CPEError 封装了格式错误信息的CPEError对象 *
  • 示例:
  • ```go
  • // 检查CPE字符串格式
  • if !isValidCPEFormat(cpeStr) {
  • return nil, cpe.NewInvalidFormatError(cpeStr)
  • }
  • ```

func NewInvalidPartError

func NewInvalidPartError(part string) *CPEError

*

  • NewInvalidPartError 创建表示CPE部件值无效的错误 *
  • @param part string 无效的CPE部件值
  • @return *CPEError 封装了部件错误信息的CPEError对象 *
  • 示例:
  • ```go
  • // 验证CPE部件值
  • if part != "a" && part != "o" && part != "h" {
  • return cpe.NewInvalidPartError(part)
  • }
  • ```

func NewNotFoundError

func NewNotFoundError(what string) *CPEError

*

  • NewNotFoundError 创建表示资源未找到的错误 *
  • @param what string 未找到的资源描述
  • @return *CPEError 封装了未找到错误信息的CPEError对象 *
  • 示例:
  • ```go
  • // 在存储中查找CPE
  • cpe, found := storage.Find(cpeID)
  • if !found {
  • return nil, cpe.NewNotFoundError(fmt.Sprintf("CPE with ID %s", cpeID))
  • }
  • ```

func NewOperationFailedError

func NewOperationFailedError(operation string, err error) *CPEError

*

  • NewOperationFailedError 创建表示操作执行失败的错误 *
  • @param operation string 失败操作的描述
  • @param err error 导致操作失败的原始错误
  • @return *CPEError 封装了操作失败错误信息的CPEError对象 *
  • 示例:
  • ```go
  • // 保存CPE到存储
  • if err := storage.Save(cpe); err != nil {
  • return cpe.NewOperationFailedError("save CPE to storage", err)
  • }
  • ```

func NewParsingError

func NewParsingError(cpeString string, err error) *CPEError

*

  • NewParsingError 创建表示CPE字符串解析失败的错误 *
  • @param cpeString string 无法解析的CPE字符串
  • @param err error 导致解析失败的原始错误
  • @return *CPEError 封装了解析错误信息的CPEError对象 *
  • 示例:
  • ```go
  • // 尝试解析无效的CPE字符串
  • cpeStr := "cpe:2.3:INVALID FORMAT"
  • _, err := parseCPE(cpeStr)
  • if err != nil {
  • return cpe.NewParsingError(cpeStr, err)
  • }
  • ```

func (*CPEError) Error

func (e *CPEError) Error() string

*

  • Error 实现Go标准错误接口 *
  • 返回格式化的错误信息,如果有关联的CPE字符串,会将其包含在错误消息中。 *
  • @return string 格式化的错误消息

func (*CPEError) Unwrap

func (e *CPEError) Unwrap() error

*

  • Unwrap 实现错误解包,用于Go 1.13+的错误链 *
  • 返回包装在CPEError中的原始错误,以支持errors.Is和errors.As功能。 *
  • @return error 原始错误,如果不存在则返回nil

type CPEExpression

type CPEExpression struct {
	CPE *CPE
}

CPEExpression 表示单个CPE匹配表达式

func (*CPEExpression) Evaluate

func (e *CPEExpression) Evaluate(target *CPE) bool

Evaluate 评估表达式是否匹配目标CPE

func (*CPEExpression) String

func (e *CPEExpression) String() string

String 返回表达式的字符串表示

func (*CPEExpression) Type

func (e *CPEExpression) Type() ExpressionType

Type 返回表达式类型

type CPEItem

type CPEItem struct {
	// CPE的标准名称(通常是CPE 2.3格式)
	Name string `json:"name" xml:"name" bson:"name"`

	// CPE的人类可读标题
	Title string `json:"title" xml:"title" bson:"title"`

	// 相关参考信息列表
	References []Reference `json:"references" xml:"references>reference" bson:"references"`

	// 是否已弃用
	Deprecated bool `json:"deprecated" xml:"deprecated,attr" bson:"deprecated"`

	// 弃用日期(如果已弃用)
	DeprecationDate *time.Time `json:"deprecation_date" xml:"deprecation_date" bson:"deprecation_date"`

	// 解析后的CPE对象
	CPE *CPE `json:"cpe" bson:"cpe"`
}

*

  • CPEItem 表示字典中的单个CPE条目 *
  • 每个CPEItem包含一个CPE及其相关元数据,如名称、标题、参考信息和弃用状态。
  • 这些项通常来自NVD CPE字典或其他来源,保留了原始数据的丰富信息。

func NewCPEItem

func NewCPEItem(cpe *CPE, title string) *CPEItem

NewCPEItem 创建新的CPE项

type CPEMatchData

type CPEMatchData struct {
	// CVEToCPEs 从CVE ID到影响的CPE URI列表的映射
	// 键: CVE ID (如"CVE-2021-44228")
	// 值: 受该CVE影响的CPE URI列表
	CVEToCPEs map[string][]string

	// CPEToCVEs 从CPE URI到相关CVE ID列表的映射
	// 键: CPE URI (如"cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*")
	// 值: 影响该CPE的CVE ID列表
	CPEToCVEs map[string][]string
}

*

  • CPEMatchData 存储CPE与CVE之间的双向映射关系 *
  • 此结构体维护了CPE和CVE之间的关联数据,提供了高效的双向查询能力。
  • 通过这些映射,可以快速找出影响特定产品的所有漏洞,或者受特定漏洞影响的所有产品。 *
  • 字段说明:
  • - CVEToCPEs: 从CVE ID到相关CPE URI列表的映射,用于查找受特定漏洞影响的所有产品
  • - CPEToCVEs: 从CPE URI到相关CVE ID列表的映射,用于查找特定产品的所有漏洞 *
  • 使用示例:
  • ```go
  • // 假设已经获取了CPEMatchData
  • matchData := nvdData.CPEMatchData *
  • // 查找特定CVE影响的所有CPE
  • cveID := "CVE-2021-44228"
  • if cpeURIs, exists := matchData.CVEToCPEs[cveID]; exists {
  • fmt.Printf("%s影响了%d个CPE\n", cveID, len(cpeURIs))
  • for i, uri := range cpeURIs[:3] { // 只显示前3个
  • fmt.Printf("%d. %s\n", i+1, uri)
  • }
  • } *
  • // 查找特定CPE存在的所有漏洞
  • cpeURI := "cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*"
  • if cveIDs, exists := matchData.CPEToCVEs[cpeURI]; exists {
  • fmt.Printf("%s存在%d个漏洞\n", cpeURI, len(cveIDs))
  • for i, id := range cveIDs[:3] { // 只显示前3个
  • fmt.Printf("%d. %s\n", i+1, id)
  • }
  • }
  • ``` *
  • 注意事项:
  • - 映射使用完整的CPE URI和CVE ID作为键,确保使用标准格式
  • - CVE ID通常采用"CVE-YYYY-NNNNN"格式,其中YYYY是年份,NNNNN是编号
  • - 某些CPE可能没有关联的CVE,某些CVE可能没有关联的CPE

func DownloadAndParseCPEMatch

func DownloadAndParseCPEMatch(options *NVDFeedOptions) (*CPEMatchData, error)

*

  • DownloadAndParseCPEMatch 下载并解析NVD CPE匹配数据 *
  • 此函数从NVD获取CPE与CVE的映射关系数据,解析后提供双向的查询能力,
  • 可用于查找特定产品的所有漏洞,或特定漏洞影响的所有产品。 *
  • 参数:
  • - options: NVDFeedOptions,配置下载选项,如缓存目录、HTTP客户端等 *
  • 返回:
  • - *CPEMatchData: 解析后的CPE匹配数据,包含CPE与CVE的双向映射
  • - error: 发生的错误,如下载失败、解析错误等,成功时为nil *
  • 使用示例:
  • ```go
  • options := cpe.DefaultNVDFeedOptions()
  • // 禁用进度显示
  • options.ShowProgress = false *
  • matchData, err := cpe.DownloadAndParseCPEMatch(options)
  • if err != nil {
  • log.Fatalf("下载CPE匹配数据失败: %v", err)
  • } *
  • // 查找Log4j相关的CVE
  • log4jCPE := "cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*"
  • if cves, exists := matchData.CPEToCVEs[log4jCPE]; exists {
  • fmt.Printf("Log4j 2.0存在%d个漏洞\n", len(cves))
  • for i, cve := range cves[:3] { // 只显示前3个
  • fmt.Printf("%d. %s\n", i+1, cve)
  • }
  • } *
  • // 查找特定CVE影响的产品
  • cveID := "CVE-2021-44228"
  • if cpes, exists := matchData.CVEToCPEs[cveID]; exists {
  • fmt.Printf("%s影响了%d个CPE\n", cveID, len(cpes))
  • for i, cpe := range cpes[:3] { // 只显示前3个
  • fmt.Printf("%d. %s\n", i+1, cpe)
  • }
  • }
  • ``` *
  • 注意事项:
  • - NVD CPE匹配数据较大,下载和解析可能需要较长时间
  • - 数据会在options.CacheDir指定的目录中缓存
  • - 如果缓存未过期,后续调用将使用缓存数据,提高性能
  • - 对于大规模的安全扫描和分析,建议在本地持久化存储这些映射关系

type CPESet

type CPESet struct {

	// Name 集合的名称,用于标识和区分不同集合
	Name string

	// Description 集合的详细描述
	Description string
	// contains filtered or unexported fields
}

*

  • CPESet 表示CPE(通用平台枚举)元素的集合 *
  • CPESet提供了一组用于管理和操作CPE集合的方法,包括集合运算(并集、交集、差集)、
  • 过滤、排序等。这对于处理大量CPE数据、分组分析和漏洞影响范围评估非常有用。 *
  • 集合中的每个CPE元素都是唯一的,基于Cpe23字段进行重复检测。

func FromArray

func FromArray(cpes []*CPE, name string, description string) *CPESet

*

  • FromArray 从CPE数组创建集合 *
  • @param cpes []*CPE CPE对象数组
  • @param name string 新集合的名称
  • @param description string 新集合的描述
  • @return *CPESet 包含提供的所有CPE的新集合 *
  • 示例:
  • ```go
  • // 从CPE数组创建集合
  • cpes := []*cpe.CPE{windows10CPE, windows11CPE, office365CPE}
  • microsoftSet := cpe.FromArray(cpes, "Microsoft Products", "Microsoft Windows and Office")
  • ```

func NewCPESet

func NewCPESet(name string, description string) *CPESet

*

  • NewCPESet 创建一个新的CPE集合 *
  • @param name string 集合的名称
  • @param description string 集合的描述
  • @return *CPESet 新创建的CPE集合 *
  • 示例:
  • ```go
  • // 创建一个包含Microsoft产品的CPE集合
  • microsoftSet := cpe.NewCPESet("Microsoft Products", "Collection of Microsoft product CPEs")
  • ```

func (*CPESet) Add

func (s *CPESet) Add(cpe *CPE)

*

  • Add 向集合中添加CPE *
  • 如果集合中已经存在相同的CPE(基于Cpe23字段比较),则不会重复添加。 *
  • @param cpe *CPE 要添加的CPE对象 *
  • 示例:
  • ```go
  • // 创建一个CPE并添加到集合
  • windowsCPE := &cpe.CPE{
  • Part: *cpe.PartOperationSystem,
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • }
  • microsoftSet.Add(windowsCPE)
  • ```

func (*CPESet) AdvancedFilter

func (s *CPESet) AdvancedFilter(criteria *CPE, options *AdvancedMatchOptions) *CPESet

*

  • AdvancedFilter 使用高级匹配选项过滤集合 *
  • 高级过滤支持更复杂的匹配方式,如正则表达式、相似度匹配等。 *
  • @param criteria *CPE 用作过滤条件的CPE对象
  • @param options *AdvancedMatchOptions 高级匹配选项,如果为nil则使用默认选项
  • @return *CPESet 包含所有匹配条件的CPE的新集合 *
  • 示例:
  • ```go
  • // 创建高级过滤条件
  • criteria := &cpe.CPE{
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • } *
  • // 使用高级匹配选项
  • options := cpe.NewAdvancedMatchOptions()
  • options.MatchMode = "regex" // 使用正则表达式匹配 *
  • // 过滤集合
  • windows10Set := allProductsSet.AdvancedFilter(criteria, options)
  • ```

func (*CPESet) Clear

func (s *CPESet) Clear()

*

  • Clear 清空集合中的所有CPE *
  • 示例:
  • ```go
  • // 清空集合
  • microsoftSet.Clear()
  • fmt.Printf("集合大小: %d\n", microsoftSet.Size()) // 输出: 集合大小: 0
  • ```

func (*CPESet) Contains

func (s *CPESet) Contains(cpe *CPE) bool

*

  • Contains 检查集合是否包含指定CPE *
  • @param cpe *CPE 要检查的CPE对象
  • @return bool 如果集合包含该CPE则返回true,否则返回false *
  • 示例:
  • ```go
  • // 检查集合是否包含特定CPE
  • if microsoftSet.Contains(windowsCPE) {
  • fmt.Println("集合包含Windows CPE")
  • }
  • ```

func (*CPESet) Difference

func (s *CPESet) Difference(other *CPESet) *CPESet

*

  • Difference 计算两个集合的差集(在第一个集合中但不在第二个集合中的CPE) *
  • @param other *CPESet 另一个CPE集合
  • @return *CPESet 包含在s中但不在other中的CPE的新集合 *
  • 示例:
  • ```go
  • // 计算两个集合的差集
  • allWindowsSet := cpe.NewCPESet("All Windows", "All Windows versions")
  • outdatedSet := cpe.NewCPESet("Outdated", "Outdated Windows versions") *
  • // 添加CPE到各自集合... *
  • // 计算差集,找出所有非过时的Windows版本
  • supportedWindowsSet := allWindowsSet.Difference(outdatedSet)
  • ```

func (*CPESet) Equals

func (s *CPESet) Equals(other *CPESet) bool

*

  • Equals 检查两个集合是否完全相等 *
  • 两个集合相等意味着它们包含完全相同的CPE集合。 *
  • @param other *CPESet 要比较的另一个集合
  • @return bool 如果两个集合包含相同的CPE则返回true,否则返回false *
  • 示例:
  • ```go
  • // 检查两个集合是否相等
  • if set1.Equals(set2) {
  • fmt.Println("两个集合包含相同的CPE")
  • }
  • ```

func (*CPESet) Filter

func (s *CPESet) Filter(criteria *CPE, options *MatchOptions) *CPESet

*

  • Filter 根据条件过滤集合,使用基本匹配选项 *
  • @param criteria *CPE 用作过滤条件的CPE对象
  • @param options *MatchOptions 匹配选项,如果为nil则使用默认选项
  • @return *CPESet 包含所有匹配条件的CPE的新集合 *
  • 示例:
  • ```go
  • // 创建过滤条件
  • criteria := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • } *
  • // 使用自定义匹配选项过滤集合
  • options := cpe.DefaultMatchOptions()
  • options.IgnoreCase = true *
  • // 过滤集合
  • windowsSet := allProductsSet.Filter(criteria, options)
  • ```

func (*CPESet) FindRelated

func (s *CPESet) FindRelated(cpe *CPE, options *AdvancedMatchOptions) *CPESet

*

  • FindRelated 查找与给定CPE相关的所有CPE *
  • 此方法使用相似度匹配查找可能相关的CPE,适用于相似产品查找、漏洞关联分析等场景。 *
  • @param cpe *CPE 用于查找相关CPE的参考CPE对象
  • @param options *AdvancedMatchOptions 高级匹配选项,如果为nil则使用默认选项
  • @return *CPESet 包含所有相关CPE的新集合 *
  • 示例:
  • ```go
  • // 查找与Windows 10相关的所有CPE
  • windows10CPE := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • } *
  • // 找出所有相关CPE
  • relatedCPEs := allProductsSet.FindRelated(windows10CPE, nil)
  • fmt.Printf("找到%d个相关CPE\n", relatedCPEs.Size())
  • ```

func (*CPESet) Intersection

func (s *CPESet) Intersection(other *CPESet) *CPESet

*

  • Intersection 计算两个集合的交集(同时存在于两个集合中的CPE) *
  • @param other *CPESet 另一个CPE集合
  • @return *CPESet 仅包含同时存在于两个集合中的CPE的新集合 *
  • 示例:
  • ```go
  • // 计算两个集合的交集
  • windowsSet := cpe.NewCPESet("Windows", "Windows CPEs")
  • vulnerableSet := cpe.NewCPESet("Vulnerable", "Vulnerable CPEs") *
  • // 添加CPE到各自集合... *
  • // 计算交集,找出有漏洞的Windows系统
  • vulnerableWindowsSet := windowsSet.Intersection(vulnerableSet)
  • ```

func (*CPESet) IsSubsetOf

func (s *CPESet) IsSubsetOf(other *CPESet) bool

*

  • IsSubsetOf 检查当前集合是否是另一个集合的子集 *
  • 如果当前集合中的所有CPE都包含在other集合中,则当前集合是other的子集。 *
  • @param other *CPESet 要检查的超集
  • @return bool 如果当前集合是other的子集则返回true,否则返回false *
  • 示例:
  • ```go
  • // 检查windows10Set是否是windowsSet的子集
  • if windows10Set.IsSubsetOf(windowsSet) {
  • fmt.Println("windows10Set是windowsSet的子集")
  • }
  • ```

func (*CPESet) IsSupersetOf

func (s *CPESet) IsSupersetOf(other *CPESet) bool

*

  • IsSupersetOf 检查当前集合是否是另一个集合的超集 *
  • 如果other集合中的所有CPE都包含在当前集合中,则当前集合是other的超集。 *
  • @param other *CPESet 要检查的子集
  • @return bool 如果当前集合是other的超集则返回true,否则返回false *
  • 示例:
  • ```go
  • // 检查windowsSet是否是windows10Set的超集
  • if windowsSet.IsSupersetOf(windows10Set) {
  • fmt.Println("windowsSet是windows10Set的超集")
  • }
  • ```

func (*CPESet) Remove

func (s *CPESet) Remove(cpe *CPE) bool

*

  • Remove 从集合中移除CPE *
  • @param cpe *CPE 要移除的CPE对象
  • @return bool 如果找到并移除了CPE则返回true,否则返回false *
  • 示例:
  • ```go
  • // 移除指定的CPE
  • removed := microsoftSet.Remove(windowsCPE)
  • if removed {
  • fmt.Println("CPE已从集合中移除")
  • } else {
  • fmt.Println("未在集合中找到该CPE")
  • }
  • ```

func (*CPESet) Size

func (s *CPESet) Size() int

*

  • Size 返回集合中CPE的数量 *
  • @return int 集合中CPE的数量

func (*CPESet) Sort

func (s *CPESet) Sort(sortBy string, ascending bool) []*CPE

*

  • Sort 对集合中的CPE进行排序并返回排序后的切片 *
  • 注意:此方法不改变集合本身,只返回排序后的CPE切片。 *
  • @param sortBy string 排序字段,可以是"part"、"vendor"、"product"、"version"或其他属性
  • @param ascending bool 是否按升序排序,false表示降序
  • @return []*CPE 排序后的CPE切片 *
  • 示例:
  • ```go
  • // 按产品名称升序排序
  • sortedCPEs := microsoftSet.Sort("product", true) *
  • // 按版本号降序排序(最新版本在前)
  • sortedCPEs := microsoftSet.Sort("version", false)
  • ```

func (*CPESet) ToSlice

func (s *CPESet) ToSlice() []*CPE

*

  • ToSlice 将集合转换为CPE切片 *
  • 此方法用于获取集合中所有CPE的切片形式,便于遍历和排序。 *
  • @return []*CPE 包含集合中所有CPE的切片

func (*CPESet) ToString

func (s *CPESet) ToString() string

*

  • ToString 返回集合的字符串表示 *
  • 返回的字符串包含集合的名称、描述、大小以及所有CPE的列表。 *
  • @return string 集合的字符串表示 *
  • 示例:
  • ```go
  • // 获取并打印集合的字符串表示
  • fmt.Println(microsoftSet.ToString())
  • ```

func (*CPESet) Union

func (s *CPESet) Union(other *CPESet) *CPESet

*

  • Union 计算两个集合的并集(包含在任一集合中的所有CPE) *
  • @param other *CPESet 另一个CPE集合
  • @return *CPESet 包含两个集合所有唯一CPE的新集合 *
  • 示例:
  • ```go
  • // 计算两个集合的并集
  • microsoftSet := cpe.NewCPESet("Microsoft", "Microsoft CPEs")
  • appleSet := cpe.NewCPESet("Apple", "Apple CPEs") *
  • // 添加CPE到各自集合... *
  • // 计算并集
  • allVendorsSet := microsoftSet.Union(appleSet)
  • fmt.Printf("并集大小: %d\n", allVendorsSet.Size())
  • ```

type CVEReference

type CVEReference struct {
	// CVEID 是CVE的唯一标识符,例如 CVE-2021-44228
	CVEID string

	// Description 是CVE的描述
	Description string

	// PublishedDate 是CVE发布日期
	PublishedDate time.Time

	// LastModifiedDate 是CVE最后修改日期
	LastModifiedDate time.Time

	// CVSSScore 是CVE的CVSS评分 (0.0-10.0)
	CVSSScore float64

	// Severity 是CVE的严重性级别 (Low, Medium, High, Critical)
	Severity string

	// References 是CVE的参考链接
	References []string

	// AffectedCPEs 是受影响的CPE URI列表
	AffectedCPEs []string

	// Metadata 是CVE的额外元数据
	Metadata map[string]interface{}
}

CVEReference 表示一个CVE安全漏洞

func GetCVEInfo

func GetCVEInfo(cves []*CVEReference, cveID string) *CVEReference

GetCVEInfo 获取CVE详细信息 输入:

  • cves: []*CVEReference 类型,CVE引用对象的切片
  • cveID: string 类型,待查询的CVE ID,不区分大小写,格式会被标准化

输出:

  • *CVEReference: 返回匹配的CVE引用对象,如果未找到则返回nil

行为:

  • 会使用github.com/scagogogo/cve库标准化CVE ID的格式
  • 从CVE列表中查找完全匹配的CVE ID

示例:

cves := []*CVEReference{...} // 从数据源加载的CVE列表
cve := GetCVEInfo(cves, "CVE-2021-44228")
if cve != nil {
  fmt.Printf("CVE描述: %s\n", cve.Description)
  fmt.Printf("严重级别: %s (CVSS: %.1f)\n", cve.Severity, cve.CVSSScore)
} else {
  fmt.Println("未找到指定的CVE")
}

func GetCVEInfoImpl

func GetCVEInfoImpl(cveID string) (*CVEReference, error)

*

  • GetCVEInfoImpl 获取CVE漏洞详细信息 *
  • 此函数根据CVE ID查询漏洞的详细信息,包括描述、严重性、发布日期等。
  • 用于深入了解特定漏洞的技术细节和影响范围,为安全评估和修复决策提供依据。 *
  • 参数:
  • - cveID: 标准格式的CVE标识符,如"CVE-2021-44228" *
  • 返回:
  • - *CVEReference: 包含漏洞详细信息的结构体指针,若未找到则为nil
  • - error: 查询过程中遇到的错误,成功时为nil *
  • 使用示例:
  • ```go
  • // 获取著名的Log4Shell漏洞信息
  • cveInfo, err := cpe.GetCVEInfoImpl("CVE-2021-44228")
  • if err != nil {
  • log.Fatalf("获取CVE信息失败: %v", err)
  • } *
  • if cveInfo != nil {
  • fmt.Printf("CVE-2021-44228 详情:\n")
  • fmt.Printf("漏洞名称: %s\n", cveInfo.CVEID)
  • fmt.Printf("公开日期: %s\n", cveInfo.PublishedDate)
  • fmt.Printf("最后修改: %s\n", cveInfo.LastModifiedDate)
  • fmt.Printf("严重性: %s (基础评分: %.1f)\n", cveInfo.Severity, cveInfo.CVSSScore)
  • fmt.Printf("描述: %s\n", cveInfo.Description) *
  • fmt.Printf("影响的产品数量: %d\n", len(cveInfo.AffectedCPEs))
  • for i, product := range cveInfo.AffectedCPEs[:3] { // 只显示前3个
  • fmt.Printf(" %d. %s\n", i+1, product)
  • }
  • } else {
  • fmt.Println("未找到此CVE的信息")
  • }
  • ``` *
  • 注意事项:
  • - 需要预先初始化数据源,通常是通过DownloadAllNVDData完成
  • - CVE ID的格式应符合标准(CVE-YYYY-NNNNN),将自动进行格式标准化
  • - 返回的信息完整度取决于数据源中可用的数据
  • - 某些较新或较罕见的CVE可能缺乏完整信息

func NewCVEReference

func NewCVEReference(cveID string) *CVEReference

NewCVEReference 创建一个新的CVE引用 输入:

  • cveID: string 类型,CVE的唯一标识符,例如 "CVE-2021-44228"

输出:

  • *CVEReference: 返回初始化的CVE引用对象,包含空的References和AffectedCPEs切片, 以及初始化的Metadata映射,PublishedDate和LastModifiedDate设置为当前时间

示例:

cve := NewCVEReference("CVE-2021-44228")
cve.Description = "Log4j远程代码执行漏洞"
cve.SetSeverity(10.0) // 设置为Critical级别

func QueryByProduct

func QueryByProduct(cves []*CVEReference, vendor, product string, version string) []*CVEReference

QueryByProduct 根据产品信息查询相关CVE 输入:

  • cves: []*CVEReference 类型,CVE引用对象的切片
  • vendor: string 类型,供应商名称,不区分大小写,空字符串表示匹配任何供应商
  • product: string 类型,产品名称,不区分大小写,空字符串表示匹配任何产品
  • version: string 类型,产品版本,区分大小写,空字符串表示匹配任何版本,"*"也表示任何版本

输出:

  • []*CVEReference: 返回匹配的CVE引用对象的切片

行为:

  • 解析每个CVE的受影响CPE列表
  • 支持解析CPE 2.2和CPE 2.3格式
  • 根据供应商、产品名和版本进行匹配过滤
  • 对于每个CVE,一旦发现一个匹配的CPE,便立即添加到结果中并跳过该CVE的其余CPE,避免重复
  • 匹配时vendor和product不区分大小写,但version区分大小写
  • 使用scagogogo/cve库对CVE ID进行标准化和验证

示例:

cves := []*CVEReference{...} // 从数据源加载的CVE列表

// 查找影响Apache Log4j的所有CVE
apacheLog4jCVEs := QueryByProduct(cves, "apache", "log4j", "")

// 查找影响特定版本的CVE
versionCVEs := QueryByProduct(cves, "apache", "log4j", "2.0")

// 查找特定供应商的所有产品漏洞
vendorCVEs := QueryByProduct(cves, "apache", "", "")

func (*CVEReference) AddAffectedCPE

func (cve *CVEReference) AddAffectedCPE(cpeURI string)

AddAffectedCPE 添加一个受影响的CPE 输入:

  • cpeURI: string 类型,要添加的CPE URI,支持CPE 2.2格式(cpe:/)或CPE 2.3格式(cpe:2.3:) 例如:"cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*" 或 "cpe:/a:apache:log4j:2.0"

输出:

  • 无返回值,直接修改CVEReference对象

行为:

  • 如果CPE已存在于AffectedCPEs列表中,则不会重复添加
  • 添加CPE后,会自动更新LastModifiedDate为当前时间

示例:

cve := NewCVEReference("CVE-2021-44228")
cve.AddAffectedCPE("cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*")

func (*CVEReference) AddReference

func (cve *CVEReference) AddReference(reference string)

AddReference 添加一个参考链接 输入:

输出:

  • 无返回值,直接修改CVEReference对象

行为:

  • 如果参考链接已存在于References列表中,则不会重复添加
  • 添加链接后,会自动更新LastModifiedDate为当前时间

示例:

cve := NewCVEReference("CVE-2021-44228")
cve.AddReference("https://nvd.nist.gov/vuln/detail/CVE-2021-44228")
cve.AddReference("https://www.cve.org/CVERecord?id=CVE-2021-44228")

func (*CVEReference) GetMetadata

func (cve *CVEReference) GetMetadata(key string) (interface{}, bool)

GetMetadata 获取元数据 输入:

  • key: string 类型,要获取的元数据键名

输出:

  • interface{}: 返回与键关联的值,如果键不存在则为nil
  • bool: 指示键是否存在 true - 键存在 false - 键不存在

示例:

cve := NewCVEReference("CVE-2021-44228")
cve.SetMetadata("exploitAvailable", true)

value, exists := cve.GetMetadata("exploitAvailable")
if exists {
  isExploitable := value.(bool) // 将返回true
}

_, notExists := cve.GetMetadata("nonExistentKey")
// notExists将为false

func (*CVEReference) RemoveAffectedCPE

func (cve *CVEReference) RemoveAffectedCPE(cpeURI string) bool

RemoveAffectedCPE 移除一个受影响的CPE 输入:

  • cpeURI: string 类型,要移除的CPE URI

输出:

  • bool: 移除操作是否成功 true - 找到并移除了指定的CPE false - 未找到指定的CPE,无需移除

行为:

  • 成功移除CPE后,会自动更新LastModifiedDate为当前时间
  • 如果移除成功,受影响的CPE列表长度将减少1

示例:

cve := NewCVEReference("CVE-2021-44228")
cve.AddAffectedCPE("cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*")
removed := cve.RemoveAffectedCPE("cpe:2.3:a:apache:log4j:2.0:*:*:*:*:*:*:*") // 返回 true
notRemoved := cve.RemoveAffectedCPE("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*") // 返回 false

func (*CVEReference) RemoveMetadata

func (cve *CVEReference) RemoveMetadata(key string) bool

RemoveMetadata 移除元数据 输入:

  • key: string 类型,要移除的元数据键名

输出:

  • bool: 移除操作是否成功 true - 键存在并被成功移除 false - 键不存在,无需移除

行为:

  • 成功移除元数据后,会自动更新LastModifiedDate为当前时间

示例:

cve := NewCVEReference("CVE-2021-44228")
cve.SetMetadata("exploitAvailable", true)

removed := cve.RemoveMetadata("exploitAvailable") // 返回true
notRemoved := cve.RemoveMetadata("nonExistentKey") // 返回false

func (*CVEReference) SetMetadata

func (cve *CVEReference) SetMetadata(key string, value interface{})

SetMetadata 设置元数据 输入:

  • key: string 类型,元数据的键名
  • value: interface{} 类型,元数据的值,可以是任意类型

输出:

  • 无返回值,直接修改CVEReference对象的Metadata映射

行为:

  • 如果键已存在,将覆盖原有值
  • 设置后,会自动更新LastModifiedDate为当前时间

示例:

cve := NewCVEReference("CVE-2021-44228")
cve.SetMetadata("exploitAvailable", true)
cve.SetMetadata("patchDate", "2021-12-10")
cve.SetMetadata("affectedVersions", []string{"2.0", "2.1", "2.2"})

func (*CVEReference) SetSeverity

func (cve *CVEReference) SetSeverity(cvssScore float64)

SetSeverity 设置CVE的严重性级别 输入:

  • cvssScore: float64 类型,CVE的CVSS评分,取值范围为0.0-10.0

输出:

  • 无返回值,直接修改CVEReference对象的CVSSScore和Severity字段

行为:

  • 根据CVSS评分自动设置对应的严重性级别:
  • 9.0-10.0: "Critical" (危急)
  • 7.0-8.9: "High" (高危)
  • 4.0-6.9: "Medium" (中危)
  • 0.0-3.9: "Low" (低危)
  • 设置后,会自动更新LastModifiedDate为当前时间

示例:

cve := NewCVEReference("CVE-2021-44228")
cve.SetSeverity(10.0) // 设置为Critical级别
cve.SetSeverity(5.5)  // 设置为Medium级别
cve.SetSeverity(2.0)  // 设置为Low级别

type CacheSettings

type CacheSettings struct {
	// 是否启用缓存
	Enabled bool

	// 缓存目录
	Directory string

	// 缓存过期时间(小时)
	ExpiryHours int

	// 缓存文件名模板
	FileNameTemplate string
}

CacheSettings 缓存设置

type Component

type Component interface {
	// String 返回组件的字符串表示
	String() string
	// IsANY 判断组件是否为ANY值
	IsANY() bool
	// IsNA 判断组件是否为NA值
	IsNA() bool
	// IsSet 判断组件是否设置了有效值(非ANY/NA/空)
	IsSet() bool
	// Normalize 标准化组件值
	Normalize() string
}

Component 接口定义CPE组件类型的通用行为

type DataSourceAuth

type DataSourceAuth struct {
	// API密钥
	APIKey string

	// 用户名
	Username string

	// 密码
	Password string

	// 认证令牌
	Token string

	// 自定义头信息
	Headers map[string]string
}

DataSourceAuth 数据源认证信息

type DataSourceType

type DataSourceType string

DataSourceType 表示数据源类型

const (
	// DataSourceNVD NVD数据源
	DataSourceNVD DataSourceType = "NVD"

	// DataSourceMITRE MITRE数据源
	DataSourceMITRE DataSourceType = "MITRE"

	// DataSourceGitHub GitHub安全公告
	DataSourceGitHub DataSourceType = "GitHub"

	// DataSourceRedHatCVE RedHat CVE数据库
	DataSourceRedHatCVE DataSourceType = "RedHat"

	// DataSourceOWASP OWASP数据源
	DataSourceOWASP DataSourceType = "OWASP"

	// DataSourceCustom 自定义数据源
	DataSourceCustom DataSourceType = "Custom"
)

type Edition

type Edition string

*

  • Edition 表示CPE中的版本类型组件 *
  • 在CPE规范中,Edition表示产品的版本类型或发行类型,如"SP1"(Service Pack 1)、
  • "企业版"、"专业版"等。Edition也可以使用特殊值"*"(任意版本类型)或"-"(不适用)。 *
  • 版本类型与具体版本号(Version)不同,它描述的是产品的发行类型而非版本号。
  • 在CPE 2.3规范中,Edition字段部分功能已被更精细的SoftwareEdition字段取代,
  • 但为了向后兼容仍然保留。 *
  • 示例:
  • ```go
  • // 创建一个表示Windows 10专业版的CPE
  • win10ProCPE := &cpe.CPE{
  • Part: *cpe.PartOperationSystem,
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • Edition: cpe.Edition("pro"),
  • } *
  • // 使用通配符匹配任意版本类型
  • windowsAnyCPE := &cpe.CPE{
  • Part: *cpe.PartOperationSystem,
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Edition: cpe.Edition("*"), // 匹配任意版本类型
  • } *
  • // 创建搜索条件,查找特定版本类型的产品
  • searchCriteria := &cpe.CPE{
  • Edition: cpe.Edition("enterprise"),
  • }
  • options := cpe.DefaultMatchOptions()
  • results := cpe.Search(cpeList, searchCriteria, options)
  • ```

func (Edition) IsANY

func (e Edition) IsANY() bool

IsANY 判断Edition是否为ANY值

func (Edition) IsNA

func (e Edition) IsNA() bool

IsNA 判断Edition是否为NA值

func (Edition) IsSet

func (e Edition) IsSet() bool

IsSet 判断Edition是否设置了有效值

func (Edition) Normalize

func (e Edition) Normalize() string

Normalize 标准化Edition值

func (Edition) String

func (e Edition) String() string

String 返回Edition的字符串表示

type ErrorType

type ErrorType int

*

  • ErrorType 表示CPE操作过程中可能出现的错误类型枚举 *
  • 这个枚举用于区分不同种类的CPE错误,便于错误处理和日志记录。
  • 每种错误类型对应特定的错误情况,使用常量定义便于代码维护。
const (
	// ErrorTypeParsingFailed 表示CPE字符串解析失败的错误类型
	ErrorTypeParsingFailed ErrorType = iota

	// ErrorTypeInvalidFormat 表示CPE格式无效的错误类型
	ErrorTypeInvalidFormat

	// ErrorTypeInvalidPart 表示CPE部件值无效的错误类型
	ErrorTypeInvalidPart

	// ErrorTypeInvalidAttribute 表示CPE属性值无效的错误类型
	ErrorTypeInvalidAttribute

	// ErrorTypeNotFound 表示未找到请求的资源或对象的错误类型
	ErrorTypeNotFound

	// ErrorTypeOperationFailed 表示CPE相关操作执行失败的错误类型
	ErrorTypeOperationFailed
)

type Expression

type Expression interface {
	/**
	 * Type 返回表达式的类型
	 *
	 * @return ExpressionType 表达式类型,可以是CPE、AND、OR或NOT
	 */
	Type() ExpressionType

	/**
	 * Evaluate 评估表达式是否匹配目标CPE
	 *
	 * @param target *CPE 要匹配的目标CPE
	 * @return bool 如果表达式匹配目标CPE返回true,否则返回false
	 */
	Evaluate(target *CPE) bool

	/**
	 * String 返回表达式的字符串表示
	 *
	 * @return string 表达式的字符串形式,可用于日志记录或调试
	 */
	String() string
}

*

  • Expression CPE适用性语言表达式接口 *
  • 这个接口定义了CPE适用性语言中表达式的共同行为。
  • 所有类型的表达式(单个CPE、AND、OR、NOT)都实现了这个接口,
  • 提供了获取表达式类型、评估表达式和字符串表示的方法。

func ParseExpression

func ParseExpression(expr string) (Expression, error)

*

  • ParseExpression 解析CPE适用性语言表达式 *
  • CPE适用性语言允许通过逻辑表达式组合多个CPE,表达复杂的匹配条件。
  • 支持的表达式类型包括:
  • - 单个CPE表达式: "cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"
  • - AND逻辑组合: "AND(expr1, expr2, ...)"
  • - OR逻辑组合: "OR(expr1, expr2, ...)"
  • - NOT逻辑求反: "NOT(expr)" *
  • @param expr 要解析的表达式字符串
  • @return (Expression, error) 成功时返回解析后的表达式对象,失败时返回nil和错误 *
  • @error 当表达式格式无效时返回错误
  • @error 当子表达式解析失败时返回错误 *
  • 示例:
  • ```go
  • // 解析单个CPE表达式
  • expr1, err := cpe.ParseExpression("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
  • if err != nil {
  • log.Fatalf("解析表达式失败: %v", err)
  • } *
  • // 解析OR表达式
  • orExpr, err := cpe.ParseExpression("OR(cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*, cpe:2.3:a:microsoft:windows:11:*:*:*:*:*:*:*)")
  • if err != nil {
  • log.Fatalf("解析OR表达式失败: %v", err)
  • } *
  • // 解析AND表达式
  • andExpr, err := cpe.ParseExpression("AND(cpe:2.3:a:microsoft:*:*:*:*:*:*:*:*:*, cpe:2.3:a:*:windows:*:*:*:*:*:*:*:*)")
  • if err != nil {
  • log.Fatalf("解析AND表达式失败: %v", err)
  • } *
  • // 解析NOT表达式
  • notExpr, err := cpe.ParseExpression("NOT(cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*)")
  • if err != nil {
  • log.Fatalf("解析NOT表达式失败: %v", err)
  • } *
  • // 评估表达式
  • targetCPE, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:11:*:*:*:*:*:*:*")
  • fmt.Println("Windows 11匹配OR表达式:", orExpr.Evaluate(targetCPE))
  • // 输出: Windows 11匹配OR表达式: true
  • ```

type ExpressionType

type ExpressionType int

ExpressionType 表达式类型

const (
	// ExpressionTypeCPE 单个CPE匹配表达式
	ExpressionTypeCPE ExpressionType = iota

	// ExpressionTypeAND 逻辑AND表达式
	ExpressionTypeAND

	// ExpressionTypeOR 逻辑OR表达式
	ExpressionTypeOR

	// ExpressionTypeNOT 逻辑NOT表达式
	ExpressionTypeNOT
)

type FieldMatchOption

type FieldMatchOption struct {
	// 匹配权重 (0.0-1.0)
	Weight float64

	// 是否必须匹配此字段
	Required bool

	// 匹配方法
	MatchMethod string
}

FieldMatchOption 定义字段特定的匹配选项

type FileStorage

type FileStorage struct {
	// contains filtered or unexported fields
}

FileStorage 是一个基于文件系统的存储实现

func NewFileStorage

func NewFileStorage(baseDir string, useCache bool) (*FileStorage, error)

*

  • NewFileStorage 创建基于文件系统的CPE数据存储实例 *
  • 此函数会在指定的基础目录下创建必要的子目录结构,包括cpes、cves、dictionary和metadata文件夹,
  • 用于存储不同类型的数据。还可以选择是否启用内存缓存以提高性能。 *
  • @param baseDir 存储数据的基础目录路径,如果不存在会自动创建
  • @param useCache 是否使用内存缓存来提高读取性能
  • @return (*FileStorage, error) 成功时返回FileStorage实例指针,失败时返回nil和错误 *
  • @error 当无法创建基础目录或子目录时,返回错误
  • @error 当启用缓存但无法初始化缓存时,返回错误 *
  • 示例:
  • ```go
  • // 创建临时目录用于存储CPE数据
  • tempDir, err := os.MkdirTemp("", "cpe-storage-*")
  • if err != nil {
  • log.Fatalf("创建临时目录失败: %v", err)
  • }
  • defer os.RemoveAll(tempDir) // 在程序结束时清理 *
  • // 创建带缓存的文件存储
  • storage, err := cpe.NewFileStorage(tempDir, true)
  • if err != nil {
  • log.Fatalf("创建存储失败: %v", err)
  • }
  • defer storage.Close() // 确保资源正确释放 *
  • // 现在可以使用storage进行CPE的存储和检索操作
  • ```

func (*FileStorage) AdvancedSearchCPE

func (f *FileStorage) AdvancedSearchCPE(criteria *CPE, options *AdvancedMatchOptions) ([]*CPE, error)

AdvancedSearchCPE 高级搜索CPE

func (*FileStorage) CPEFilePath

func (fs *FileStorage) CPEFilePath(id string) string

CPEFilePath 根据CPE ID获取CPE文件路径

func (*FileStorage) CVEFilePath

func (fs *FileStorage) CVEFilePath(id string) string

CVEFilePath 根据CVE ID获取CVE文件路径

func (*FileStorage) Close

func (fs *FileStorage) Close() error

Close 关闭存储连接

func (*FileStorage) DeleteCPE

func (f *FileStorage) DeleteCPE(uri string) error

DeleteCPE 删除一个CPE记录

func (*FileStorage) DeleteCVE

func (fs *FileStorage) DeleteCVE(cveID string) error

DeleteCVE 删除CVE信息

func (*FileStorage) DictionaryFilePath

func (fs *FileStorage) DictionaryFilePath() string

DictionaryFilePath 获取字典文件路径

func (*FileStorage) FindCPEsByCVE

func (fs *FileStorage) FindCPEsByCVE(cveID string) ([]*CPE, error)

FindCPEsByCVE 查找与CVE关联的CPE

func (*FileStorage) FindCVEsByCPE

func (fs *FileStorage) FindCVEsByCPE(cpe *CPE) ([]*CVEReference, error)

FindCVEsByCPE 查找与CPE关联的CVE

func (*FileStorage) Initialize

func (fs *FileStorage) Initialize() error

Initialize 初始化存储

func (*FileStorage) MetadataFilePath

func (fs *FileStorage) MetadataFilePath(key string) string

MetadataFilePath 根据键获取元数据文件路径

func (*FileStorage) RetrieveCPE

func (fs *FileStorage) RetrieveCPE(id string) (*CPE, error)

*

  • RetrieveCPE 根据CPE URI检索CPE对象 *
  • 此方法首先尝试从内存缓存(如果启用)中获取CPE,缓存未命中时则从文件系统读取CPE数据。
  • 检索到的CPE会被添加到缓存中(如果启用缓存)以加速后续访问。 *
  • @param id CPE URI,作为检索CPE的唯一标识符,如"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"
  • @return (*CPE, error) 成功时返回检索到的CPE结构体指针,失败时返回nil和错误 *
  • @error 当CPE不存在时,返回ErrNotFound
  • @error 当无法读取文件或解析JSON数据时,返回相应错误 *
  • 示例:
  • ```go
  • // 以Windows 10的CPE URI为例
  • cpeURI := "cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*" *
  • // 从存储中检索CPE
  • winCPE, err := storage.RetrieveCPE(cpeURI)
  • if err != nil {
  • if err == cpe.ErrNotFound {
  • log.Printf("CPE不存在: %s", cpeURI)
  • } else {
  • log.Fatalf("检索CPE失败: %v", err)
  • }
  • } else {
  • fmt.Printf("成功检索到CPE: %s (厂商: %s, 产品: %s)\n",
  • cpeURI, winCPE.Vendor, winCPE.ProductName)
  • }
  • ```

func (*FileStorage) RetrieveCVE

func (fs *FileStorage) RetrieveCVE(cveID string) (*CVEReference, error)

RetrieveCVE 查询CVE

func (*FileStorage) RetrieveDictionary

func (fs *FileStorage) RetrieveDictionary() (*CPEDictionary, error)

RetrieveDictionary 检索CPE字典

func (*FileStorage) RetrieveModificationTimestamp

func (fs *FileStorage) RetrieveModificationTimestamp(key string) (time.Time, error)

RetrieveModificationTimestamp 检索最后修改时间

func (*FileStorage) SearchCPE

func (f *FileStorage) SearchCPE(criteria *CPE, options *MatchOptions) ([]*CPE, error)

*

  • SearchCPE 根据条件搜索CPE记录 *
  • 此方法允许根据指定的查询条件和选项搜索CPE数据库。
  • 可以搜索CPE的各种属性,如供应商名称、产品名称或版本号。 *
  • @param criteria *CPE 搜索条件,包含要匹配的CPE字段,如果为nil则返回所有CPE
  • @param options *MatchOptions 匹配选项,控制匹配行为,如忽略版本或使用正则表达式
  • @return ([]*CPE, error) 成功时返回匹配的CPE列表,失败时返回nil和错误 *
  • @error 当读取目录或文件失败时,返回相应错误
  • @error 当解析CPE数据失败时,返回相应错误 *
  • 示例:
  • ```go
  • // 搜索所有Microsoft的产品
  • criteria := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • } *
  • // 设置匹配选项,忽略版本匹配
  • options := &cpe.MatchOptions{
  • IgnoreVersion: true,
  • } *
  • // 执行搜索
  • results, err := storage.SearchCPE(criteria, options)
  • if err != nil {
  • log.Fatalf("搜索CPE失败: %v", err)
  • } *
  • // 显示搜索结果
  • fmt.Printf("找到 %d 个匹配的CPE:\n", len(results))
  • for i, cpeItem := range results {
  • fmt.Printf("%d. %s (产品: %s, 版本: %s)\n",
  • i+1, cpeItem.GetURI(), cpeItem.ProductName, cpeItem.Version)
  • } *
  • // 搜索所有CPE
  • allCPEs, err := storage.SearchCPE(nil, nil)
  • if err != nil {
  • log.Fatalf("获取所有CPE失败: %v", err)
  • }
  • fmt.Printf("总共有 %d 个CPE记录\n", len(allCPEs))
  • ```

func (*FileStorage) SearchCVE

func (fs *FileStorage) SearchCVE(query string, options *SearchOptions) ([]*CVEReference, error)

SearchCVE 搜索CVE

func (*FileStorage) StoreCPE

func (fs *FileStorage) StoreCPE(cpe *CPE) error

StoreCPE 存储单个CPE

func (*FileStorage) StoreCVE

func (fs *FileStorage) StoreCVE(cve *CVEReference) error

StoreCVE 存储CVE

func (*FileStorage) StoreDictionary

func (fs *FileStorage) StoreDictionary(dict *CPEDictionary) error

*

  • StoreDictionary 存储CPE字典 *
  • 此方法将整个CPE字典序列化为JSON并存储到文件系统中。如果启用了缓存,
  • 也会同时更新内存缓存。还会更新字典的最后修改时间戳。 *
  • @param dict 要存储的CPE字典,包含一组CPE项和元数据
  • @return error 成功时返回nil,失败时返回错误 *
  • @error 当参数为nil时,返回ErrInvalidData
  • @error 当序列化字典失败时,返回错误
  • @error 当写入文件失败时,返回错误
  • @error 当更新缓存失败时,返回错误 *
  • 示例:
  • ```go
  • // 创建一个新的CPE字典
  • dictionary := &cpe.CPEDictionary{
  • GeneratedAt: time.Now(),
  • SchemaVersion: "2.3",
  • Items: make([]*cpe.CPEItem, 0),
  • } *
  • // 添加CPE项到字典
  • windowsCPE, _ := cpe.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*") *
  • // 创建Windows 10的字典项
  • windowsItem := &cpe.CPEItem{
  • Name: windowsCPE.Cpe23,
  • Title: "Microsoft Windows 10",
  • CPE: windowsCPE,
  • References: []cpe.Reference{
  • {
  • URL: "https://www.microsoft.com/windows",
  • Type: "vendor",
  • },
  • },
  • } *
  • // 添加到字典
  • dictionary.Items = append(dictionary.Items, windowsItem) *
  • // 存储字典
  • err := storage.StoreDictionary(dictionary)
  • if err != nil {
  • log.Fatalf("存储CPE字典失败: %v", err)
  • } *
  • fmt.Printf("成功存储包含 %d 条CPE记录的字典\n", len(dictionary.Items))
  • ```

func (*FileStorage) StoreModificationTimestamp

func (fs *FileStorage) StoreModificationTimestamp(key string, timestamp time.Time) error

StoreModificationTimestamp 存储最后修改时间

func (*FileStorage) UpdateCPE

func (f *FileStorage) UpdateCPE(cpe *CPE) error

UpdateCPE 更新一个CPE记录

func (*FileStorage) UpdateCVE

func (fs *FileStorage) UpdateCVE(cve *CVEReference) error

UpdateCVE 更新CVE信息

type Language

type Language string

*

  • Language 表示CPE中的语言组件 *
  • 在CPE规范中,Language用于标识软件的语言版本。通常使用ISO 639-2标准的语言代码:
  • 例如"zh"(中文)、"en"(英文)、"fr"(法语)等。Language也可以使用特殊值"*"(任意语言)
  • 或"-"(不适用)。 *
  • Language字段对于区分同一软件的不同语言版本非常重要,因为不同语言版本可能具有
  • 不同的安全漏洞或兼容性问题。 *
  • 示例:
  • ```go
  • // 创建一个表示中文版Microsoft Office的CPE
  • officeZhCPE := &cpe.CPE{
  • Part: *cpe.PartApplication,
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("office"),
  • Version: cpe.Version("2019"),
  • Language: cpe.Language("zh"),
  • } *
  • // 使用特殊值匹配任意语言版本
  • officeAnyCPE := &cpe.CPE{
  • Part: *cpe.PartApplication,
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("office"),
  • Language: cpe.Language("*"), // 匹配任意语言
  • } *
  • // 创建搜索条件,查找特定语言的产品
  • searchCriteria := &cpe.CPE{
  • Language: cpe.Language("ja"), // 查找日语版本
  • }
  • options := cpe.DefaultMatchOptions()
  • results := cpe.Search(cpeList, searchCriteria, options)
  • ```

func (Language) IsANY

func (l Language) IsANY() bool

IsANY 判断Language是否为ANY值

func (Language) IsNA

func (l Language) IsNA() bool

IsNA 判断Language是否为NA值

func (Language) IsSet

func (l Language) IsSet() bool

IsSet 判断Language是否设置了有效值

func (Language) Normalize

func (l Language) Normalize() string

Normalize 标准化Language值

func (Language) String

func (l Language) String() string

String 返回Language的字符串表示

type MatchOptions

type MatchOptions struct {
	// 是否忽略版本匹配
	// 设为true时版本号不参与匹配判断,适用于只需比较产品名称或供应商的场景
	IgnoreVersion bool

	// 是否允许子版本匹配
	// 设为true时,查询版本"1.0"可匹配"1.0"、"1.0.1"、"1.0.2"等所有子版本
	// 仅当IgnoreVersion为false且VersionRange为false时有效
	AllowSubVersions bool

	// 使用正则表达式匹配
	// 设为true时,Vendor、ProductName等字符串字段将使用正则表达式进行匹配
	// 注意:正则表达式匹配会降低性能,大规模匹配时慎用
	UseRegex bool

	// 比较版本范围而不是精确匹配
	// 设为true时,将使用MinVersion和MaxVersion定义的版本范围进行匹配
	// 此选项优先于AllowSubVersions
	VersionRange bool

	// 最小版本(含)
	// 指定版本范围的下限,当VersionRange为true时生效
	// 匹配时CPE版本必须大于或等于此版本
	MinVersion string

	// 最大版本(含)
	// 指定版本范围的上限,当VersionRange为true时生效
	// 匹配时CPE版本必须小于或等于此版本
	MaxVersion string
}

*

  • MatchOptions 匹配选项结构体 *
  • 用于配置CPE匹配过程中的各种行为选项,包括版本匹配逻辑、正则表达式支持等。
  • 此结构体可用于精细控制Search和matchCPE函数的匹配行为。 *
  • 注意事项:
  • - 启用正则表达式会对性能有一定影响,大规模CPE集合时要谨慎使用
  • - 版本范围和子版本匹配不能同时生效,启用VersionRange会优先于AllowSubVersions *
  • 示例:
  • ```go
  • // 创建匹配选项,忽略版本匹配
  • options := &cpe.MatchOptions{
  • IgnoreVersion: true,
  • } *
  • // 创建匹配选项,使用版本范围匹配
  • options := &cpe.MatchOptions{
  • VersionRange: true,
  • MinVersion: "2.0",
  • MaxVersion: "3.5",
  • }
  • ```

func DefaultMatchOptions

func DefaultMatchOptions() *MatchOptions

*

  • DefaultMatchOptions 返回默认匹配选项 *
  • 创建并返回一个预设默认值的MatchOptions实例,用于简化匹配选项的创建过程。
  • 默认配置下:
  • - 会考虑版本匹配(IgnoreVersion = false)
  • - 允许子版本匹配(AllowSubVersions = true)
  • - 不使用正则表达式匹配(UseRegex = false)
  • - 不使用版本范围匹配(VersionRange = false) *
  • @return *MatchOptions 预设了默认值的匹配选项对象 *
  • 示例:
  • ```go
  • // 使用默认匹配选项
  • options := cpe.DefaultMatchOptions() *
  • // 在默认选项基础上修改
  • options := cpe.DefaultMatchOptions()
  • options.UseRegex = true
  • ``` *
  • 注意事项:
  • - 返回的是指针类型,可以直接修改其属性
  • - 在大多数简单匹配场景下,默认选项已经能满足需求

type MemoryStorage

type MemoryStorage struct {
	// contains filtered or unexported fields
}

MemoryStorage 是一个基于内存的存储实现

func NewMemoryStorage

func NewMemoryStorage() *MemoryStorage

NewMemoryStorage 创建一个新的内存存储

func (*MemoryStorage) AdvancedSearchCPE

func (ms *MemoryStorage) AdvancedSearchCPE(criteria *CPE, options *AdvancedMatchOptions) ([]*CPE, error)

AdvancedSearchCPE 高级搜索CPE

func (*MemoryStorage) Close

func (ms *MemoryStorage) Close() error

Close 关闭存储连接

func (*MemoryStorage) DeleteCPE

func (ms *MemoryStorage) DeleteCPE(id string) error

DeleteCPE 删除CPE

func (*MemoryStorage) DeleteCVE

func (ms *MemoryStorage) DeleteCVE(cveID string) error

DeleteCVE 删除CVE信息

func (*MemoryStorage) FindCPEsByCVE

func (ms *MemoryStorage) FindCPEsByCVE(cveID string) ([]*CPE, error)

FindCPEsByCVE 查找与CVE关联的CPE

func (*MemoryStorage) FindCVEsByCPE

func (ms *MemoryStorage) FindCVEsByCPE(cpe *CPE) ([]*CVEReference, error)

FindCVEsByCPE 查找与CPE关联的CVE

func (*MemoryStorage) Initialize

func (ms *MemoryStorage) Initialize() error

Initialize 初始化存储

func (*MemoryStorage) RetrieveCPE

func (ms *MemoryStorage) RetrieveCPE(id string) (*CPE, error)

RetrieveCPE 根据ID检索CPE

func (*MemoryStorage) RetrieveCVE

func (ms *MemoryStorage) RetrieveCVE(cveID string) (*CVEReference, error)

RetrieveCVE 根据CVE ID检索CVE信息

func (*MemoryStorage) RetrieveDictionary

func (ms *MemoryStorage) RetrieveDictionary() (*CPEDictionary, error)

RetrieveDictionary 检索CPE字典

func (*MemoryStorage) RetrieveModificationTimestamp

func (ms *MemoryStorage) RetrieveModificationTimestamp(key string) (time.Time, error)

RetrieveModificationTimestamp 检索最后修改时间

func (*MemoryStorage) SearchCPE

func (ms *MemoryStorage) SearchCPE(criteria *CPE, options *MatchOptions) ([]*CPE, error)

SearchCPE 搜索CPE

func (*MemoryStorage) SearchCVE

func (ms *MemoryStorage) SearchCVE(query string, options *SearchOptions) ([]*CVEReference, error)

SearchCVE 搜索CVE

func (*MemoryStorage) StoreCPE

func (ms *MemoryStorage) StoreCPE(cpe *CPE) error

StoreCPE 存储单个CPE

func (*MemoryStorage) StoreCVE

func (ms *MemoryStorage) StoreCVE(cve *CVEReference) error

StoreCVE 存储CVE信息

func (*MemoryStorage) StoreDictionary

func (ms *MemoryStorage) StoreDictionary(dict *CPEDictionary) error

StoreDictionary 存储CPE字典

func (*MemoryStorage) StoreModificationTimestamp

func (ms *MemoryStorage) StoreModificationTimestamp(key string, timestamp time.Time) error

StoreModificationTimestamp 存储最后修改时间

func (*MemoryStorage) UpdateCPE

func (ms *MemoryStorage) UpdateCPE(cpe *CPE) error

UpdateCPE 更新CPE

func (*MemoryStorage) UpdateCVE

func (ms *MemoryStorage) UpdateCVE(cve *CVEReference) error

UpdateCVE 更新CVE信息

type MultiSourceVulnerabilitySearch

type MultiSourceVulnerabilitySearch struct {
	// 数据源列表
	Sources []*VulnDataSource

	// 并发级别
	ConcurrencyLevel int

	// 超时时间(秒)
	TimeoutSeconds int

	// 是否合并结果
	MergeResults bool
}

MultiSourceVulnerabilitySearch 多数据源漏洞搜索

func CreateDefaultMultiSourceSearch

func CreateDefaultMultiSourceSearch() *MultiSourceVulnerabilitySearch

CreateDefaultMultiSourceSearch 创建默认的多源搜索

func NewMultiSourceSearch

func NewMultiSourceSearch(sources []*VulnDataSource) *MultiSourceVulnerabilitySearch

NewMultiSourceSearch 创建新的多数据源搜索

func (*MultiSourceVulnerabilitySearch) SearchByCPE

func (ms *MultiSourceVulnerabilitySearch) SearchByCPE(cpe *CPE) ([]*CVEReference, error)

SearchByCPE 根据CPE在多个数据源中搜索

func (*MultiSourceVulnerabilitySearch) SearchByCVE

func (ms *MultiSourceVulnerabilitySearch) SearchByCVE(cveID string) ([]*CVEReference, error)

SearchByCVE 根据CVE ID在多个数据源中搜索

type NOTExpression

type NOTExpression struct {
	Expression Expression
}

NOTExpression 表示逻辑NOT表达式

func (*NOTExpression) Evaluate

func (e *NOTExpression) Evaluate(target *CPE) bool

Evaluate 评估表达式是否匹配目标CPE

func (*NOTExpression) String

func (e *NOTExpression) String() string

String 返回表达式的字符串表示

func (*NOTExpression) Type

func (e *NOTExpression) Type() ExpressionType

Type 返回表达式类型

type NVDCPEData

type NVDCPEData struct {
	// CPEDictionary 包含所有官方注册的CPE条目及其详细信息
	// 通过此字段可以获取特定CPE的标准化表示和元数据
	CPEDictionary *CPEDictionary

	// CPEMatchData 包含CPE与CVE之间的双向映射关系
	// 用于快速查找特定CPE关联的漏洞,或特定漏洞影响的产品
	CPEMatchData *CPEMatchData

	// DownloadTime 记录数据下载的时间戳
	// 可用于判断数据的新鲜度,决定是否需要更新
	DownloadTime time.Time
}

*

  • NVDCPEData 集成了从NVD获取的CPE和CVE关联数据 *
  • 此结构体封装了从美国国家漏洞数据库(NVD)获取的多种数据,包括CPE字典和CPE与CVE之间的映射关系。
  • 它为应用程序提供了一个统一的接口来获取漏洞信息,便于进行安全评估和漏洞管理。 *
  • 字段说明:
  • - CPEDictionary: CPE字典,包含所有正式注册的CPE条目及其详细信息
  • - CPEMatchData: CPE与CVE的映射关系数据,用于查找特定CPE相关的漏洞或特定漏洞影响的CPE
  • - DownloadTime: 数据下载的时间戳,便于判断数据的新鲜度 *
  • 使用示例:
  • ```go
  • // 下载NVD数据
  • options := cpe.DefaultNVDFeedOptions()
  • nvdData, err := cpe.DownloadAllNVDData(options)
  • if err != nil {
  • log.Fatalf("下载NVD数据失败: %v", err)
  • } *
  • // 查找特定CPE相关的CVE
  • windowsCPE, _ := cpe.ParseCpe23("cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*")
  • cves := nvdData.FindCVEsForCPE(windowsCPE)
  • fmt.Printf("找到%d个影响Windows 10的CVE\n", len(cves))
  • for i, cveID := range cves[:5] { // 只显示前5个
  • fmt.Printf("%d. %s\n", i+1, cveID)
  • } *
  • // 查找特定CVE影响的CPE
  • cveID := "CVE-2021-44228" // Log4Shell
  • affectedCPEs := nvdData.FindCPEsForCVE(cveID)
  • fmt.Printf("%s影响了%d个CPE\n", cveID, len(affectedCPEs)) *
  • // 获取数据下载时间
  • fmt.Printf("数据更新时间: %s\n", nvdData.DownloadTime.Format(time.RFC3339))
  • ``` *
  • 注意事项:
  • - NVD数据量较大,首次下载和处理可能需要较长时间
  • - 定期更新数据以获取最新的漏洞信息
  • - FindCVEsForCPE和FindCPEsForCVE方法支持模糊匹配,但可能不如精确匹配准确

func DownloadAllNVDData

func DownloadAllNVDData(options *NVDFeedOptions) (*NVDCPEData, error)

*

  • DownloadAllNVDData 下载并解析所有NVD数据 *
  • 此函数综合获取NVD的CPE字典和CPE匹配数据,提供完整的数据集供应用程序使用。
  • 它是获取全面NVD数据的便捷方法,避免分别调用多个下载函数。 *
  • 参数:
  • - options: NVDFeedOptions,配置下载选项,如缓存目录、HTTP客户端等 *
  • 返回:
  • - *NVDCPEData: 包含CPE字典和CPE匹配数据的综合结构
  • - error: 发生的错误,如下载失败、解析错误等,成功时为nil *
  • 使用示例:
  • ```go
  • options := cpe.DefaultNVDFeedOptions()
  • // 设置缓存目录和最大缓存期限
  • options.CacheDir = "./nvd_cache"
  • options.CacheMaxAge = 7 * 24 * time.Hour // 7天 *
  • // 下载所有NVD数据
  • fmt.Println("开始下载NVD数据...")
  • nvdData, err := cpe.DownloadAllNVDData(options)
  • if err != nil {
  • log.Fatalf("下载NVD数据失败: %v", err)
  • }
  • fmt.Println("NVD数据下载完成!") *
  • // 查找特定产品的漏洞
  • apacheTomcatCPE, _ := cpe.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0.0:*:*:*:*:*:*:*")
  • cves := nvdData.FindCVEsForCPE(apacheTomcatCPE)
  • fmt.Printf("发现Apache Tomcat 9.0.0存在%d个漏洞\n", len(cves)) *
  • // 查找指定漏洞影响的产品
  • heartbleedCVE := "CVE-2014-0160"
  • affectedCPEs := nvdData.FindCPEsForCVE(heartbleedCVE)
  • fmt.Printf("Heartbleed漏洞(CVE-2014-0160)影响了%d个产品\n", len(affectedCPEs))
  • ``` *
  • 注意事项:
  • - 此函数执行两次独立的下载操作,总下载时间可能较长
  • - 对于生产环境,建议定期(如每周)后台更新NVD数据
  • - 下载完成的数据可以持久化存储,以便多个应用程序共享使用
  • - 如果只需要特定类型的数据,可以单独调用DownloadAndParseCPEDict或DownloadAndParseCPEMatch

func (*NVDCPEData) EnrichCPEWithVulnerabilityData

func (data *NVDCPEData) EnrichCPEWithVulnerabilityData(cpe *CPE)

EnrichCPEWithVulnerabilityData 使用NVD数据丰富CPE信息

func (*NVDCPEData) FindCPEsForCVE

func (data *NVDCPEData) FindCPEsForCVE(cveID string) []*CPE

FindCPEsForCVE 查找与特定CVE相关的所有CPE

func (*NVDCPEData) FindCVEsForCPE

func (data *NVDCPEData) FindCVEsForCPE(cpe *CPE) []string

FindCVEsForCPE 查找与特定CPE相关的所有CVE

type NVDFeedOptions

type NVDFeedOptions struct {
	// CacheDir 缓存目录路径,用于存储下载的NVD数据Feed文件
	// 默认为系统临时目录下的"cpe-cache"子目录
	CacheDir string

	// CacheMaxAge 缓存最大有效期(小时)
	// 超过此时间后,缓存将被视为过期,需要重新下载数据
	// 默认为24小时
	CacheMaxAge int

	// MaxConcurrentDownloads 最大并发下载数
	// 控制同时进行的下载任务数量,避免过多并发请求导致资源耗尽或被服务器限制
	// 默认为3
	MaxConcurrentDownloads int

	// ShowProgress 是否显示进度信息
	// 设置为true时,下载过程中会在标准输出中显示进度信息
	// 默认为true
	ShowProgress bool

	// HTTPClient 用户自定义的HTTP客户端
	// 可配置超时时间、代理设置、传输参数等
	// 默认为带有60秒超时的标准HTTP客户端
	HTTPClient *http.Client
}

*

  • NVDFeedOptions 定义美国国家漏洞数据库(NVD)数据Feed的下载和处理选项 *
  • 该结构体包含配置NVD数据Feed获取过程的各项参数,包括缓存策略、并发控制、
  • 进度显示以及HTTP客户端自定义等。这些选项影响数据获取的效率、资源消耗和用户体验。 *
  • 字段说明:
  • - CacheDir: 缓存目录路径,用于存储下载的NVD数据Feed文件
  • - CacheMaxAge: 缓存有效期(小时),超过此时间将重新下载数据
  • - MaxConcurrentDownloads: 最大并发下载数,控制同时进行的下载任务数量
  • - ShowProgress: 是否显示下载进度信息
  • - HTTPClient: 自定义HTTP客户端,可设置超时、代理等参数 *
  • 使用示例:
  • ```go
  • // 使用默认选项
  • options := cpe.DefaultNVDFeedOptions() *
  • // 自定义选项
  • customOptions := &cpe.NVDFeedOptions{
  • CacheDir: "/tmp/my-nvd-cache",
  • CacheMaxAge: 48, // 缓存48小时有效
  • MaxConcurrentDownloads: 5, // 最多5个并发下载
  • ShowProgress: true,
  • HTTPClient: &http.Client{
  • Timeout: 120 * time.Second, // 设置2分钟超时
  • Transport: &http.Transport{
  • Proxy: http.ProxyFromEnvironment,
  • MaxIdleConns: 10,
  • IdleConnTimeout: 30 * time.Second,
  • },
  • },
  • } *
  • // 下载NVD数据
  • data, err := cpe.DownloadAllNVDData(customOptions)
  • if err != nil {
  • log.Fatalf("下载NVD数据失败: %v", err)
  • }
  • ``` *
  • 注意事项:
  • - 缓存目录需要有写入权限
  • - 网络环境不稳定时可能需要增加HTTP客户端的超时时间
  • - 较大的并发下载数可能导致NVD服务器拒绝请求,请谨慎设置

func DefaultNVDFeedOptions

func DefaultNVDFeedOptions() *NVDFeedOptions

*

  • DefaultNVDFeedOptions 返回配置了合理默认值的NVD Feed下载选项 *
  • 此函数创建并返回一个NVDFeedOptions结构体实例,其中所有字段都设置了适合大多数使用场景的默认值。
  • 用户可以在此基础上根据需要修改特定字段,避免手动设置所有参数的麻烦。 *
  • @return *NVDFeedOptions 配置了默认值的NVD Feed下载选项 *
  • 默认配置:
  • - CacheDir: 系统临时目录下的"cpe-cache"子目录
  • - CacheMaxAge: 24小时
  • - MaxConcurrentDownloads: 3
  • - ShowProgress: true
  • - HTTPClient: 带有60秒超时的标准HTTP客户端 *
  • 使用示例:
  • ```go
  • // 获取默认选项
  • options := cpe.DefaultNVDFeedOptions() *
  • // 只修改缓存相关设置,保留其他默认值
  • options.CacheDir = "/var/cache/nvd-data"
  • options.CacheMaxAge = 12 // 降低缓存有效期至12小时 *
  • // 使用修改后的选项下载数据
  • dict, err := cpe.DownloadAndParseCPEDict(options)
  • if err != nil {
  • log.Fatalf("下载CPE字典失败: %v", err)
  • }
  • ``` *
  • 注意事项:
  • - 返回的是指针类型,可以直接修改其字段值
  • - 默认HTTP客户端设置的超时时间为60秒,对于网络条件较差的环境可能需要增加

type ORExpression

type ORExpression struct {
	Expressions []Expression
}

ORExpression 表示逻辑OR表达式

func (*ORExpression) Evaluate

func (e *ORExpression) Evaluate(target *CPE) bool

Evaluate 评估表达式是否匹配目标CPE

func (*ORExpression) String

func (e *ORExpression) String() string

String 返回表达式的字符串表示

func (*ORExpression) Type

func (e *ORExpression) Type() ExpressionType

Type 返回表达式类型

type Part

type Part struct {
	// 单字符简称,在CPE URI中使用,如'a'、'h'、'o'
	ShortName string

	// 完整名称,如'Application'、'Hardware'、'Operation System'
	LongName string

	// 描述信息,提供关于该组件类型的附加说明
	Description string
}

*

  • Part 表示CPE标识中的组件类型 *
  • 在CPE规范中,Part表示产品类型,可以是应用程序、硬件或操作系统。
  • 这是CPE标识的第一个组成部分,用于区分不同种类的IT产品。 *
  • 属性:
  • - ShortName: 单字符简称,在CPE URI中使用,如'a'、'h'、'o'
  • - LongName: 完整名称,如'Application'、'Hardware'、'Operation System'
  • - Description: 描述信息,提供关于该组件类型的附加说明 *
  • 示例:
  • ```go
  • // 创建一个表示应用程序类型的CPE
  • appCPE := &cpe.CPE{
  • Part: *cpe.PartApplication, // 使用预定义的应用程序类型
  • Vendor: cpe.Vendor("adobe"),
  • ProductName: cpe.Product("acrobat_reader"),
  • } *
  • // 创建一个表示操作系统类型的CPE
  • osCPE := &cpe.CPE{
  • Part: *cpe.PartOperationSystem, // 使用预定义的操作系统类型
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • }
  • ```

func ParsePart

func ParsePart(s string) (Part, error)

ParsePart 解析Part字符串,返回对应的Part对象

func StringToPart

func StringToPart(s string) (*Part, error)

StringToPart 将字符串转换为Part类型

示例:

part := cpe.StringToPart("a") // PartApplication

func (Part) IsANY

func (p Part) IsANY() bool

IsANY 判断Part是否为ANY值

func (Part) IsNA

func (p Part) IsNA() bool

IsNA 判断Part是否为NA值

func (Part) IsSet

func (p Part) IsSet() bool

IsSet 判断Part是否设置了有效值

func (Part) Normalize

func (p Part) Normalize() string

Normalize 标准化Part值

type Product

type Product string

*

  • Product 表示CPE中的产品名称组件 *
  • 在CPE规范中,Product表示软件或硬件的具体产品名称,如"windows"、"office"、
  • "iphone"等。Product也可以使用特殊值"*"(任意产品)或"-"(不适用)。 *
  • 与其他CPE组件类似,产品名称在标准化过程中会被转换为小写,空格会被替换为下划线。 *
  • 示例:
  • ```go
  • // 创建一个表示Microsoft Office产品的CPE
  • officeCPE := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("office"),
  • Version: cpe.Version("2019"),
  • } *
  • // 搜索特定产品
  • searchCriteria := &cpe.CPE{
  • ProductName: cpe.Product("office"),
  • }
  • options := cpe.DefaultMatchOptions()
  • results := cpe.Search(cpeList, searchCriteria, options) *
  • // 使用正则表达式匹配产品名
  • options.UseRegex = true
  • regexCriteria := &cpe.CPE{
  • ProductName: cpe.Product("(word|excel|powerpoint)"),
  • }
  • ```

func (Product) IsANY

func (p Product) IsANY() bool

IsANY 判断Product是否为ANY值

func (Product) IsNA

func (p Product) IsNA() bool

IsNA 判断Product是否为NA值

func (Product) IsSet

func (p Product) IsSet() bool

IsSet 判断Product是否设置了有效值

func (Product) Normalize

func (p Product) Normalize() string

Normalize 标准化Product值

func (Product) String

func (p Product) String() string

String 返回Product的字符串表示

type Reference

type Reference struct {
	// 参考URL
	URL string `json:"url" xml:"href,attr" bson:"url"`

	// 参考类型,如"Vendor", "Advisory", "External"等
	Type string `json:"type" xml:"type" bson:"type"`
}

*

  • Reference 表示CPE项的参考信息 *
  • 每个Reference包含一个指向额外信息的URL和引用类型,
  • 通常指向供应商网站、文档或其他资源。

type Relation

type Relation int

Relation 表示两个CPE之间的匹配关系 按照 NISTIR 7696 CPE Name Matching 规范定义

const (
	// RelationDisjoint 表示两个CPE不相交,没有重叠
	RelationDisjoint Relation = iota

	// RelationSubset 表示源CPE是目标CPE的子集
	RelationSubset

	// RelationSuperset 表示源CPE是目标CPE的超集
	RelationSuperset

	// RelationEqual 表示两个CPE相等
	RelationEqual

	// RelationOverlap 表示两个CPE有重叠但不完全包含
	RelationOverlap

	// RelationUnknown 表示关系无法确定
	RelationUnknown
)

func CompareWFNRelation

func CompareWFNRelation(comparisons map[string]int) Relation

CompareWFNRelation 根据属性比较结果确定整体关系

func (Relation) String

func (r Relation) String() string

String 返回Relation的字符串表示

type SearchOptions

type SearchOptions struct {
	// 分页选项
	Offset int
	Limit  int

	// 排序字段
	SortBy string

	// 排序方向(true为升序,false为降序)
	SortAscending bool

	// 过滤条件
	Filters map[string]interface{}

	// 全文搜索查询
	FullTextQuery string

	// 是否包含已弃用的项
	IncludeDeprecated bool

	// 日期范围过滤
	DateStart *time.Time
	DateEnd   *time.Time

	// 最小CVSS评分
	MinCVSS float64

	// 最大CVSS评分
	MaxCVSS float64
}

SearchOptions 搜索选项

func NewSearchOptions

func NewSearchOptions() *SearchOptions

NewSearchOptions 创建默认搜索选项

功能描述:

  • 创建并初始化带有默认值的SearchOptions对象
  • 提供搜索操作的基础配置,包括分页、排序和过滤设置
  • 适用于需要搜索CPE或CVE数据时简化选项创建的场景

参数:

返回值:

  • *SearchOptions: 初始化后的搜索选项对象,包含以下默认值:
  • Offset: 0 (从第一条记录开始)
  • Limit: 100 (每页最多返回100条记录)
  • SortBy: "id" (默认按ID字段排序)
  • SortAscending: true (默认升序排列)
  • Filters: 空map (默认无过滤条件)
  • IncludeDeprecated: false (默认不包含已弃用项)

使用示例:

// 创建默认搜索选项
options := cpe.NewSearchOptions()

// 修改默认值以满足特定需求
options.Limit = 50
options.SortBy = "severity"
options.SortAscending = false
options.Filters["vendor"] = "microsoft"

// 使用选项进行搜索
results, err := storage.SearchCVE("windows", options)

线程安全:

  • 此函数是无状态的,可以在并发环境中安全调用

type Storage

type Storage interface {
	/**
	 * Initialize 初始化存储
	 *
	 * 该方法用于执行存储系统所需的初始化操作,如创建目录、建立连接、初始化表结构等。
	 * 在使用存储系统前应首先调用此方法。
	 *
	 * @return error 初始化过程中发生的错误,成功则返回nil
	 */
	Initialize() error

	/**
	 * Close 关闭存储连接
	 *
	 * 关闭与存储系统的连接,释放相关资源。使用完存储后应调用此方法。
	 *
	 * @return error 关闭过程中发生的错误,成功则返回nil
	 */
	Close() error

	/**
	 * StoreCPE 存储单个CPE对象
	 *
	 * 将CPE对象持久化到存储系统中。如果存储中已存在相同ID的CPE,
	 * 具体行为取决于实现(可能返回错误或覆盖现有记录)。
	 *
	 * @param cpe *CPE 要存储的CPE对象
	 * @return error 存储过程中发生的错误,成功则返回nil
	 */
	StoreCPE(cpe *CPE) error

	/**
	 * RetrieveCPE 根据ID检索CPE
	 *
	 * 从存储中检索指定ID的CPE对象。通常ID是CPE的URI表示形式。
	 *
	 * @param id string CPE的唯一标识符
	 * @return *CPE 检索到的CPE对象
	 * @return error 检索过程中发生的错误,如果未找到则返回ErrNotFound
	 */
	RetrieveCPE(id string) (*CPE, error)

	/**
	 * UpdateCPE 更新CPE
	 *
	 * 更新存储中已存在的CPE对象。如果指定ID的CPE不存在,则返回错误。
	 *
	 * @param cpe *CPE 包含更新信息的CPE对象
	 * @return error 更新过程中发生的错误,成功则返回nil
	 */
	UpdateCPE(cpe *CPE) error

	/**
	 * DeleteCPE 删除CPE
	 *
	 * 从存储中删除指定ID的CPE对象。
	 *
	 * @param id string 要删除的CPE的唯一标识符
	 * @return error 删除过程中发生的错误,成功则返回nil
	 */
	DeleteCPE(id string) error

	/**
	 * SearchCPE 搜索CPE
	 *
	 * 根据给定的条件和选项搜索匹配的CPE对象。
	 *
	 * @param criteria *CPE 搜索条件,包含要匹配的CPE属性
	 * @param options *MatchOptions 匹配选项,控制匹配行为
	 * @return []*CPE 匹配的CPE对象列表
	 * @return error 搜索过程中发生的错误,成功则返回nil
	 */
	SearchCPE(criteria *CPE, options *MatchOptions) ([]*CPE, error)

	/**
	 * AdvancedSearchCPE 高级搜索CPE
	 *
	 * 使用高级匹配选项搜索CPE对象,支持更复杂的匹配条件。
	 *
	 * @param criteria *CPE 搜索条件
	 * @param options *AdvancedMatchOptions 高级匹配选项
	 * @return []*CPE 匹配的CPE对象列表
	 * @return error 搜索过程中发生的错误,成功则返回nil
	 */
	AdvancedSearchCPE(criteria *CPE, options *AdvancedMatchOptions) ([]*CPE, error)

	/**
	 * StoreCVE 存储CVE信息
	 *
	 * 将CVE引用对象持久化到存储系统中。
	 *
	 * @param cve *CVEReference 要存储的CVE引用对象
	 * @return error 存储过程中发生的错误,成功则返回nil
	 */
	StoreCVE(cve *CVEReference) error

	/**
	 * RetrieveCVE 根据CVE ID检索CVE信息
	 *
	 * 从存储中检索指定ID的CVE引用对象。
	 *
	 * @param cveID string CVE的唯一标识符,如"CVE-2021-44228"
	 * @return *CVEReference 检索到的CVE引用对象
	 * @return error 检索过程中发生的错误,如果未找到则返回ErrNotFound
	 */
	RetrieveCVE(cveID string) (*CVEReference, error)

	/**
	 * UpdateCVE 更新CVE信息
	 *
	 * 更新存储中已存在的CVE引用对象。
	 *
	 * @param cve *CVEReference 包含更新信息的CVE引用对象
	 * @return error 更新过程中发生的错误,成功则返回nil
	 */
	UpdateCVE(cve *CVEReference) error

	/**
	 * DeleteCVE 删除CVE信息
	 *
	 * 从存储中删除指定ID的CVE引用对象。
	 *
	 * @param cveID string 要删除的CVE的唯一标识符
	 * @return error 删除过程中发生的错误,成功则返回nil
	 */
	DeleteCVE(cveID string) error

	/**
	 * SearchCVE 搜索CVE
	 *
	 * 根据查询字符串和搜索选项搜索匹配的CVE引用对象。
	 *
	 * @param query string 搜索查询字符串
	 * @param options *SearchOptions 搜索选项
	 * @return []*CVEReference 匹配的CVE引用对象列表
	 * @return error 搜索过程中发生的错误,成功则返回nil
	 */
	SearchCVE(query string, options *SearchOptions) ([]*CVEReference, error)

	/**
	 * FindCVEsByCPE 查找与CPE关联的CVE
	 *
	 * 查找影响指定CPE的所有CVE引用对象。
	 *
	 * @param cpe *CPE 目标CPE对象
	 * @return []*CVEReference 与指定CPE关联的CVE引用对象列表
	 * @return error 查找过程中发生的错误,成功则返回nil
	 */
	FindCVEsByCPE(cpe *CPE) ([]*CVEReference, error)

	/**
	 * FindCPEsByCVE 查找与CVE关联的CPE
	 *
	 * 查找受指定CVE影响的所有CPE对象。
	 *
	 * @param cveID string CVE的唯一标识符
	 * @return []*CPE 与指定CVE关联的CPE对象列表
	 * @return error 查找过程中发生的错误,成功则返回nil
	 */
	FindCPEsByCVE(cveID string) ([]*CPE, error)

	/**
	 * StoreDictionary 存储CPE字典
	 *
	 * 将CPE字典对象持久化到存储系统中。
	 *
	 * @param dict *CPEDictionary 要存储的CPE字典对象
	 * @return error 存储过程中发生的错误,成功则返回nil
	 */
	StoreDictionary(dict *CPEDictionary) error

	/**
	 * RetrieveDictionary 检索CPE字典
	 *
	 * 从存储中检索CPE字典对象。
	 *
	 * @return *CPEDictionary 检索到的CPE字典对象
	 * @return error 检索过程中发生的错误,如果未找到则返回ErrNotFound
	 */
	RetrieveDictionary() (*CPEDictionary, error)

	/**
	 * StoreModificationTimestamp 存储最后修改时间
	 *
	 * 记录特定键的最后修改时间戳,用于跟踪数据更新。
	 *
	 * @param key string 时间戳的键
	 * @param timestamp time.Time 时间戳值
	 * @return error 存储过程中发生的错误,成功则返回nil
	 */
	StoreModificationTimestamp(key string, timestamp time.Time) error

	/**
	 * RetrieveModificationTimestamp 检索最后修改时间
	 *
	 * 检索特定键的最后修改时间戳。
	 *
	 * @param key string 时间戳的键
	 * @return time.Time 检索到的时间戳
	 * @return error 检索过程中发生的错误,如果未找到则返回ErrNotFound
	 */
	RetrieveModificationTimestamp(key string) (time.Time, error)
}

*

  • Storage 定义了CPE和CVE数据的存储接口 *
  • 该接口提供了一组统一的方法来存储、检索、更新和搜索CPE和CVE数据,
  • 使得不同的存储实现(如文件存储、内存存储、数据库存储等)能够以一致的方式使用。 *
  • 示例:
  • ```go
  • // 创建文件存储
  • storage, err := cpe.NewFileStorage("/path/to/storage", true)
  • if err != nil {
  • log.Fatalf("无法创建存储: %v", err)
  • } *
  • // 初始化存储
  • if err := storage.Initialize(); err != nil {
  • log.Fatalf("初始化存储失败: %v", err)
  • } *
  • // 存储CPE
  • windowsCPE := &cpe.CPE{
  • Cpe23: "cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*",
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • }
  • if err := storage.StoreCPE(windowsCPE); err != nil {
  • log.Printf("存储CPE失败: %v", err)
  • } *
  • // 检索CPE
  • retrievedCPE, err := storage.RetrieveCPE(windowsCPE.GetURI())
  • if err != nil {
  • if errors.Is(err, cpe.ErrNotFound) {
  • log.Println("CPE不存在")
  • } else {
  • log.Printf("检索CPE失败: %v", err)
  • }
  • } *
  • // 使用完毕后关闭存储
  • defer storage.Close()
  • ```

type StorageManager

type StorageManager struct {
	// 主存储
	Primary Storage

	// 缓存存储
	Cache Storage

	// 是否启用缓存
	CacheEnabled bool

	// 缓存有效期(秒)
	CacheTTLSeconds int
}

StorageManager 存储管理器

func NewStorageManager

func NewStorageManager(primary Storage) *StorageManager

NewStorageManager 创建存储管理器

功能描述:

  • 创建并初始化StorageManager对象,用于管理CPE和CVE数据的存储操作
  • 支持主存储与缓存存储的分层架构,提高数据访问效率
  • 管理器会自动处理主存储和缓存存储之间的数据同步

参数:

  • primary Storage: 主存储接口实现,不能为nil,作为数据的持久化存储

返回值:

  • *StorageManager: 初始化后的存储管理器对象,包含以下默认设置:
  • Primary: 设置为传入的主存储
  • Cache: nil (默认不启用缓存)
  • CacheEnabled: false (默认缓存功能关闭)
  • CacheTTLSeconds: 3600 (默认缓存有效期为1小时)

异常处理:

  • 如果primary参数为nil,虽然函数不会立即返回错误,但在之后使用时会导致空指针异常

使用示例:

// 创建文件存储作为主存储
fileStorage, err := cpe.NewFileStorage("/path/to/data", true)
if err != nil {
    log.Fatalf("创建文件存储失败: %v", err)
}

// 初始化主存储
if err := fileStorage.Initialize(); err != nil {
    log.Fatalf("初始化存储失败: %v", err)
}

// 创建存储管理器
manager := cpe.NewStorageManager(fileStorage)

// 可选: 添加内存缓存以提高性能
memCache, _ := cpe.NewMemoryStorage()
memCache.Initialize()
manager.SetCache(memCache)

性能考虑:

  • 添加缓存可以显著提高频繁访问相同数据时的性能
  • 默认的缓存过期时间(1小时)适用于大多数场景,对于频繁更新的数据可能需要调整

线程安全:

  • StorageManager本身的初始化是线程安全的
  • 实际使用的线程安全性取决于传入的Storage实现

关联方法:

  • SetCache: 设置缓存存储
  • GetCPE, StoreCPE: CPE数据的获取与存储

func (*StorageManager) AdvancedSearch

func (sm *StorageManager) AdvancedSearch(criteria *CPE, options *AdvancedMatchOptions) ([]*CPE, error)

AdvancedSearch 高级搜索CPE对象

功能描述:

  • 提供比基本Search更强大的CPE搜索功能
  • 支持复杂的匹配条件和高级过滤规则
  • 直接从主存储搜索,不使用缓存,确保结果完整和最新

参数:

  • criteria *CPE: 搜索条件,包含要匹配的CPE属性
  • 可以为nil,表示不限制搜索条件(返回所有CPE)
  • 各个字段值将根据AdvancedMatchOptions中的规则进行匹配
  • options *AdvancedMatchOptions: 高级匹配选项
  • 不能为nil,必须提供有效的选项对象
  • 包含高级匹配规则,如正则表达式匹配、版本范围匹配、逻辑组合条件等

返回值:

  • []*CPE: 匹配条件的CPE对象切片
  • 如果没有匹配项,返回空切片(非nil)
  • error: 如果搜索过程中发生错误则返回错误
  • 可能的错误类型包括:
  • ErrInvalidData: 无效的搜索条件或匹配选项
  • ErrStorageDisconnected: 存储后端连接问题
  • 其他存储实现特定的错误

搜索行为:

  • 此方法总是直接查询主存储,不使用缓存
  • 查询结果不会被缓存,每次调用都会执行完整搜索
  • 根据高级匹配选项,可能会执行更复杂的数据库查询或内存过滤

使用示例:

// 高级搜索: 查找所有Microsoft的产品,版本在10.0到11.0之间
criteria := &cpe.CPE{
    Vendor: cpe.Vendor("microsoft"),
}

options := &cpe.AdvancedMatchOptions{
    VersionRange: &cpe.VersionRange{
        MinVersion: "10.0",
        MaxVersion: "11.0",
        Inclusive: true,
    },
    RegexMatch: map[string]string{
        "product": "windows|office",  // 产品名称匹配windows或office
    },
}

results, err := manager.AdvancedSearch(criteria, options)
if err != nil {
    fmt.Printf("高级搜索失败: %v\n", err)
    return
}

fmt.Printf("找到 %d 个匹配项\n", len(results))

性能考虑:

  • 高级搜索通常比基本搜索消耗更多资源,尤其是使用正则表达式匹配时
  • 对于大型数据集,应当限制结果数量或使用更具体的搜索条件

关联方法:

  • Search: 基本搜索功能,适用于简单的精确匹配

func (*StorageManager) ClearCache

func (sm *StorageManager) ClearCache() error

ClearCache 清空存储管理器的所有缓存数据

功能描述:

  • 清空整个缓存存储,移除所有缓存的CPE和CVE数据
  • 通过重新初始化缓存存储来实现彻底清除
  • 清除后,后续查询将从主存储获取最新数据

参数:

返回值:

  • error: 清空缓存过程中发生的错误
  • 如果缓存未启用或Cache为nil,返回nil
  • 如果缓存初始化失败,返回相应错误

缓存行为:

  • 如果缓存未启用(CacheEnabled为false),此方法直接返回nil
  • 如果Cache为nil,此方法直接返回nil
  • 缓存清空是通过重新初始化缓存实现的,比单独删除每个项更高效

使用场景:

  • 在数据大规模更新后使缓存完全失效
  • 当检测到缓存和主存储严重不一致时
  • 作为系统维护操作的一部分
  • 在缓存可能已损坏的情况下重置缓存

使用示例:

// 清空缓存
err := manager.ClearCache()
if err != nil {
    fmt.Printf("清空缓存失败: %v\n", err)
    return
}
fmt.Println("缓存已清空")

// 之后的所有查询都将从主存储获取数据
cpe, err := manager.GetCPE("cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*")

性能影响:

  • 清空缓存后,后续的查询性能可能暂时下降,直到缓存重新填充
  • 对于高访问量的系统,应在低峰期执行此操作

副作用:

  • 导致所有已缓存的数据被丢弃
  • 可能会触发大量的主存储查询,如果随后有大量访问请求

关联方法:

  • InvalidateCache: 只使特定CPE缓存失效,而不是整个缓存

func (*StorageManager) GetCPE

func (sm *StorageManager) GetCPE(id string) (*CPE, error)

GetCPE 获取CPE对象,优先从缓存获取

功能描述:

  • 根据CPE ID检索对应的CPE对象
  • 实现了两级存储查询策略: 如果缓存启用,优先从缓存查询,缓存未命中则从主存储查询
  • 从主存储获取的数据会自动同步到缓存中,以便后续查询更快速

参数:

  • id string: CPE的唯一标识符,通常为CPE 2.3格式的URI字符串
  • 例如: "cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*"
  • 不能为空,否则可能导致未定义行为

返回值:

  • *CPE: 成功检索到的CPE对象指针
  • error: 如果检索失败则返回错误
  • 可能的错误类型包括:
  • ErrNotFound: 指定ID的CPE不存在
  • ErrStorageDisconnected: 存储后端连接问题
  • 其他存储实现特定的错误

缓存行为:

  • 如果缓存启用且缓存命中,直接返回缓存中的对象,不访问主存储
  • 如果缓存启用但缓存未命中,从主存储获取并自动更新缓存
  • 如果缓存未启用,或Cache为nil,直接从主存储获取

错误处理:

  • 仅在主存储查询失败时返回错误,缓存查询失败会静默处理并继续查询主存储
  • 将数据写入缓存失败不会影响返回结果,错误会被忽略

使用示例:

// 创建带缓存的存储管理器
manager := cpe.NewStorageManager(primaryStorage)
manager.SetCache(memoryCache)

// 获取Windows 10的CPE信息
windowsCPE, err := manager.GetCPE("cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*")
if err != nil {
    if errors.Is(err, cpe.ErrNotFound) {
        fmt.Println("CPE不存在")
    } else {
        fmt.Printf("获取CPE失败: %v\n", err)
    }
    return
}

// 使用获取到的CPE对象
fmt.Printf("产品名称: %s\n", windowsCPE.ProductName)

性能考虑:

  • 缓存命中时,性能显著优于直接从主存储查询
  • 频繁查询相同CPE时,建议启用缓存

关联方法:

  • StoreCPE: 存储CPE并更新缓存
  • InvalidateCache: 使指定CPE的缓存失效

func (*StorageManager) GetCVE

func (sm *StorageManager) GetCVE(cveID string) (*CVEReference, error)

GetCVE 获取CVE引用对象,优先从缓存获取

功能描述:

  • 根据CVE ID检索对应的CVE引用对象
  • 实现了两级存储查询策略: 如果缓存启用,优先从缓存查询,缓存未命中则从主存储查询
  • 从主存储获取的数据会自动同步到缓存中,以便后续查询更快速

参数:

  • cveID string: CVE的唯一标识符,标准格式如"CVE-2021-44228"
  • 不能为空,否则可能导致未定义行为
  • ID格式应符合CVE命名规范(CVE-YYYY-NNNNN)

返回值:

  • *CVEReference: 成功检索到的CVE引用对象指针
  • error: 如果检索失败则返回错误
  • 可能的错误类型包括:
  • ErrNotFound: 指定ID的CVE不存在
  • ErrStorageDisconnected: 存储后端连接问题
  • 其他存储实现特定的错误

缓存行为:

  • 如果缓存启用且缓存命中,直接返回缓存中的对象,不访问主存储
  • 如果缓存启用但缓存未命中,从主存储获取并自动更新缓存
  • 如果缓存未启用,或Cache为nil,直接从主存储获取

错误处理:

  • 仅在主存储查询失败时返回错误,缓存查询失败会静默处理并继续查询主存储
  • 将数据写入缓存失败不会影响返回结果,错误会被忽略

使用示例:

// 获取Log4Shell漏洞的CVE信息
log4jCVE, err := manager.GetCVE("CVE-2021-44228")
if err != nil {
    if errors.Is(err, cpe.ErrNotFound) {
        fmt.Println("CVE不存在")
    } else {
        fmt.Printf("获取CVE失败: %v\n", err)
    }
    return
}

// 使用获取到的CVE信息
fmt.Printf("漏洞描述: %s\n", log4jCVE.Description)
fmt.Printf("CVSS评分: %.1f\n", log4jCVE.CVSSScore)

性能考虑:

  • 缓存命中时,性能显著优于直接从主存储查询
  • 频繁查询相同CVE时,建议启用缓存

关联方法:

  • FindCPEsByCVE: 查找受此CVE影响的所有CPE
  • FindCVEsByCPE: 查找影响特定CPE的所有CVE

func (*StorageManager) GetStats

func (sm *StorageManager) GetStats() (*StorageStats, error)

GetStats 获取存储的统计信息

功能描述:

  • 收集并返回存储系统的统计数据
  • 包括CPE和CVE数据的数量、字典项数量和最后更新时间等信息
  • 只从主存储中获取统计信息,不涉及缓存

参数:

返回值:

  • *StorageStats: 包含各种统计信息的结构体指针
  • TotalCPEs: 存储中的CPE总数
  • TotalCVEs: 存储中的CVE总数
  • TotalDictionaryItems: 字典中的项目总数
  • StorageBytes: 存储占用的字节数(部分实现可能不提供)
  • LastUpdated: 最后更新时间
  • error: 如果统计过程中发生错误则返回错误
  • 可能的错误类型包括:
  • ErrStorageDisconnected: 存储后端连接问题
  • 其他存储实现特定的错误

统计过程:

  • 执行全量CPE搜索,获取CPE总数
  • 执行全量CVE搜索,获取CVE总数
  • 获取字典并计数字典项数量
  • 获取最后更新时间,如果不存在则使用当前时间

使用示例:

// 获取存储统计信息
stats, err := manager.GetStats()
if err != nil {
    fmt.Printf("获取统计信息失败: %v\n", err)
    return
}

// 输出统计信息
fmt.Printf("CPE总数: %d\n", stats.TotalCPEs)
fmt.Printf("CVE总数: %d\n", stats.TotalCVEs)
fmt.Printf("字典项总数: %d\n", stats.TotalDictionaryItems)
fmt.Printf("最后更新时间: %v\n", stats.LastUpdated)

性能考虑:

  • 此方法可能会执行多次全量查询,在大型数据集上可能较慢
  • 不建议在高频操作中调用此方法,适合用于定期监控或管理界面

实现限制:

  • 目前实现仅统计总数,不提供更详细的分布信息
  • StorageBytes字段在当前实现中未填充实际值

关联信息:

  • StorageStats: 存储统计信息的数据结构

func (*StorageManager) InvalidateCache

func (sm *StorageManager) InvalidateCache(id string)

InvalidateCache 使指定CPE的缓存失效

功能描述:

  • 从缓存中删除指定ID的CPE对象
  • 用于在CPE数据更新后确保缓存与主存储一致
  • 静默处理删除失败的情况,不影响程序流程

参数:

  • id string: 要使其缓存失效的CPE的唯一标识符
  • 通常为CPE 2.3格式的URI字符串
  • 如果ID在缓存中不存在,操作不会产生任何效果

返回值:

缓存行为:

  • 如果缓存未启用(CacheEnabled为false),此方法不执行任何操作
  • 如果Cache为nil,此方法不执行任何操作
  • 缓存删除操作是尽力而为的,删除失败不会报告错误

使用场景:

  • 当通过其他途径(非StorageManager)更新了CPE数据时
  • 在执行UpdateCPE操作后手动调用,确保缓存一致性
  • 当检测到数据不一致时主动清除缓存项

使用示例:

// 在更新CPE后,使缓存失效
cpeID := "cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*"

// 通过其他方式更新了CPE数据
primaryStorage.UpdateCPE(updatedCPE)

// 使对应的缓存失效,确保下次获取时能获取最新数据
manager.InvalidateCache(cpeID)

// 下次调用GetCPE将从主存储获取最新数据
latestCPE, err := manager.GetCPE(cpeID)

并发安全:

  • 此方法的并发安全性取决于Cache实现的DeleteCPE方法
  • 对于多数实现,此方法可以安全地并发调用

关联方法:

  • ClearCache: 清空整个缓存,而不是单个项
  • GetCPE: 会受到此方法的影响,在缓存失效后将重新从主存储获取

func (*StorageManager) Search

func (sm *StorageManager) Search(criteria *CPE, options *MatchOptions) ([]*CPE, error)

Search 搜索匹配指定条件的CPE对象

功能描述:

  • 在主存储中搜索符合给定条件的CPE对象
  • 根据MatchOptions中的匹配规则进行过滤
  • 直接从主存储搜索,不使用缓存,确保结果完整和最新

参数:

  • criteria *CPE: 搜索条件,包含要匹配的CPE属性
  • 可以为nil,表示不限制搜索条件(返回所有CPE)
  • 如果指定了某个字段,则匹配该字段的值
  • 特殊值"*"和"-"按CPE规范处理
  • options *MatchOptions: 匹配选项,控制匹配行为
  • 如果为nil,将使用默认匹配选项
  • 包含精确匹配/模式匹配等控制参数

返回值:

  • []*CPE: 匹配条件的CPE对象切片
  • 如果没有匹配项,返回空切片(非nil)
  • error: 如果搜索过程中发生错误则返回错误
  • 可能的错误类型包括:
  • ErrStorageDisconnected: 存储后端连接问题
  • 其他存储实现特定的错误

搜索行为:

  • 此方法总是直接查询主存储,不使用缓存
  • 查询结果不会被缓存,每次调用都会执行完整搜索
  • 返回的CPE对象是数据库中对象的拷贝,修改不会影响存储

使用示例:

// 搜索所有Microsoft Windows产品的CPE
criteria := &cpe.CPE{
    Vendor:      cpe.Vendor("microsoft"),
    ProductName: cpe.Product("windows"),
}

// 使用默认匹配选项
options := &cpe.MatchOptions{}

// 执行搜索
results, err := manager.Search(criteria, options)
if err != nil {
    fmt.Printf("搜索失败: %v\n", err)
    return
}

// 处理搜索结果
fmt.Printf("找到 %d 个匹配项\n", len(results))
for i, cpe := range results {
    fmt.Printf("%d. %s\n", i+1, cpe.Cpe23)
}

性能考虑:

  • 对于大型数据集,搜索可能需要较长时间,应考虑使用分页或限制结果数量
  • 频繁执行相同搜索时,可考虑在应用层面实现结果缓存

关联方法:

  • AdvancedSearch: 支持更复杂查询条件的高级搜索
  • GetCPE: 根据ID直接获取单个CPE对象(支持缓存)

func (*StorageManager) SetCache

func (sm *StorageManager) SetCache(cache Storage)

SetCache 设置缓存存储

功能描述:

  • 为存储管理器配置缓存存储,启用缓存功能
  • 设置缓存后,管理器会在读取数据时优先从缓存获取,写入数据时同时更新缓存
  • 提高频繁访问相同数据时的性能,减轻主存储负担

参数:

  • cache Storage: 实现Storage接口的缓存存储对象,通常为内存存储
  • 如果传入nil,缓存仍会被标记为启用,但实际不会生效(建议避免传入nil)

返回值:

副作用:

  • 修改管理器的Cache属性为传入的缓存存储
  • 将CacheEnabled设置为true,启用缓存功能

使用示例:

// 创建存储管理器
manager := cpe.NewStorageManager(primaryStorage)

// 创建内存缓存
memCache, _ := cpe.NewMemoryStorage()
memCache.Initialize()

// 设置缓存
manager.SetCache(memCache)

// 现在管理器会使用缓存来提高性能
cpe, err := manager.GetCPE("cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*")

注意事项:

  • 在调用此方法前,应确保缓存存储已经正确初始化
  • 此方法不会自动同步现有数据到缓存中,缓存会在后续访问时逐渐填充

关联方法:

  • GetCPE, GetCVE: 会优先从缓存获取数据
  • StoreCPE: 会同时更新缓存
  • InvalidateCache, ClearCache: 用于管理缓存内容

func (*StorageManager) StoreCPE

func (sm *StorageManager) StoreCPE(cpe *CPE) error

StoreCPE 存储CPE对象到主存储和缓存中

功能描述:

  • 将CPE对象持久化保存到主存储中
  • 如果缓存已启用,同时更新缓存中的对应数据
  • 确保主存储和缓存的数据一致性

参数:

  • cpe *CPE: 要存储的CPE对象指针,不能为nil
  • 对象必须包含有效的识别信息(如Cpe23字段)以便正确存储
  • 建议在存储前使用ValidateCPE验证对象有效性

返回值:

  • error: 如果存储过程中发生错误则返回具体错误
  • 可能的错误类型包括:
  • ErrInvalidData: CPE数据无效
  • ErrDuplicate: 已存在相同ID的CPE(取决于具体存储实现)
  • ErrStorageDisconnected: 存储后端连接问题
  • 其他存储实现特定的错误

缓存行为:

  • 如果缓存启用且Cache不为nil,成功写入主存储后会同步更新缓存
  • 缓存写入失败不会影响主函数返回结果,错误会被忽略
  • 即使缓存更新失败,主存储的数据仍然会成功保存

事务特性:

  • 对主存储的写入具有事务性,要么完全成功要么完全失败
  • 缓存更新不参与主存储的事务,缓存更新可能在主存储成功后失败

使用示例:

// 创建一个CPE对象
windowsCPE := &cpe.CPE{
    Cpe23:       "cpe:2.3:o:microsoft:windows:10:*:*:*:*:*:*:*",
    Vendor:      cpe.Vendor("microsoft"),
    ProductName: cpe.Product("windows"),
    Version:     cpe.Version("10"),
}

// 使用存储管理器保存CPE
err := manager.StoreCPE(windowsCPE)
if err != nil {
    if errors.Is(err, cpe.ErrDuplicate) {
        fmt.Println("CPE已存在")
    } else {
        fmt.Printf("存储CPE失败: %v\n", err)
    }
    return
}
fmt.Println("CPE存储成功")

并发安全:

  • 此方法的并发安全性取决于底层Storage实现
  • 对于支持并发的Storage实现,此方法可以安全地并发调用

关联方法:

  • GetCPE: 检索已存储的CPE
  • ValidateCPE: 建议在存储前先验证CPE对象有效性

type StorageStats

type StorageStats struct {
	// CPE总数
	TotalCPEs int

	// CVE总数
	TotalCVEs int

	// 字典项总数
	TotalDictionaryItems int

	// 存储占用空间(字节)
	StorageBytes int64

	// 上次更新时间
	LastUpdated time.Time
}

StorageStats 存储统计信息

type Update

type Update string

*

  • Update 表示CPE中产品的更新标识符 *
  • 在CPE规范中,Update表示特定版本的更新或补丁级别,如"sp1"(Service Pack 1)、
  • "update2"、"patch3"等。Update也可以使用特殊值"*"(任意更新)或"-"(不适用)。 *
  • 与其他CPE组件类似,更新标识符在标准化过程中会被转换为小写,空格会被替换为下划线。 *
  • 示例:
  • ```go
  • // 创建一个表示Windows 10 SP1的CPE
  • windowsCPE := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • Update: cpe.Update("sp1"),
  • } *
  • // 搜索具有特定更新的产品
  • searchCriteria := &cpe.CPE{
  • ProductName: cpe.Product("windows"),
  • Update: cpe.Update("sp1"),
  • }
  • options := cpe.DefaultMatchOptions()
  • results := cpe.Search(cpeList, searchCriteria, options) *
  • // 使用正则表达式匹配更新
  • options.UseRegex = true
  • regexCriteria := &cpe.CPE{
  • Update: cpe.Update("sp[0-9]"), // 匹配sp后跟随一个数字
  • }
  • ```

func (Update) IsANY

func (u Update) IsANY() bool

IsANY 判断Update是否为ANY值

func (Update) IsNA

func (u Update) IsNA() bool

IsNA 判断Update是否为NA值

func (Update) IsSet

func (u Update) IsSet() bool

IsSet 判断Update是否设置了有效值

func (Update) Normalize

func (u Update) Normalize() string

Normalize 标准化Update值

func (Update) String

func (u Update) String() string

String 返回Update的字符串表示

type Vendor

type Vendor string

*

  • Vendor 表示CPE中的产品供应商 *
  • 在CPE规范中,Vendor是指产品的制造商或提供者的名称。供应商名称通常是小写字母,
  • 多词名称使用下划线连接,如"microsoft"、"adobe"、"apache_software_foundation"等。
  • 供应商也可以使用特殊值"*"(任意供应商)或"-"(不适用)。 *
  • 在CPE标准化过程中,供应商名称会被转换为小写,空格会被替换为下划线。 *
  • 示例:
  • ```go
  • // 创建一个表示Microsoft产品的CPE
  • microsoftCPE := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • } *
  • // 在搜索条件中使用特定供应商
  • searchCriteria := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • }
  • options := cpe.DefaultMatchOptions()
  • results := cpe.Search(cpeList, searchCriteria, options) *
  • // 使用标准化函数处理供应商名称
  • normalizedVendor := cpe.NormalizeComponent("Microsoft Corporation")
  • // 结果为 "microsoft_corporation"
  • ```

func (Vendor) IsANY

func (v Vendor) IsANY() bool

IsANY 判断Vendor是否为ANY值

func (Vendor) IsNA

func (v Vendor) IsNA() bool

IsNA 判断Vendor是否为NA值

func (Vendor) IsSet

func (v Vendor) IsSet() bool

IsSet 判断Vendor是否设置了有效值

func (Vendor) Normalize

func (v Vendor) Normalize() string

Normalize 标准化Vendor值

func (Vendor) String

func (v Vendor) String() string

String 返回Vendor的字符串表示

type Version

type Version string

*

  • Version 表示CPE中产品的版本号 *
  • 在CPE规范中,Version是表示产品版本的字符串,可以包含数字、字母和特殊字符。
  • 版本号可以是具体的数值如"10.0.1",也可以使用特殊值"*"(任意版本)或"-"(不适用)。 *
  • 示例:
  • ```go
  • // 创建一个表示Windows 10的CPE
  • windowsCPE := &cpe.CPE{
  • Vendor: cpe.Vendor("microsoft"),
  • ProductName: cpe.Product("windows"),
  • Version: cpe.Version("10"),
  • } *
  • // 版本比较示例
  • v1 := cpe.Version("10.0")
  • v2 := cpe.Version("11.0")
  • result := cpe.compareVersionsSimple(string(v1), string(v2)) // 返回 -1,表示v1 < v2 *
  • // 在匹配选项中设置版本范围
  • options := cpe.DefaultMatchOptions()
  • options.VersionRange = true
  • options.MinVersion = "10.0"
  • options.MaxVersion = "11.0"
  • ```

func (Version) IsANY

func (v Version) IsANY() bool

IsANY 判断Version是否为ANY值

func (Version) IsNA

func (v Version) IsNA() bool

IsNA 判断Version是否为NA值

func (Version) IsSet

func (v Version) IsSet() bool

IsSet 判断Version是否设置了有效值

func (Version) Normalize

func (v Version) Normalize() string

Normalize 标准化Version值

func (Version) String

func (v Version) String() string

String 返回Version的字符串表示

type VersionRange

type VersionRange struct {
	MinVersion string // 最小版本(包含)
	MaxVersion string // 最大版本(包含)
}

VersionRange 表示版本范围

func ParseVersionRange

func ParseVersionRange(s string) (*VersionRange, error)

ParseVersionRange 解析版本范围字符串 支持格式:

  • "1.0" -> 精确版本
  • "1.0-2.0" -> 范围(从1.0到2.0)
  • "1.0+" -> 1.0及以上
  • "-2.0" -> 2.0及以下

func (*VersionRange) Contains

func (vr *VersionRange) Contains(version string) bool

Contains 检查版本是否在范围内

type VulnDataSource

type VulnDataSource struct {
	// 数据源类型
	Type DataSourceType

	// 数据源名称
	Name string

	// 数据源描述
	Description string

	// 数据源URL
	URL string

	// 认证信息
	Authentication *DataSourceAuth

	// HTTP客户端
	Client *http.Client

	// 上次更新时间
	LastUpdated time.Time

	// 缓存设置
	CacheSettings *CacheSettings

	// 自定义选项
	Options map[string]interface{}
}

VulnDataSource 表示一个漏洞数据源

func CreateGitHubDataSource

func CreateGitHubDataSource(token string) *VulnDataSource

CreateGitHubDataSource 创建GitHub数据源

func CreateNVDDataSource

func CreateNVDDataSource(apiKey string) *VulnDataSource

CreateNVDDataSource 创建NVD数据源

func CreateRedHatDataSource

func CreateRedHatDataSource() *VulnDataSource

CreateRedHatDataSource 创建RedHat数据源

func NewVulnDataSource

func NewVulnDataSource(sourceType DataSourceType, name, description, url string) *VulnDataSource

NewDataSource 创建新的数据源

func (*VulnDataSource) FetchData

func (ds *VulnDataSource) FetchData(endpoint string) ([]byte, error)

FetchData 从数据源获取数据

func (*VulnDataSource) GetVulnerabilities

func (ds *VulnDataSource) GetVulnerabilities(params map[string]string) ([]*CVEReference, error)

GetVulnerabilities 获取漏洞信息

func (*VulnDataSource) GetVulnerabilityById

func (ds *VulnDataSource) GetVulnerabilityById(cveID string) (*CVEReference, error)

GetVulnerabilityById 根据CVE ID获取漏洞信息

func (*VulnDataSource) SearchVulnerabilitiesByCPE

func (ds *VulnDataSource) SearchVulnerabilitiesByCPE(cpe *CPE) ([]*CVEReference, error)

SearchVulnerabilitiesByCPE 根据CPE查找相关漏洞

func (*VulnDataSource) SetAuthentication

func (ds *VulnDataSource) SetAuthentication(auth *DataSourceAuth)

SetAuthentication 设置数据源认证信息

func (*VulnDataSource) SetCacheSettings

func (ds *VulnDataSource) SetCacheSettings(cache *CacheSettings)

SetCacheSettings 设置缓存设置

type WFN

type WFN struct {
	Part            string // 组件类型: a(应用程序)、o(操作系统)、h(硬件设备)
	Vendor          string // 厂商名称
	Product         string // 产品名称
	Version         string // 版本号
	Update          string // 更新版本
	Edition         string // 版本
	Language        string // 语言
	SoftwareEdition string // 软件版本
	TargetSoftware  string // 目标软件
	TargetHardware  string // 目标硬件
	Other           string // 其他信息
}

WFN (Well-Formed Name) 表示CPE的规范化内部表示 WFN是CPE的内部规范表示形式,用于存储CPE各个组成部分的值 一个完整的WFN包含以下11个属性:part, vendor, product, version, update, edition, language, softwareEdition, targetSoftware, targetHardware和other

func FromCPE

func FromCPE(cpe *CPE) *WFN

FromCPE 从CPE结构体创建WFN 本方法将CPE结构体转换为规范化的WFN格式,用于内部处理和比较

参数:

  • cpe: CPE结构体指针,包含各个属性的值

返回值:

  • *WFN: 转换后的WFN结构体指针

示例:

cpe := &CPE{
  Part: *PartApplication,
  Vendor: "microsoft",
  ProductName: "windows",
  Version: "10",
}
wfn := FromCPE(cpe)
fmt.Println(wfn.Part)     // 输出: "a"
fmt.Println(wfn.Vendor)   // 输出: "microsoft"
fmt.Println(wfn.Product)  // 输出: "windows"
fmt.Println(wfn.Version)  // 输出: "10"

func FromCPE22String

func FromCPE22String(cpe22 string) (*WFN, error)

FromCPE22String 从CPE 2.2格式字符串创建WFN 本方法解析CPE 2.2格式的字符串,将其转换为WFN结构体 内部实现是先将CPE 2.2转换为CPE 2.3格式,再调用FromCPE23String方法

参数:

  • cpe22: 符合CPE 2.2规范的字符串,例如"cpe:/a:microsoft:windows:10"

返回值:

  • *WFN: 解析成功返回WFN结构体指针
  • error: 解析失败返回错误信息

示例:

wfn, err := FromCPE22String("cpe:/a:microsoft:windows:10")
if err != nil {
  panic(err)
}
fmt.Println(wfn.Part)     // 输出: "a"
fmt.Println(wfn.Vendor)   // 输出: "microsoft"
fmt.Println(wfn.Product)  // 输出: "windows"
fmt.Println(wfn.Version)  // 输出: "10"

错误情况:

  • 如果转换后的CPE 2.3格式字符串无效,会返回FromCPE23String传递的错误

注意:

  • 该方法依赖convertCpe22ToCpe23函数,该函数将CPE 2.2格式转换为CPE 2.3格式

func FromCPE23String

func FromCPE23String(cpe23 string) (*WFN, error)

FromCPE23String 从CPE 2.3格式字符串创建WFN 本方法解析CPE 2.3格式的字符串,将其转换为WFN结构体

参数:

  • cpe23: 符合CPE 2.3规范的字符串,例如"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"

返回值:

  • *WFN: 解析成功返回WFN结构体指针
  • error: 解析失败返回错误信息

示例:

wfn, err := FromCPE23String("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
if err != nil {
  panic(err)
}
fmt.Println(wfn.Part)     // 输出: "a"
fmt.Println(wfn.Vendor)   // 输出: "microsoft"
fmt.Println(wfn.Product)  // 输出: "windows"
fmt.Println(wfn.Version)  // 输出: "10"

错误情况:

  • 如果字符串不以"cpe:2.3:"开头,返回格式错误
  • 如果字符串不包含13个部分(以冒号分隔),返回格式错误

注意:

  • 方法会自动对每个字段进行反转义处理

func NewWFN

func NewWFN() *WFN

NewWFN creates an empty WFN with all attributes defaulting to ANY

func UnbindFS

func UnbindFS(fs string) (*WFN, error)

UnbindFS 将CPE 2.3 FS格式字符串解绑为WFN

func UnbindURI

func UnbindURI(uri string) (*WFN, error)

UnbindURI 将CPE 2.2 URI格式字符串解绑为WFN

func (*WFN) Get

func (w *WFN) Get(attr string) string

func (*WFN) IsIdentifierName

func (w *WFN) IsIdentifierName() bool

func (*WFN) Match

func (w *WFN) Match(other *WFN) bool

Match 比较两个WFN是否匹配 本方法检查当前WFN与另一个WFN是否匹配,匹配规则遵循CPE规范

参数:

  • other: 另一个WFN结构体指针,用于与当前WFN比较

返回值:

  • bool: 如果匹配返回true,否则返回false

示例:

wfn1 := &WFN{
  Part: "a",
  Vendor: "microsoft",
  Product: "windows",
  Version: "*", // 任意版本
}

wfn2 := &WFN{
  Part: "a",
  Vendor: "microsoft",
  Product: "windows",
  Version: "10",
}

fmt.Println(wfn1.Match(wfn2)) // 输出: true
fmt.Println(wfn2.Match(wfn1)) // 输出: true

匹配规则:

  • 如果两个WFN的所有属性都匹配,则这两个WFN匹配
  • 单个属性的匹配规则通过matchWFNAttribute函数定义
  • 属性为"*"表示ANY,可以匹配任何值
  • 如果两个属性都是"-"(NA),则它们匹配
  • 其他情况要求精确匹配

func (*WFN) Set

func (w *WFN) Set(attr string, value string)

func (*WFN) ToCPE

func (w *WFN) ToCPE() *CPE

ToCPE 转换WFN为CPE结构体 本方法将WFN转换回CPE结构体,用于外部使用和展示

返回值:

  • *CPE: 转换后的CPE结构体指针,包含从WFN提取的所有属性值

示例:

wfn := &WFN{
  Part: "a",
  Vendor: "microsoft",
  Product: "windows",
  Version: "10",
}
cpe := wfn.ToCPE()
fmt.Println(cpe.Part.Name)      // 输出: "Application"
fmt.Println(string(cpe.Vendor)) // 输出: "microsoft"
fmt.Println(cpe.Cpe23)          // 输出CPE 2.3格式字符串

注意:

  • 方法会自动设置CPE.Cpe23字段,生成CPE 2.3格式字符串
  • 如果WFN.Part不是有效值(a/h/o),默认为应用程序(a)

func (*WFN) ToCPE22String

func (w *WFN) ToCPE22String() string

ToCPE22String 转换WFN为CPE 2.2格式字符串 本方法将WFN结构体转换为标准的CPE 2.2格式字符串

返回值:

  • string: 符合CPE 2.2规范的字符串,例如"cpe:/a:microsoft:windows:10"

示例:

wfn := &WFN{
  Part: "a",
  Vendor: "microsoft",
  Product: "windows",
  Version: "10",
  Update: "sp1",
  Edition: "pro",
  Language: "zh-cn",
}
cpe22 := wfn.ToCPE22String()
fmt.Println(cpe22) // 输出: "cpe:/a:microsoft:windows:10:sp1:pro~zh-cn"

注意:

  • CPE 2.2格式与CPE 2.3格式不完全兼容,部分字段可能无法完整表示
  • 主要部分(Part, Vendor, Product, Version, Update)用冒号分隔
  • 扩展属性(如Edition等)使用波浪线(~)分隔
  • 方法会自动移除末尾空值的扩展属性
  • 使用escapeValueForCpe22函数进行转义,转义规则与CPE 2.3不同

func (*WFN) ToCPE23String

func (w *WFN) ToCPE23String() string

ToCPE23String 转换WFN为CPE 2.3格式字符串 本方法将WFN结构体转换为标准的CPE 2.3格式字符串

返回值:

  • string: 符合CPE 2.3规范的字符串,例如"cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"

示例:

wfn := &WFN{
  Part: "a",
  Vendor: "microsoft",
  Product: "windows",
  Version: "10",
}
cpe23 := wfn.ToCPE23String()
fmt.Println(cpe23) // 输出: "cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*"

注意:

  • 方法会自动对每个字段进行转义处理,使用escapeValue函数
  • 所有字段之间用冒号(:)分隔,共有13部分
  • 返回的字符串始终以"cpe:2.3:"开头

func (*WFN) WFNString

func (w *WFN) WFNString() string

type XMLCPEDictionary

type XMLCPEDictionary struct {
	XMLName       xml.Name     `xml:"cpe-list"`
	SchemaVersion string       `xml:"schema_version,attr"`
	GeneratedAt   string       `xml:"generated,attr"`
	Items         []XMLCPEItem `xml:"cpe-item"`
}

XMLCPEDictionary XML格式的CPE字典(用于解析)

type XMLCPEItem

type XMLCPEItem struct {
	XMLName         xml.Name       `xml:"cpe-item"`
	Name            string         `xml:"name,attr"`
	Deprecated      string         `xml:"deprecated,attr,omitempty"`
	DeprecationDate string         `xml:"deprecation_date,attr,omitempty"`
	Title           string         `xml:"title"`
	References      []XMLReference `xml:"references>reference,omitempty"`
}

XMLCPEItem XML格式的CPE项

type XMLReference

type XMLReference struct {
	URL  string `xml:"href,attr"`
	Type string `xml:"type,attr"`
}

XMLReference XML格式的参考信息

Directories

Path Synopsis
cmd
cpe command
examples
02_cpe_matching command
06_cpe_sets command
08_storage command
10_cve_mapping command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL