license

package
v3.97.0 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const CDXSourceName = "vulnetix-license-analyzer"
View Source
const ExceptionsAPIVersion = "vulnetix.com/v1"

ExceptionsAPIVersion is the apiVersion an exceptions document must declare.

View Source
const ExceptionsKind = "LicenseExceptions"

ExceptionsKind is the kind an exceptions document must declare.

View Source
const PolicyAPIVersion = "vulnetix.com/v1"

PolicyAPIVersion is the apiVersion a policy document must declare.

View Source
const PolicyKind = "LicensePolicy"

PolicyKind is the kind a policy document must declare.

Variables

This section is empty.

Functions

func AllLicenses

func AllLicenses() map[string]LicenseRecord

AllLicenses returns the full embedded SPDX license database.

func BatchFetchGitHubLicenses

func BatchFetchGitHubLicenses(packages []PackageLicense, onProgress func(resolved, total int))

BatchFetchGitHubLicenses resolves licenses for GitHub-hosted packages concurrently. Handles github.com/ prefixed packages (Go), owner/repo packages (GHA, Terraform), and any other package that maps to a GitHub repository.

func BatchFetchLicenses

func BatchFetchLicenses(packages []PackageLicense, onProgress func(resolved, total int))

BatchFetchLicenses resolves licenses for multiple packages concurrently via deps.dev. It modifies the slice in place, setting LicenseSpdxID and LicenseSource for resolved packages.

func BatchFetchRegistryLicenses

func BatchFetchRegistryLicenses(packages []PackageLicense, onProgress func(resolved, total int))

BatchFetchRegistryLicenses resolves licenses for packages whose ecosystems have native registry APIs not covered by deps.dev. Modifies slice in place, setting LicenseSpdxID and LicenseSource = "registry" for resolved packages.

func BuildSARIFFromAnalysis added in v3.7.0

func BuildSARIFFromAnalysis(result *AnalysisResult) ([]SARIFFinding, []SARIFRule)

BuildSARIFFromAnalysis converts the analysis result into SARIFFinding + SARIFRule slices. Each LicenseConflict becomes a finding with a rule id like "license-conflict-incompatible". Findings ([]license.Finding) become rules like "license-policy-{category}" carrying the package PURL and severity.

func CanonicalSPDXID added in v3.41.0

func CanonicalSPDXID(id string) string

CanonicalSPDXID returns the canonical SPDX identifier for a case-insensitive input when it is a recognised single SPDX license, or "" otherwise.

Unlike NormalizeSPDX (which echoes unknown input back), this reports recognisability, so CycloneDX writers can decide whether a value is safe to emit as the schema-constrained license.id versus a free-form license.name. The embedded SPDX database is a subset of the SPDX enum baked into the CycloneDX schema, so a non-empty result is always accepted as license.id.

func ClassifyLicenseText

func ClassifyLicenseText(text string) string

ClassifyLicenseText identifies a license SPDX ID from the full text content. Uses keyword matching — not a full license parser, but handles the vast majority of standard open-source licenses.

func ConflictFindingID added in v3.57.0

func ConflictFindingID(c LicenseConflict) string

ConflictFindingID builds the stable identifier for a license-conflict finding. The license and package pairs are each sorted so that the same conflict discovered from either direction yields one identifier.

func CountFindingsAtOrAbove

func CountFindingsAtOrAbove(findings []Finding, threshold string) int

CountFindingsAtOrAbove counts findings at or above the given severity threshold.

func FetchContainerLicense

func FetchContainerLicense(name, version, ecosystem string) string

FetchContainerLicense attempts to resolve a license for a container image or infrastructure-as-code package. Tries local tools first, then registry APIs.

Handles:

  • Docker/OCI images (podman/docker inspect → labels/annotations → registry)
  • Terraform providers (registry API → GitHub source repo)
  • Nix flakes (nix CLI if available)

func FetchFromEcosystemRegistry

func FetchFromEcosystemRegistry(pkg PackageLicense) string

FetchFromEcosystemRegistry attempts to resolve a license from the package's native ecosystem registry for ecosystems not covered by deps.dev.

func FetchLicenseFromDepsDev

