Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
4490f72
inital sbomqs:2.0 library and scoring
viveksahu26 Oct 1, 2025
811d2c6
add scoring capbility and related functionality
viveksahu26 Oct 3, 2025
846a248
refractor and some feature, category added
viveksahu26 Oct 3, 2025
d936d26
add support for url and folder of sboms
viveksahu26 Oct 6, 2025
5f0536e
restructured code
viveksahu26 Oct 6, 2025
80b4b1f
add formula tests
viveksahu26 Oct 6, 2025
72ad642
add category filtering test
viveksahu26 Oct 7, 2025
7d3f0bc
add all basecategory
viveksahu26 Oct 7, 2025
55a6934
refractors and added extractors
viveksahu26 Oct 7, 2025
c274768
add identification,provenance extractors with tests
viveksahu26 Oct 8, 2025
9abf3f1
small fix
viveksahu26 Oct 8, 2025
3c28e4c
add integrity extractor
viveksahu26 Oct 8, 2025
913b9fc
add integrity extractor test
viveksahu26 Oct 10, 2025
eb5fd86
add completeness extractor
viveksahu26 Oct 10, 2025
9218992
add completeness extractor test
viveksahu26 Oct 11, 2025
613b96c
other updates
viveksahu26 Oct 11, 2025
51f2428
fix import cycle issue
viveksahu26 Oct 11, 2025
11af30e
add licensing extractor and it's test
viveksahu26 Oct 13, 2025
d91f090
make local var global
viveksahu26 Oct 13, 2025
ade7ad3
fix restrictive license fn, add tests
viveksahu26 Oct 14, 2025
b0d4547
add vuln extractors and it's tests
viveksahu26 Oct 14, 2025
27c4d5e
add schemaValidation method
viveksahu26 Oct 14, 2025
a92afd5
add structural extracts and it's tests
viveksahu26 Oct 14, 2025
1a66dbc
initiated with profiles config
viveksahu26 Oct 15, 2025
4a50617
add profiles
viveksahu26 Oct 24, 2025
97c255a
add oct profile
viveksahu26 Oct 24, 2025
2f328e0
update feature function
viveksahu26 Oct 24, 2025
e0beef6
refractor and centralized compre, profile specs
viveksahu26 Oct 27, 2025
8bdba6a
refractor profile logic
viveksahu26 Oct 28, 2025
7280e7c
add reporter for v2
viveksahu26 Oct 30, 2025
68baea4
add profile reporter for v2
viveksahu26 Oct 31, 2025
89494ef
update profiles
viveksahu26 Nov 3, 2025
f4d7711
fix and update profiles functionality
viveksahu26 Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions cmd/score.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ type userCmd struct {

signature string
publicKey string

// profiles
profile []string

// Old scoring
legacy bool
}

