/ pkg / vulstruct / scanner.go
scanner.go
  1  // Copyright (c) 2024-2026 Tencent Zhuque Lab. All rights reserved.
  2  //
  3  // Licensed under the Apache License, Version 2.0 (the "License");
  4  // you may not use this file except in compliance with the License.
  5  // You may obtain a copy of the License at
  6  //
  7  //     http://www.apache.org/licenses/LICENSE-2.0
  8  //
  9  // Unless required by applicable law or agreed to in writing, software
 10  // distributed under the License is distributed on an "AS IS" BASIS,
 11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  // See the License for the specific language governing permissions and
 13  // limitations under the License.
 14  //
 15  // Requirement: Any integration or derivative work must explicitly attribute
 16  // Tencent Zhuque Lab (https://github.com/Tencent/AI-Infra-Guard) in its
 17  // documentation or user interface, as detailed in the NOTICE file.
 18  
 19  // Package vulstruct 漏洞扫描
 20  package vulstruct
 21  
 22  import (
 23  	"fmt"
 24  	"strings"
 25  
 26  	"github.com/Tencent/AI-Infra-Guard/common/fingerprints/parser"
 27  	"gopkg.in/yaml.v3"
 28  )
 29  
 30  // Info represents vulnerability information structure
 31  // 存储漏洞信息的结构体
 32  type Info struct {
 33  	FingerPrintName string   `yaml:"name" json:"name"`                                 // Name of the fingerprint
 34  	CVEName         string   `yaml:"cve" json:"cve"`                                   // CVE identifier
 35  	Summary         string   `yaml:"summary" json:"summary"`                           // Brief summary of the vulnerability
 36  	Details         string   `yaml:"details" json:"details"`                           // Detailed description
 37  	CVSS            string   `yaml:"cvss" json:"cvss"`                                 // CVSS score
 38  	Severity        string   `yaml:"severity" json:"severity"`                         // Severity level
 39  	SecurityAdvise  string   `yaml:"security_advise,omitempty" json:"security_advise"` // Security advisory
 40  	References      []string `yaml:"references" json:"references"`
 41  	Author          string   `yaml:"author,omitempty" json:"author,omitempty"`
 42  }
 43  
 44  // VersionVul represents a version-based vulnerability
 45  // 版本相关的漏洞结构体
 46  type VersionVul struct {
 47  	Info        Info         `yaml:"info" json:"info"`             // Basic vulnerability information
 48  	Rule        string       `yaml:"rule" json:"rule"`             // Rule expression in string format
 49  	RuleCompile *parser.Rule `yaml:"-" json:"-"`                   // Compiled rule for evaluation
 50  	References  []string     `yaml:"references" json:"references"` // Reference links
 51  }
 52  
 53  // UnmarshalYAML implements the yaml.Unmarshaler interface
 54  func (v *VersionVul) UnmarshalYAML(unmarshal func(interface{}) error) error {
 55  	// 定义临时结构体,Rule字段为指针类型
 56  	type tmpStruct struct {
 57  		Info       Info     `yaml:"info"`
 58  		Rule       *string  `yaml:"rule"`
 59  		References []string `yaml:"references"`
 60  	}
 61  
 62  	var tmp tmpStruct
 63  	if err := unmarshal(&tmp); err != nil {
 64  		return err
 65  	}
 66  
 67  	// 检查Rule字段是否存在
 68  	if tmp.Rule == nil {
 69  		return fmt.Errorf("missing required field 'rule'")
 70  	}
 71  
 72  	// 将临时结构体的值赋给原结构体
 73  	v.Info = tmp.Info
 74  	v.Rule = *tmp.Rule // 即使为空字符串也允许
 75  	v.References = tmp.References
 76  
 77  	return nil
 78  }
 79  
 80  // ReadVersionVul reads and parses a single vulnerability file
 81  // 读取并解析单个漏洞文件
 82  func ReadVersionVul(body []byte) (*VersionVul, error) {
 83  	// Unmarshal YAML content into VersionVul struct
 84  	// 将YAML内容解析到VersionVul结构体中
 85  	var advisory VersionVul
 86  	err := yaml.Unmarshal(body, &advisory)
 87  	if err != nil {
 88  		return nil, err
 89  	}
 90  	advisory.Info.Details = strings.TrimSpace(advisory.Info.Details)
 91  	advisory.Info.References = advisory.References
 92  
 93  	if advisory.Rule == "" {
 94  		advisory.RuleCompile = nil
 95  		return &advisory, nil
 96  	}
 97  
 98  	// Parse rule string into tokens
 99  	// 将规则字符串解析为词法单元
100  	tokens, err := parser.ParseAdvisorTokens(advisory.Rule)
101  	if err != nil {
102  		return nil, err
103  	}
104  
105  	// Verify token balance
106  	// 验证词法单元的平衡性
107  	err = parser.CheckBalance(tokens)
108  	if err != nil {
109  		return nil, err
110  	}
111  
112  	// Transform tokens into DSL rule
113  	// 将词法单元转换为DSL规则
114  	dsl, err := parser.TransFormExp(tokens)
115  	if err != nil {
116  		return nil, err
117  	}
118  
119  	advisory.RuleCompile = dsl
120  	return &advisory, nil
121  }