func FetchLicenseFromDepsDev(name, version, ecosystem string) string

FetchLicenseFromDepsDev queries api.deps.dev for a package's license. Returns the SPDX license ID or "" if not found/unsupported.

func FetchLicenseFromGitHub

func FetchLicenseFromGitHub(name, ecosystem string) string

FetchLicenseFromGitHub resolves a license for a GitHub-hosted package. Uses a multi-strategy approach:

  1. GitHub repo API .license.spdx_id field (via gh CLI or REST API)
  2. Dedicated /repos/{owner}/{repo}/license endpoint
  3. Fetch LICENSE/COPYING file content and classify text
  4. Discover license files via directory listing

func FindLicenseInDir

func FindLicenseInDir(dir string) string

FindLicenseInDir searches for a license file in the given directory and classifies it. Works for any ecosystem where deps are on the filesystem.

func FindLicenseInModuleCache

func FindLicenseInModuleCache(moduleName, version string) string

FindLicenseInModuleCache looks for a license file in the Go module cache for the given module and version, reads it, and classifies the license. Returns "" if not found or unclassifiable.

func FindingID added in v3.57.0

func FindingID(category string, pkg PackageLicense) string

FindingID builds the stable identifier for a per-package license finding.

Identifiers must survive across runs: memory reconciliation resolves a finding by noticing its ID has disappeared from the current result set, and the SARIF partialFingerprint is derived from it. A run-local counter would make both meaningless, since the ordinal depends on package iteration order.

The SPDX id is deliberately absent: a package resolves to exactly one license per run, so <category>:<ecosystem>:<package>@<version> is already unique, and omitting it lets legacy counter-keyed memory records be migrated (a FindingRecord stores no license field).

func FindingsToCDXVulnerabilities

func FindingsToCDXVulnerabilities(findings []Finding, packages []PackageLicense) []cdx.Vulnerability

FindingsToCDXVulnerabilities converts license findings to CycloneDX vulnerability entries.

func MarshalSPDXJSON

func MarshalSPDXJSON(doc *SPDXDocument) ([]byte, error)

MarshalSPDXJSON serialises an SPDX document to indented JSON.

func MergeBOM

func MergeBOM(existingPath string, newVulns []cdx.Vulnerability, source string) error

MergeBOM reads an existing BOM from path, replaces all vulnerabilities with the given source name, appends the new vulnerabilities, and writes back. If the file doesn't exist, it creates a minimal BOM with just the new vulnerabilities.

func NormalizeSPDX

func NormalizeSPDX(id string) string

NormalizeSPDX returns the canonical SPDX ID for a case-insensitive input, or the input unchanged if not found in the database.

func ParseSPDXExpression

func ParseSPDXExpression(expr string) []string

ParseSPDXExpression splits a simple SPDX license expression into constituent IDs. Handles "MIT", "MIT OR Apache-2.0", "GPL-2.0-only WITH Classpath-exception-2.0", and parenthesised groups. WITH exceptions are stripped.

func PopulateBOMLicenses

func PopulateBOMLicenses(bomPath string, packages []PackageLicense, groups []scan.ManifestGroup)

PopulateBOMLicenses reads an existing BOM, populates component licenses and the dependency tree, then writes it back. This is used by the standalone license command to enrich an existing BOM without rebuilding it. If the BOM has no components, they are created from the package list.

Types

type AllowList

type AllowList struct {
	Licenses []string `yaml:"licenses"`
}

AllowList is a set of approved SPDX license IDs.

func LoadAllowListFromFile

func LoadAllowListFromFile(path string) (*AllowList, error)

LoadAllowListFromFile reads a YAML allow list file. Expected format:

licenses:
  - MIT
  - Apache-2.0

func ParseAllowListCSV

func ParseAllowListCSV(csv string) *AllowList

ParseAllowListCSV parses a comma-separated list of SPDX IDs.

func (*AllowList) Contains

func (al *AllowList) Contains(spdxID string) bool

Contains returns true if the given SPDX ID is in the allow list.

func (*AllowList) IsActive

func (al *AllowList) IsActive() bool

IsActive returns true if the allow list has entries.

