celrules

package
v1.18.2 Latest Latest
Warning

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

Go to latest
Published: Nov 6, 2026 License: AGPL-3.0 Imports: 24 Imported by: 0

Documentation

Overview

Copyright (C) 2026 l3montree GmbH

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.

Index

Constants

View Source
const (
	// PathPatternWildcard matches any path element at that position
	PathPatternWildcard = "*"
)

PathPattern wildcard for VEX rules

Variables

View Source
var SoftMatchCelEnv = sync.OnceValues(func() (*cel.Env, error) {
	return newVEXCelEnv(func(pattern, path, _ []string) bool {
		return PathPattern(pattern).SoftMatches(path)
	})
})

SoftMatchCelEnv is for callers that haven't loaded artifacts at all - e.g. crowdsourced-vexing's soft-match phase, run against representative vulns before their real artifacts are known. See PathPattern.SoftMatches for the semantics this widens matchesPattern to.

View Source
var VEXCelEnv = sync.OnceValues(func() (*cel.Env, error) {
	return newVEXCelEnv(func(pattern, path, artifactPurls []string) bool {
		return PathPattern(pattern).Matches(path, artifactPurls)
	})
})

VEXCelEnv is the CEL environment used for real VEX rule matching, where the vuln's real artifacts are known.

Functions

func CompileVEXRules

func CompileVEXRules(ctx context.Context, rules []models.UpstreamVEXRule) (map[string]CompiledVEXRule, error)

CompileVEXRules compiles every rule's CEL expression against the real-match CelEnv. cel.Env is safe for concurrent Compile/Program calls, so rules are compiled in parallel batches.

func CompileVEXRulesForSoftMatching

func CompileVEXRulesForSoftMatching(ctx context.Context, rules []models.UpstreamVEXRule) (map[string]CompiledVEXRule, error)

CompileVEXRulesForSoftMatching is CompileVEXRules against SoftMatchCelEnv, for crowdsourced-vexing's soft-match phase over vulns without real artifacts.

func EvalCompiledVEXRules

func EvalCompiledVEXRules(ctx context.Context, compiled map[string]CompiledVEXRule, vulnMaps []map[string]any) (map[string][]string, error)

returns map keyed by vulnID and value is a list of ruleIDs that match that vuln

func EvaluatePackage

func EvaluatePackage(rules []CompiledPackageRule, p Package) (bool, string, error)

func IdentityOfRule

func IdentityOfRule(rule models.UpstreamVEXRule) (string, error)

func PrepareVulnsForEval

func PrepareVulnsForEval(ctx context.Context, vulns []models.DependencyVuln) ([]map[string]any, error)

func PrepareVulnsForEvalMap

func PrepareVulnsForEvalMap(ctx context.Context, vulns []models.DependencyVuln) (map[string]map[string]any, error)

func PurlVersionMatches

func PurlVersionMatches(patternPurl, pathPurl packageurl.PackageURL) (bool, error)

func ToCELExpression

func ToCELExpression(cveID string, pattern PathPattern) string

func VexRuleTitle

func VexRuleTitle(cveID string, pattern PathPattern) string

Types

type Action

type Action string
const (
	ActionAllow Action = "allow"
	ActionDeny  Action = "deny"
)

type CompiledPackageRule

type CompiledPackageRule struct {
	Rule    PackageRule
	Program cel.Program
}

func CompilePackageRules

func CompilePackageRules(rules []PackageRule) ([]CompiledPackageRule, error)

func ParsePackageRules

func ParsePackageRules(content string) ([]CompiledPackageRule, error)

type CompiledVEXRule

type CompiledVEXRule struct {
	Program  cel.Program
	CVEScope *string
}

CompiledVEXRule pairs a compiled CEL program with the CVE scope of the rule it came from, so EvalCompiledVEXRules can narrow evaluation to just the vulns sharing that CVE instead of cross-evaluating every rule against every vuln in the batch (a scoped rule's own vuln.cveId == "..." check would reject every mismatch anyway - this just skips paying for that Eval call at all).

type Package

type Package struct {
	Name       string
	Version    string
	Ecosystem  string
	Purl       string
	Registry   string
	Suite      string
	ReleasedAt time.Time
	Publisher  *Publisher
	Provenance *Provenance
}

func (Package) ToCELMap

func (p Package) ToCELMap() map[string]any

type PackageRule

type PackageRule struct {
	Name   string `yaml:"name" validate:"required"`
	Action Action `yaml:"action" validate:"required,oneof=allow deny"`
	Expr   string `yaml:"expr" validate:"required"`
}

type PathPattern

type PathPattern []string

PathPattern represents a path pattern with wildcards. Patterns use suffix matching where "*" can match any number of path elements. A wildcard "*" can appear at any position to match zero or more path elements. Examples:

  • ["pkg:golang/lib@v1.0"] matches paths ending with exactly this element
  • ["*", "pkg:golang/lib@v1.0"] matches paths ending with any elements followed by this element
  • ["*"] matches any path suffix

func (PathPattern) Matches

func (p PathPattern) Matches(path []string, artifactPurls []string) bool

Matches is like matchesSuffix, but first strips a leading pattern element that identifies one of the vulnerability's own artifacts.

VulnerabilityPath is always component-only and never includes the artifact's own identity, but devguard's own exports (CSAF, CycloneDX VEX) always include the artifact as the path's root. A pattern reconstructed from such an export - e.g. a downloaded VEX document being re-uploaded - would otherwise carry that artifact element as its first path segment and never match any real vulnerability path.

Once stripped, the remainder is matched exactly from the start of path (like the ROOT stop-marker case in matchesSuffix), not as a generic suffix: the artifact anchors the pattern to the absolute root of the dependency graph, so a shorter pattern must not match as a mere suffix of a longer, distinct path through a shared component - that per-path distinction is exactly what CSAF's product tree encodes.

func (PathPattern) SoftMatches

func (p PathPattern) SoftMatches(path []string) bool

SoftMatches is Matches for callers that haven't loaded artifacts at all (e.g. crowdsourced-vexing's soft-match phase, run against representative vulns before their real artifacts are known). It always assumes the artifact-anchor element would have matched, since a real vuln always has at least one artifact and none can be ruled out here - so a "no match" from SoftMatches reliably implies Matches would also not match once real artifacts are loaded, but a "match" is only a candidate to confirm.

type Provenance

type Provenance struct {
	SourceRepository string
	Builder          string
}

type Publisher

type Publisher struct {
	Name                    string
	ChangedSinceLastVersion bool
}

Jump to

Keyboard shortcuts

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