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
- Variables
- func CompileRules(ctx context.Context, rules []models.UpstreamVEXRule) (map[string]CompiledRule, error)
- func CompileRulesForSoftMatching(ctx context.Context, rules []models.UpstreamVEXRule) (map[string]CompiledRule, error)
- func EvalCompiledRules(ctx context.Context, compiled map[string]CompiledRule, ...) (map[string][]string, error)
- func IdentityOfRule(rule models.UpstreamVEXRule) (string, error)
- func PrepareVulnsForEval(ctx context.Context, vulns []models.DependencyVuln) ([]map[string]any, error)
- func PrepareVulnsForEvalMap(ctx context.Context, vulns []models.DependencyVuln) (map[string]map[string]any, error)
- func PurlVersionMatches(patternPurl, pathPurl packageurl.PackageURL) (bool, error)
- func ToCELExpression(cveID string, pattern PathPattern) string
- func VexRuleTitle(cveID string, pattern PathPattern) string
- type CompiledRule
- type PathPattern
Constants ¶
const (
// PathPatternWildcard matches any path element at that position
PathPatternWildcard = "*"
)
PathPattern wildcard for VEX rules
Variables ¶
var CelEnv = sync.OnceValues(func() (*cel.Env, error) { return newCelEnv(func(pattern, path, artifactPurls []string) bool { return PathPattern(pattern).Matches(path, artifactPurls) }) })
CelEnv is the CEL environment used for real VEX rule matching, where the vuln's real artifacts are known.
var SoftMatchCelEnv = sync.OnceValues(func() (*cel.Env, error) { return newCelEnv(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.
Functions ¶
func CompileRules ¶
func CompileRules(ctx context.Context, rules []models.UpstreamVEXRule) (map[string]CompiledRule, error)
CompileRules 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 CompileRulesForSoftMatching ¶ added in v1.12.5
func CompileRulesForSoftMatching(ctx context.Context, rules []models.UpstreamVEXRule) (map[string]CompiledRule, error)
CompileRulesForSoftMatching is CompileRules against SoftMatchCelEnv, for crowdsourced-vexing's soft-match phase over vulns without real artifacts.
func EvalCompiledRules ¶
func EvalCompiledRules(ctx context.Context, compiled map[string]CompiledRule, 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 IdentityOfRule ¶
func IdentityOfRule(rule models.UpstreamVEXRule) (string, error)
func PrepareVulnsForEval ¶
func PrepareVulnsForEvalMap ¶ added in v1.12.5
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 CompiledRule ¶ added in v1.12.3
CompiledRule pairs a compiled CEL program with the CVE scope of the rule it came from, so EvalCompiledRules 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 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 ¶ added in v1.12.5
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.