type AnalysisResult

type AnalysisResult struct {
	Mode      string            `json:"mode"`
	Packages  []PackageLicense  `json:"packages"`
	Conflicts []LicenseConflict `json:"conflicts"`
	Findings  []Finding         `json:"findings"`
	Summary   AnalysisSummary   `json:"summary"`
}

AnalysisResult is the complete output of a license analysis run.

func Evaluate

func Evaluate(packages []PackageLicense, cfg EvalConfig) *AnalysisResult

Evaluate runs all license evaluation rules against the detected packages.

type AnalysisSummary

type AnalysisSummary struct {
	TotalPackages  int              `json:"totalPackages"`
	LicenseCounts  map[string]int   `json:"licenseCounts"`
	CategoryCounts map[Category]int `json:"categoryCounts"`
	ConflictCount  int              `json:"conflictCount"`
	FindingsBySev  map[string]int   `json:"findingsBySeverity"`
	OsiApproved    int              `json:"osiApproved"`
	FsfLibre       int              `json:"fsfLibre"`
	Deprecated     int              `json:"deprecated"`
	Unknown        int              `json:"unknown"`

	// Exempted is the count an approved exception covers, and Effective is what
	// remains. The same split VEX uses for vulnerabilities, for the same
	// reason: the number to act on is not the number found.
	Exempted  int `json:"exempted"`
	Effective int `json:"effective"`
	// ExpiredExceptions counts findings whose exception has lapsed. They are
	// live findings; the count exists so a lapse is visible rather than
	// arriving as an unexplained new violation.
	ExpiredExceptions int `json:"expiredExceptions"`
}

AnalysisSummary provides aggregate counts.

type Applied added in v3.97.0

type Applied struct {
	// Exception is the governance metadata.
	Exception Exception
	// Kind is "blanket" or "package".
	Kind string
	// Match describes what the exception was written against.
	Match string
	// Expired reports that the exception has lapsed and did NOT apply.
	Expired bool
}

Applied is a matched exception, with why it matched.

func (Applied) Label added in v3.97.0

func (a Applied) Label() string

Label renders a short attribution for terminal and report output.

type BlanketException added in v3.97.0

type BlanketException struct {
	// License is the SPDX id. Matching is by prefix, so an exception for
	// MPL-2.0 also covers MPL-2.0-no-copyleft-exception: they are the same
	// licence with a variation nobody writes a separate exception for.
	License   string `yaml:"license" json:"license"`
	Exception `yaml:",inline" json:",inline"`
}

BlanketException exempts a licence wherever it is found.

type Category

type Category string

Category classifies a license by its copyleft characteristics.

const (
	CategoryPermissive     Category = "permissive"
	CategoryWeakCopyleft   Category = "weak-copyleft"
	CategoryStrongCopyleft Category = "strong-copyleft"
	CategoryProprietary    Category = "proprietary"
	CategoryPublicDomain   Category = "public-domain"
	CategoryUnknown        Category = "unknown"
)

func ClassifyCategory

func ClassifyCategory(spdxID string) Category

ClassifyCategory returns the license category for a given SPDX ID.

type ConflictSeverity

type ConflictSeverity struct {
	Severity       string
	Description    string
	Recommendation string
}

ConflictSeverity describes a conflict rule result.

func CategoryConflict

func CategoryConflict(cat1, cat2 Category) *ConflictSeverity

CategoryConflict checks if two license categories conflict and returns severity info. Returns nil if the combination is compatible.

func IDConflict

func IDConflict(id1, id2 string) *ConflictSeverity

IDConflict checks for specific SPDX ID pair overrides. Returns nil if no specific rule exists.

type EvalConfig

type EvalConfig struct {
	Mode              string   // "inclusive" or "individual"
	AllowedLicenses   []string // SPDX IDs; empty = no allow list
	SeverityThreshold string   // "critical", "high", "medium", "low"

	// Policy is the declarative licence policy. Nil falls back to
	// DefaultPolicy(), which reproduces the severities the evaluator used
	// before policies existed — so adopting one is a deliberate change rather
	// than something that arrives with an upgrade and turns a build red.
	Policy *Policy
	// Exceptions is the approved-exception set. Nil means no exceptions.
	Exceptions *ExceptionSet
	// Project selects per-project policy overrides, from --project.
	Project string
	// Now is the clock used for exception expiry. Zero means time.Now().
	Now time.Time
}