// scoreCmd represents the score command
Expand Down Expand Up @@ -242,6 +248,8 @@ func toUserCmd(cmd *cobra.Command, args []string) *userCmd {
uCmd.color, _ = cmd.Flags().GetBool("color")
uCmd.signature, _ = cmd.Flags().GetString("sig")
uCmd.publicKey, _ = cmd.Flags().GetString("pub")
uCmd.legacy, _ = cmd.Flags().GetBool("legacy")
uCmd.profile, _ = cmd.Flags().GetStringSlice("profile")

if reportFormat != "" {
uCmd.json = strings.ToLower(reportFormat) == "json"
Expand Down Expand Up @@ -269,6 +277,8 @@ func toEngineParams(uCmd *userCmd) *engine.Params {
ConfigPath: uCmd.configPath,
Signature: uCmd.signature,
PublicKey: uCmd.publicKey,
Legacy: uCmd.legacy,
Profiles: uCmd.profile,
}
}

Expand Down Expand Up @@ -363,4 +373,7 @@ func init() {

scoreCmd.Flags().StringP("sig", "v", "", "signature of sbom")
scoreCmd.Flags().StringP("pub", "p", "", "public key of sbom")

scoreCmd.Flags().StringSlice("profile", nil, "Profiles to run (comma-separated or repeatable)")
scoreCmd.Flags().BoolP("legacy", "e", false, "legacy")
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/charmbracelet/fang v0.4.1
github.com/github/go-spdx/v2 v2.3.3
github.com/google/uuid v1.6.0
github.com/knqyf263/go-cpe v0.0.0-20230627041855-cb0794d06872
github.com/maxbrunsfeld/counterfeiter/v6 v6.12.0
github.com/olekukonko/tablewriter v0.0.5
github.com/package-url/packageurl-go v0.1.3
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/knqyf263/go-cpe v0.0.0-20230627041855-cb0794d06872 h1:snH0nDYi3kizy9vxYBhZm5KXkGt9VXdGEtr6/1SGUqY=
github.com/knqyf263/go-cpe v0.0.0-20230627041855-cb0794d06872/go.mod h1:4cVhzV/TndScEg4xMtSo3TTz3cMFhEAvhAA4igAyXZY=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
Expand Down Expand Up @@ -120,6 +122,7 @@ github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/
github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoXLtmE3I0PLs=
github.com/package-url/packageurl-go v0.1.3/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
12 changes: 6 additions & 6 deletions pkg/compliance/bsi.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,10 @@ func bsiSpec(doc sbom.Document) *db.Record {
result := ""
score := 0.0

if vToLower == "spdx" {
if vToLower == string(sbom.SBOMSpecSPDX) {
result = v
score = 10.0
} else if vToLower == "cyclonedx" {
} else if vToLower == string(sbom.SBOMSpecCDX) {
result = v
score = 10.0
}
Expand All @@ -141,7 +141,7 @@ func bsiSpecVersion(doc sbom.Document) *db.Record {
result := ""
score := 0.0

if spec == "spdx" {
if spec == string(sbom.SBOMSpecSPDX) {
count := lo.Count(validBsiSpdxVersions, version)
validate := lo.Contains(validSpdxVersion, version)
if validate {
Expand All @@ -153,7 +153,7 @@ func bsiSpecVersion(doc sbom.Document) *db.Record {
score = 0.0
}
}
} else if spec == "cyclonedx" {
} else if spec == string(sbom.SBOMSpecCDX) {
count := lo.Count(validBsiCdxVersions, version)
if count > 0 {
result = version
Expand Down Expand Up @@ -424,7 +424,7 @@ func bsiComponentDepth(doc sbom.Document, component sbom.GetComponent) *db.Recor
}

func bsiComponentLicense(component sbom.GetComponent) *db.Record {
licenses := component.Licenses()
licenses := component.GetLicenses()
score := 0.0

if len(licenses) == 0 {
Expand Down Expand Up @@ -487,7 +487,7 @@ func bsiComponentDownloadURL(component sbom.GetComponent) *db.Record {
}

func bsiComponentSourceCodeURL(component sbom.GetComponent) *db.Record {
result := component.SourceCodeURL()
result := component.GetSourceCodeURL()

if result != "" {
return db.NewRecordStmtOptional(COMP_SOURCE_CODE_URL, common.UniqueElementID(component), result, 10.0)
Expand Down
10 changes: 5 additions & 5 deletions pkg/compliance/bsiV2.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func bsiV2SpecVersion(doc sbom.Document) *db.Record {

result, score := "", 0.0

if spec == "spdx" {
if spec == string(sbom.SBOMSpecSPDX) {
count := lo.Count(validBsiV2SpdxVersions, version)
validate := lo.Contains(validSpdxVersion, version)
if validate {
Expand All @@ -151,7 +151,7 @@ func bsiV2SpecVersion(doc sbom.Document) *db.Record {
score = 0.0
}
}
} else if spec == "cyclonedx" {
} else if spec == string(sbom.SBOMSpecCDX) {
count := lo.Count(validBsiV2CdxVersions, version)
if count > 0 {
result = version
Expand Down Expand Up @@ -213,9 +213,9 @@ func bsiV2ComponentAssociatedLicense(doc sbom.Document, component sbom.GetCompon
spec := doc.Spec().GetSpecType()

var licenses []licenses.License
if spec == "cyclonedx" {
licenses = component.Licenses()
} else if spec == "spdx" {
if spec == string(sbom.SBOMSpecCDX) {
licenses = component.GetLicenses()
} else if spec == string(sbom.SBOMSpecSPDX) {
licenses = component.ConcludedLicenses()
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/compliance/fsct/fsct.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ func fsctPackageDependencies(doc sbom.Document, component sbom.GetComponent) *db
func fsctPackageLicense(component sbom.GetComponent) *db.Record {
result, score, maturity := "", 0.0, "None"

licenses := component.Licenses()
licenses := component.GetLicenses()
if len(licenses) == 0 {
return db.NewRecordStmt(COMP_LICENSE, common.UniqueElementID(component), result, score, maturity)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/compliance/ntia.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func ntiaSbomCreator(doc sbom.Document) *db.Record {
result, score := "", SCORE_ZERO

switch spec {
case "spdx":
case string(sbom.SBOMSpecSPDX):
if tools := doc.Tools(); tools != nil {
if toolResult, found := getToolInfo(tools); found {
result = toolResult
Expand All @@ -110,7 +110,7 @@ func ntiaSbomCreator(doc sbom.Document) *db.Record {
break
}
}
case "cyclonedx":
case string(sbom.SBOMSpecCDX):
if authors := doc.Authors(); authors != nil {
if authorResult, found := getAuthorInfo(authors); found {
result = authorResult
Expand Down
2 changes: 1 addition & 1 deletion pkg/compliance/oct.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func octSpec(doc sbom.Document) *db.Record {
result := ""
score := 0.0

if vToLower == "spdx" {
if vToLower == string(sbom.SBOMSpecSPDX) {
result = v
score = 10.0
} else {
Expand Down
46 changes: 45 additions & 1 deletion pkg/engine/score.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ import (
"github.com/interlynk-io/sbomqs/pkg/compliance/common"
"github.com/interlynk-io/sbomqs/pkg/logger"
"github.com/interlynk-io/sbomqs/pkg/reporter"
v2 "github.com/interlynk-io/sbomqs/pkg/reporter/v2"
"github.com/interlynk-io/sbomqs/pkg/sbom"
"github.com/interlynk-io/sbomqs/pkg/scorer"
"github.com/interlynk-io/sbomqs/pkg/scorer/v2/config"
score "github.com/interlynk-io/sbomqs/pkg/scorer/v2/score"

"github.com/spf13/afero"
)

Expand Down Expand Up @@ -66,6 +70,9 @@ type Params struct {
Signature string
PublicKey string
Blob string

Legacy bool
Profiles []string
}

func Run(ctx context.Context, ep *Params) error {
Expand All @@ -77,7 +84,44 @@ func Run(ctx context.Context, ep *Params) error {
log.Fatal("path is required")
}

return handlePaths(ctx, ep)
if ep.Legacy {
return handlePaths(ctx, ep)
}

return scored(ctx, ep)
}

func scored(ctx context.Context, ep *Params) error {
log := logger.FromContext(ctx)
log.Debugf("starting engine to score v2")

cfg := config.Config{
Categories: ep.Categories,
Features: ep.Features,
ConfigFile: ep.ConfigPath,
Profile: ep.Profiles,
}

results, err := score.ScoreSBOM(ctx, cfg, ep.Path)
if err != nil {
return err
}

reportFormat := "detailed"
if ep.Basic {
reportFormat = "basic"
}

if ep.JSON {
reportFormat = "json"
}

nr := v2.NewReport(ctx, results, reportFormat)
nr.Report()

return nil

// print the score
}

func handleURL(path string) (string, string, error) {
Expand Down
18 changes: 16 additions & 2 deletions pkg/licenses/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ func LookupSpdxLicense(licenseKey string) (License, error) {
return nil, errors.New("license not found")
}

license = overlayRestrictiveFromAboutCode(license)

return license, nil
}

Expand Down Expand Up @@ -183,14 +185,14 @@ func LookupExpression(expression string, customLicenses []License) []License {
continue
}

//if custom license list is provided use that.
// if custom license list is provided use that.
license, err = customLookup(trimLicenseKey)
if err == nil {
licenses = append(licenses, license)
continue
}

//if nothing else this license is custom
// if nothing else this license is custom
licenses = append(licenses, CreateCustomLicense(trimLicenseKey, trimLicenseKey))
}

Expand All @@ -210,3 +212,15 @@ func CreateCustomLicense(id, name string) License {
source: "custom",
}
}

// overlayRestrictiveFromAboutCode sets spdx.restrictive to true if AboutCode
// metadata marks the same license ID as restrictive. No other fields are changed.
func overlayRestrictiveFromAboutCode(spdx meta) meta {
if spdx.restrictive {
return spdx
}
if ac, ok := licenseListAboutCode[spdx.short]; ok && ac.restrictive {
spdx.restrictive = true
}
return spdx
}
12 changes: 6 additions & 6 deletions pkg/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ func evaluateCompWithUniqID(comp sbom.GetComponent) (bool, string, error) {

// evaluateCompWithValidLicenses evaluates if the component has valid licenses
func evaluateCompWithValidLicenses(comp sbom.GetComponent) (bool, string, error) {
licenses := comp.Licenses()
licenses := comp.GetLicenses()
if len(licenses) == 0 {
return false, "", nil
}
Expand Down Expand Up @@ -518,7 +518,7 @@ func evaluateCompWithMultiVulnLookupID(comp sbom.GetComponent) (bool, string, er

// evaluateCompWithDeprecatedLicenses evaluates if the component has any deprecated licenses
func evaluateCompWithDeprecatedLicenses(comp sbom.GetComponent) (bool, string, error) {
licenses := comp.Licenses()
licenses := comp.GetLicenses()
if len(licenses) == 0 {
return false, "", nil
}
Expand Down Expand Up @@ -550,7 +550,7 @@ func evaluateCompWithPrimaryPurpose(doc sbom.Document, comp sbom.GetComponent) (

// evaluateCompWithRestrictedLicenses evaluates if the component has any restrictive licenses
func evaluateCompWithRestrictedLicenses(comp sbom.GetComponent) (bool, string, error) {
licenses := comp.Licenses()
licenses := comp.GetLicenses()
if len(licenses) == 0 {
return false, "", nil
}
Expand Down Expand Up @@ -593,7 +593,7 @@ func evaluateCompWithChecksums(comp sbom.GetComponent) (bool, string, error) {

// evaluateCompWithLicenses
func evaluateCompWithLicenses(comp sbom.GetComponent) (bool, string, error) {
licenses := comp.Licenses()
licenses := comp.GetLicenses()
if len(licenses) == 0 {
return false, "", nil
}
Expand Down Expand Up @@ -639,7 +639,7 @@ func evaluateCompWithSourceCodeURI(doc sbom.Document, comp sbom.GetComponent) (b
return false, "source code URI is not supported for SPDX documents", nil
}

sourceCodeURI := comp.SourceCodeURL()
sourceCodeURI := comp.GetSourceCodeURL()
if sourceCodeURI != "" {
return true, sourceCodeURI, nil
}
Expand Down Expand Up @@ -688,7 +688,7 @@ func evaluateCompWithAssociatedLicense(doc sbom.Document, comp sbom.GetComponent
} else if spec == "cyclonedx" {
var associatedLicense []string

for _, l := range comp.Licenses() {
for _, l := range comp.GetLicenses() {
if l != nil {
associatedLicense = append(associatedLicense, l.Name())
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/policy/extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ func (extractor *Extractor) MapFieldWithFunction(ctx context.Context) {

extractor.compGetters["license"] = func(c sbom.GetComponent) []string {
licenses := []string{}
if len(c.Licenses()) == 0 {
if len(c.GetLicenses()) == 0 {
licenses = append(licenses, "NOASSERTION")
}

for _, l := range c.Licenses() {
for _, l := range c.GetLicenses() {
// preferring ID instead of Name, coz, user prefer ID over names.
if ln := l.ShortID(); ln != "" {
licenses = append(licenses, ln)
Expand Down
Loading
Loading