mirror of
https://github.com/anchore/syft.git
synced 2026-10-30 22:12:28 +01:00
* fix(ai): use go.yaml.in/yaml/v3 to parse model card frontmatter gopkg.in/yaml.v3 panics on some malformed merge-key payloads (for example "<<:\r? 0:"), which crashed the gguf and safetensors catalogers when a model README contained such frontmatter. Switch the Hugging Face frontmatter parser to the maintained go.yaml.in/yaml/v3 fork, which is already used by the other catalogers and returns an error instead of panicking. The existing error path logs and skips the frontmatter. Fixes #5327 Signed-off-by: tk1475 <118763009+tk1475@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: finish moving off gopkg.in/yaml.v3 - move the snap catalogers and `internal/capabilities` to `go.yaml.in/yaml/v3`. The snap parsers decode yaml from scanned sources and hit the same merge-key panic as #5327 - enable `depguard` with a deny rule for `gopkg.in/yaml.v3` so it can't be reintroduced Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: tk1475 <118763009+tk1475@users.noreply.github.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
95 lines
3.0 KiB
Go
95 lines
3.0 KiB
Go
package internal
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"go.yaml.in/yaml/v3"
|
|
|
|
"github.com/anchore/syft/internal/capabilities"
|
|
)
|
|
|
|
// LoadCapabilities loads the capabilities document from a YAML file.
|
|
// Returns both the parsed document and the original YAML node tree to preserve comments.
|
|
// Exported for use by the generator in generate/main.go
|
|
func LoadCapabilities(catalogerDir, repoRoot string) (*capabilities.Document, map[string]*yaml.Node, error) {
|
|
// load all cataloger/*/capabilities.yaml files
|
|
files, err := filepath.Glob(filepath.Join(catalogerDir, "*", CapabilitiesFilename))
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to glob capabilities files: %w", err)
|
|
}
|
|
|
|
mergedDoc := &capabilities.Document{
|
|
Configs: make(map[string]capabilities.CatalogerConfigEntry),
|
|
Catalogers: []capabilities.CatalogerEntry{},
|
|
}
|
|
nodeMap := make(map[string]*yaml.Node)
|
|
|
|
// load each package file
|
|
for _, file := range files {
|
|
data, err := os.ReadFile(file)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to read %s: %w", file, err)
|
|
}
|
|
|
|
// parse into node tree to preserve comments
|
|
var rootNode yaml.Node
|
|
if err := yaml.Unmarshal(data, &rootNode); err != nil {
|
|
return nil, nil, fmt.Errorf("failed to parse %s into node tree: %w", file, err)
|
|
}
|
|
|
|
// parse into struct
|
|
var doc struct {
|
|
Configs map[string]capabilities.CatalogerConfigEntry `yaml:"configs"`
|
|
Catalogers []capabilities.CatalogerEntry `yaml:"catalogers"`
|
|
}
|
|
if err := yaml.Unmarshal(data, &doc); err != nil {
|
|
fmt.Printf("\n=== DEBUG: YAML Parse Error in %s ===\n", file)
|
|
fmt.Printf("Error: %v\n\n", err)
|
|
fmt.Printf("=== FULL FILE CONTENT ===\n%s\n=== END FILE ===\n", string(data))
|
|
return nil, nil, fmt.Errorf("failed to parse %s into struct: %w", file, err)
|
|
}
|
|
|
|
// merge configs
|
|
for k, v := range doc.Configs {
|
|
mergedDoc.Configs[k] = v
|
|
}
|
|
|
|
// merge catalogers
|
|
mergedDoc.Catalogers = append(mergedDoc.Catalogers, doc.Catalogers...)
|
|
|
|
// store node tree by ecosystem directory name
|
|
// path is like "/path/to/syft/pkg/cataloger/alpine/capabilities.yaml"
|
|
ecosystem := filepath.Base(filepath.Dir(file))
|
|
nodeMap[ecosystem] = &rootNode
|
|
}
|
|
|
|
// load appconfig.yaml separately (from internal/capabilities/)
|
|
appconfigPath := AppconfigPath(repoRoot)
|
|
if _, err := os.Stat(appconfigPath); err == nil {
|
|
data, err := os.ReadFile(appconfigPath)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to read appconfig.yaml: %w", err)
|
|
}
|
|
|
|
var appDoc struct {
|
|
Application []capabilities.ApplicationConfigField `yaml:"application"`
|
|
}
|
|
if err := yaml.Unmarshal(data, &appDoc); err != nil {
|
|
return nil, nil, fmt.Errorf("failed to parse appconfig.yaml: %w", err)
|
|
}
|
|
|
|
mergedDoc.ApplicationConfig = appDoc.Application
|
|
|
|
// load node tree for appconfig
|
|
var appNode yaml.Node
|
|
if err := yaml.Unmarshal(data, &appNode); err != nil {
|
|
return nil, nil, fmt.Errorf("failed to parse appconfig.yaml into node tree: %w", err)
|
|
}
|
|
nodeMap["appconfig"] = &appNode
|
|
}
|
|
|
|
return mergedDoc, nodeMap, nil
|
|
}
|