EvalConfig controls evaluation behaviour.

type EvidenceStep

type EvidenceStep struct {
	Rule     string `json:"rule"`
	Input    string `json:"input"`
	Expected string `json:"expected,omitempty"`
	Actual   string `json:"actual,omitempty"`
	Result   string `json:"result"` // "PASS" or "FAIL"
}

EvidenceStep is one step in a rule evaluation trace.

type Exception added in v3.97.0

type Exception struct {
	// ID is a stable identifier for referring to this exception in a report.
	ID string `yaml:"id,omitempty" json:"id,omitempty"`
	// Reason is why the exception exists. Required: an exception nobody can
	// explain is indistinguishable from a mistake.
	Reason string `yaml:"reason" json:"reason"`
	// Scope narrows the claim, e.g. "vendored, unmodified, dynamically linked".
	Scope string `yaml:"scope,omitempty" json:"scope,omitempty"`
	// Approver is who signed it off.
	Approver string `yaml:"approver,omitempty" json:"approver,omitempty"`
	// ApprovedDate is when, as YYYY-MM-DD.
	ApprovedDate string `yaml:"approvedDate,omitempty" json:"approvedDate,omitempty"`
	// Expires is when the exception lapses, as YYYY-MM-DD. Empty never expires.
	Expires string `yaml:"expires,omitempty" json:"expires,omitempty"`
	// Projects limits the exception to named projects. Empty applies everywhere.
	Projects []string `yaml:"projects,omitempty" json:"projects,omitempty"`
}

Exception is the governance metadata every exception carries.

func (Exception) AppliesToProject added in v3.97.0

func (e Exception) AppliesToProject(project string) bool

AppliesToProject reports whether the exception covers a project.

func (Exception) Expired added in v3.97.0

func (e Exception) Expired(now time.Time) bool

Expired reports whether the exception has lapsed as of now.

An expired exception is not a soft signal: the finding reverts to a violation. That is the whole reason an expiry is worth writing down — an exception that quietly outlives its review is the failure mode this is designed to prevent.

func (Exception) ExpiresAt added in v3.97.0

func (e Exception) ExpiresAt() (time.Time, error)

ExpiresAt parses Expires, returning the zero time when it never expires.

type ExceptionSet added in v3.97.0

type ExceptionSet struct {
	APIVersion string `yaml:"apiVersion" json:"apiVersion"`
	Kind       string `yaml:"kind" json:"kind"`

	// Blanket exempts a licence everywhere it appears.
	Blanket []BlanketException `yaml:"blanket,omitempty" json:"blanket,omitempty"`
	// Packages exempts a specific package, optionally under a specific licence.
	Packages []PackageException `yaml:"packages,omitempty" json:"packages,omitempty"`
}

ExceptionSet is a collection of licence exceptions.

func LoadExceptions added in v3.97.0

func LoadExceptions(path string) (*ExceptionSet, error)

LoadExceptions reads an exception set from a YAML file.

func ParseExceptions added in v3.97.0

func ParseExceptions(data []byte) (*ExceptionSet, error)

ParseExceptions parses an exception document.

func (*ExceptionSet) Expiring added in v3.97.0

func (s *ExceptionSet) Expiring(now time.Time, within time.Duration) []Applied

Expiring returns exceptions lapsing within the given window, soonest first.

An exception that expires without anyone noticing turns into a surprise red build. Being able to ask "what lapses in the next 30 days" is what makes the expiry a review cadence rather than a trap.

func (*ExceptionSet) MarshalYAML added in v3.97.0

func (s *ExceptionSet) MarshalYAML() ([]byte, error)

MarshalYAML renders the exception set as a YAML document.

func (*ExceptionSet) Match added in v3.97.0

func (s *ExceptionSet) Match(pkg PackageLicense, project string, now time.Time) (Applied, bool)

Match finds the exception covering a package, if any.

Returns the applied exception and whether it exempts the finding. An expired exception is returned with Expired set and exempts nothing: the caller reports why the finding is live rather than leaving the user to wonder why their exception stopped working.

func (*ExceptionSet) Validate added in v3.97.0

func (s *ExceptionSet) Validate() error

Validate checks an exception document for structural problems.

type Finding

type Finding struct {
	ID              string         `json:"id"`
	Title           string         `json:"title"`
	Description     string         `json:"description"`
	Severity        string         `json:"severity"`
	Confidence      float64        `json:"confidence"`
	Package         PackageLicense `json:"package"`
	Category        string         `json:"category"` // rule category
	Evidence        []EvidenceStep `json:"evidence"`
	IntroducedPaths [][]string     `json:"introducedPaths,omitempty"`
	PathCount       int            `json:"pathCount,omitempty"`

	// Exempted marks a finding an approved exception covers. Exempted findings
	// are retained and badged, never dropped: a violation count that fell
	// because somebody wrote an exception is a different fact from one that
	// fell because the dependency was removed, and a report that cannot tell
	// them apart is not an audit trail.
	Exempted bool `json:"exempted,omitempty"`
	// ExemptionReason is why the exception exists.
	ExemptionReason string `json:"exemptionReason,omitempty"`
	// ExemptionLabel attributes the exception — its id, approver and expiry.
	ExemptionLabel string `json:"exemptionLabel,omitempty"`
	// ExemptionExpired marks a finding whose exception has lapsed. It is NOT
	// exempted; the field exists so the report can say why an exception the
	// user wrote is no longer working.
	ExemptionExpired bool `json:"exemptionExpired,omitempty"`
}

Finding is a single license issue produced by evaluation.

type LicenseConflict

type LicenseConflict struct {
	Type           string     `json:"type"`     // "incompatible", "copyleft-mixing", "deprecated", "version-incompatible"
	Severity       string     `json:"severity"` // critical, high, medium, low
	License1       string     `json:"license1"`
	License2       string     `json:"license2"`
	Package1       string     `json:"package1"`
	Package2       string     `json:"package2"`
	Description    string     `json:"description"`
	Recommendation string     `json:"recommendation"`
	Package1Paths  [][]string `json:"package1Paths,omitempty"`
	Package2Paths  [][]string `json:"package2Paths,omitempty"`
}

LicenseConflict describes an incompatibility between two licenses.

type LicenseRecord

type LicenseRecord struct {
	SpdxID        string   `json:"spdxId" yaml:"spdx_id"`
	Name          string   `json:"name" yaml:"name"`
	Category      Category `json:"category" yaml:"category"`
	IsOsiApproved bool     `json:"isOsiApproved" yaml:"osi_approved"`
	IsFsfLibre    bool     `json:"isFsfLibre" yaml:"fsf_libre"`
	IsDeprecated  bool     `json:"isDeprecated" yaml:"deprecated"`
}

LicenseRecord describes a single SPDX license entry.

func LookupSPDX

func LookupSPDX(id string) *LicenseRecord

LookupSPDX returns the license record for the given SPDX ID, or nil if not found. Lookup is case-insensitive.

type PackageException added in v3.97.0

type PackageException struct {
	// Purl matches the package, with '*' as a wildcard segment. A glob is the
	// useful form: an organisation vendoring every hashicorp module writes
	// pkg:golang/github.com/hashicorp/* once rather than an entry per module.
	Purl string `yaml:"purl,omitempty" json:"purl,omitempty"`
	// Name matches the package name as a substring, for ecosystems where the
	// short name and the fully-qualified module path are both in use.
	Name string `yaml:"name,omitempty" json:"name,omitempty"`
	// License narrows the exception to one licence. Empty exempts the package
	// whatever licence it turns out to carry, which is a broader claim and
	// should be rarer.
	License   string `yaml:"license,omitempty" json:"license,omitempty"`
	Exception `yaml:",inline" json:",inline"`
}

PackageException exempts one package.

type PackageLicense

type PackageLicense struct {
	PackageName     string         `json:"packageName"`
	PackageVersion  string         `json:"packageVersion"`
	Ecosystem       string         `json:"ecosystem"`
	Scope           string         `json:"scope"`
	LicenseSpdxID   string         `json:"licenseSpdxId"`
	LicenseSource   string         `json:"licenseSource"` // "manifest", "lockfile", "embedded-db"
	SourceFile      string         `json:"sourceFile"`
	IsDirect        bool           `json:"isDirect"`
	GitHubURL       string         `json:"-"` // optional: "owner/repo" from manifest, used for license resolution
	Record          *LicenseRecord `json:"record,omitempty"`
	IntroducedPaths [][]string     `json:"introducedPaths,omitempty"`
	PathCount       int            `json:"pathCount,omitempty"`
}

PackageLicense ties a detected package to its resolved license.

func DetectLicenses

func DetectLicenses(packages []scan.ScopedPackage, groups []scan.ManifestGroup) []PackageLicense

DetectLicenses takes already-parsed packages and resolves their licenses. It reads the original manifest files to extract license fields where possible, falling back to the embedded SPDX database for well-known packages. When groups is non-nil, dependency paths are computed for each package.

type Policy added in v3.97.0

type Policy struct {
	APIVersion string `yaml:"apiVersion" json:"apiVersion"`
	Kind       string `yaml:"kind" json:"kind"`

	// Categories reassigns SPDX ids to categories, overriding the embedded
	// classification. An organisation's counsel may classify a licence
	// differently from the default, and that decision belongs in their policy
	// rather than in a fork of this CLI.
	Categories map[Category][]string `yaml:"categories,omitempty" json:"categories,omitempty"`

	// Severity maps a category to the severity of a finding against it.
	Severity map[Category]string `yaml:"severity,omitempty" json:"severity,omitempty"`

	// Unknown says what to do about an unresolved licence.
	Unknown UnknownHandling `yaml:"unknown,omitempty" json:"unknown,omitempty"`

	// Scopes says how each dependency scope is treated.
	Scopes map[string]ScopeHandling `yaml:"scopes,omitempty" json:"scopes,omitempty"`

	// Projects holds per-project overrides, keyed on the --project label. A
	// monorepo's payment service and its docs site have different obligations,
	// and forcing them to share one threshold means the stricter one wins
	// everywhere or the looser one wins everywhere.
	Projects map[string]ProjectPolicy `yaml:"projects,omitempty" json:"projects,omitempty"`
	// contains filtered or unexported fields
}

Policy is a declarative licence policy.

func DefaultPolicy added in v3.97.0

func DefaultPolicy() *Policy

DefaultPolicy is the policy applied when none is supplied.

It reproduces exactly what the evaluator did before policies existed, so adopting a policy file is a change a team makes deliberately rather than one that arrives with an upgrade and turns their build red. Two consequences are deliberate and easy to get wrong:

  • Only strong copyleft carries a severity. Proprietary arguably should too, but it did not before, and quietly adding it would fail builds on an upgrade for a decision nobody made.
  • No scope is ignored. Scope filtering is genuinely useful — a copyleft build tool that never ships is not a licence obligation — but turning it on by default would silently stop reporting findings that were being reported yesterday, which is the more dangerous direction to be wrong in.

A policy file opts into both. RecommendedPolicy() is the starting point.

func LoadPolicy added in v3.97.0

func LoadPolicy(path string) (*Policy, error)

LoadPolicy reads a policy from a YAML file.

func ParsePolicy added in v3.97.0

func ParsePolicy(data []byte) (*Policy, error)

ParsePolicy parses a policy document, filling defaults for absent fields.

func RecommendedPolicy added in v3.97.0

func RecommendedPolicy() *Policy

RecommendedPolicy is the starting point `license policy init` writes.

Unlike DefaultPolicy it makes the judgements a team adopting a policy generally wants: proprietary licences are a finding, network copyleft is critical because the obligation triggers on use rather than distribution, and dependencies that are never shipped are out of scope.

func (*Policy) CategoryFor added in v3.97.0

func (p *Policy) CategoryFor(spdxID string, fallback Category) Category

CategoryFor returns the category for an SPDX id under this policy.

A policy override wins over the embedded classification, which is the point: the embedded database is a reasonable default, not an authority on what a particular organisation has decided about a particular licence.

func (*Policy) EvaluatesScope added in v3.97.0

func (p *Policy) EvaluatesScope(scope, project string) bool

EvaluatesScope reports whether a dependency scope is in scope for the policy.

func (*Policy) MarshalYAML added in v3.97.0

func (p *Policy) MarshalYAML() ([]byte, error)

MarshalYAML renders the policy as a YAML document.

func (*Policy) SeverityFor added in v3.97.0

func (p *Policy) SeverityFor(cat Category, project string) string

SeverityFor returns the severity a category carries, honouring per-project overrides. An empty result means the category produces no finding.

func (*Policy) UnknownFor added in v3.97.0

func (p *Policy) UnknownFor(project string) UnknownHandling

UnknownFor returns the unknown-licence handling, honouring project overrides.

func (*Policy) Validate added in v3.97.0

func (p *Policy) Validate() error

Validate checks a policy document for structural problems.

type ProjectPolicy added in v3.97.0

type ProjectPolicy struct {
	Severity map[Category]string      `yaml:"severity,omitempty" json:"severity,omitempty"`
	Unknown  UnknownHandling          `yaml:"unknown,omitempty" json:"unknown,omitempty"`
	Scopes   map[string]ScopeHandling `yaml:"scopes,omitempty" json:"scopes,omitempty"`
}

ProjectPolicy overrides parts of the policy for one project.

type RepoLicenseHit added in v3.7.0

type RepoLicenseHit struct {
	SPDXID      string `json:"spdxId,omitempty"`
	Name        string `json:"name,omitempty"`
	URL         string `json:"url,omitempty"`
	Source      string `json:"source,omitempty"`          // "file:LICENSE" | "manifest:package.json"
	Acknowledge string `json:"acknowledgement,omitempty"` // "declared" | "concluded"
	Text        string `json:"text,omitempty"`            // first N bytes of license text
}

RepoLicenseHit mirrors the shape vdb-api expects on CliEnv.Licenses.

func DetectRepoLicense added in v3.7.0

func DetectRepoLicense(repoRoot string) []RepoLicenseHit

DetectRepoLicense scans the given repo root for license signals. Returns one hit per distinct (SPDX, source) tuple. Always returns nil rather than an error on read failure — license detection is best-effort context.

type SARIFFinding added in v3.7.0

type SARIFFinding struct {
	RuleID      string
	RuleName    string
	Message     string
	Severity    string
	Level       string
	ArtifactURI string
	PackagePurl string
	Fingerprint string
	Tags        []string
}

SARIFFinding mirrors sast.Finding (kept local so this package does not depend on internal/sast). The cmd layer converts these into the typed vdb.CliSARIFFinding shape before posting.

type SARIFRule added in v3.7.0

type SARIFRule struct {
	ID       string
	Name     string
	Severity string
	Tags     []string
}

SARIFRule mirrors sast.RuleMetadata's relevant fields.

type SPDXChecksum added in v3.97.0

type SPDXChecksum struct {
	Algorithm     string `json:"algorithm"`
	ChecksumValue string `json:"checksumValue"`
}

SPDXChecksum is a package checksum entry.

type SPDXCreationInfo

type SPDXCreationInfo struct {
	Created            string   `json:"created"`
	Creators           []string `json:"creators"`
	LicenseListVersion string   `json:"licenseListVersion,omitempty"`
	Comment            string   `json:"comment,omitempty"`
}

SPDXCreationInfo describes when and by whom the SPDX document was created.

type SPDXDocument

type SPDXDocument struct {
	SPDXVersion             string                 `json:"spdxVersion"`
	DataLicense             string                 `json:"dataLicense"`
	SPDXID                  string                 `json:"SPDXID"`
	Name                    string                 `json:"name"`
	DocumentNamespace       string                 `json:"documentNamespace"`
	CreationInfo            SPDXCreationInfo       `json:"creationInfo"`
	Packages                []SPDXPackage          `json:"packages"`
	Relationships           []SPDXRelationship     `json:"relationships,omitempty"`
	ExtractedLicensingInfos []SPDXExtractedLicense `json:"extractedLicensingInfos,omitempty"`
	DocumentDescribes       []string               `json:"documentDescribes,omitempty"`
	Comment                 string                 `json:"comment,omitempty"`
}

SPDXDocument represents an SPDX 2.x JSON document.

The fields BuildSPDXDocument writes are the required core; the rest carry `omitempty` and exist for the read side, so a document this package builds serialises exactly as it did before they were added. internal/bom parses third-party SPDX (Syft, BuildKit, cdxgen) through this same struct set — dropping supplier and checksum data on the way in would leave the SBOM quality check unable to see fields that are demonstrably present.

func BuildSPDXDocument

func BuildSPDXDocument(result *AnalysisResult, name string) *SPDXDocument

BuildSPDXDocument creates an SPDX 2.3 JSON document from license analysis results.

type SPDXExternalRef

type SPDXExternalRef struct {
	ReferenceCategory string `json:"referenceCategory"`
	ReferenceType     string `json:"referenceType"`
	ReferenceLocator  string `json:"referenceLocator"`
}

SPDXExternalRef is a package external reference.

type SPDXExtractedLicense

type SPDXExtractedLicense struct {
	LicenseID     string `json:"licenseId"`
	ExtractedText string `json:"extractedText"`
	Name          string `json:"name"`
}

SPDXExtractedLicense captures non-standard license text.

type SPDXPackage

type SPDXPackage struct {
	SPDXID           string            `json:"SPDXID"`
	Name             string            `json:"name"`
	VersionInfo      string            `json:"versionInfo,omitempty"`
	DownloadLocation string            `json:"downloadLocation"`
	LicenseConcluded string            `json:"licenseConcluded"`
	LicenseDeclared  string            `json:"licenseDeclared"`
	CopyrightText    string            `json:"copyrightText"`
	FilesAnalyzed    bool              `json:"filesAnalyzed"`
	ExternalRefs     []SPDXExternalRef `json:"externalRefs,omitempty"`

	// Read-side fields — see the SPDXDocument doc comment.
	Supplier              string         `json:"supplier,omitempty"`
	Originator            string         `json:"originator,omitempty"`
	Homepage              string         `json:"homepage,omitempty"`
	Description           string         `json:"description,omitempty"`
	Summary               string         `json:"summary,omitempty"`
	SourceInfo            string         `json:"sourceInfo,omitempty"`
	PackageFileName       string         `json:"packageFileName,omitempty"`
	PrimaryPackagePurpose string         `json:"primaryPackagePurpose,omitempty"`
	Checksums             []SPDXChecksum `json:"checksums,omitempty"`
}

SPDXPackage is an SPDX package entry.

type SPDXRelationship

type SPDXRelationship struct {
	Element        string `json:"spdxElementId"`
	RelType        string `json:"relationshipType"`
	RelatedElement string `json:"relatedSpdxElement"`
	Comment        string `json:"comment,omitempty"`
}

SPDXRelationship defines a relationship between SPDX elements.

type ScopeHandling added in v3.97.0

type ScopeHandling string

ScopeHandling says how a dependency scope is treated.

const (
	// ScopeEvaluate applies the policy to this scope.
	ScopeEvaluate ScopeHandling = "evaluate"
	// ScopeIgnore skips it. Development and test dependencies are not
	// distributed, so a copyleft build tool is usually not a licence obligation.
	ScopeIgnore ScopeHandling = "ignore"
)

type UnknownHandling added in v3.97.0

type UnknownHandling string

UnknownHandling says what to do about a licence that could not be resolved.

const (
	// UnknownWarn reports unresolved licences without failing. The default: an
	// unresolved licence is a gap in the data, not evidence of a violation, and
	// failing on it would make the policy unusable on any real dependency tree.
	UnknownWarn UnknownHandling = "warn"
	// UnknownFail treats an unresolved licence as a violation. For teams whose
	// compliance position is that an unidentified licence cannot be shipped.
	UnknownFail UnknownHandling = "fail"
	// UnknownIgnore drops unresolved licences entirely.
	UnknownIgnore UnknownHandling = "ignore"
)

Jump to

Keyboard shortcuts

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