From 761f1ea8cfc00db225c0b62f1de3f13476acf5e0 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Tue, 17 Mar 2026 18:22:16 +0200 Subject: [PATCH 1/4] fix go remediation normalization --- utils/xray/remediation/cdxremediation.go | 7 ++- utils/xray/remediation/cdxremediation_test.go | 48 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/utils/xray/remediation/cdxremediation.go b/utils/xray/remediation/cdxremediation.go index cf0c44405..b3df11bbd 100644 --- a/utils/xray/remediation/cdxremediation.go +++ b/utils/xray/remediation/cdxremediation.go @@ -2,6 +2,7 @@ package remediation import ( "fmt" + "strings" "github.com/CycloneDX/cyclonedx-go" @@ -58,6 +59,10 @@ func matchVulnerabilityToRemediationOptions(bom *cyclonedx.BOM, vulnerability *c } } +func normalizeVersion(version string) string { + return strings.TrimPrefix(version, "v") +} + func getAffectComponentCveRemediationStepsByFixedVersion(cve string, component cyclonedx.Component, cveRemediationOptions []utils.Option, strategy utils.FixStrategy) (steps []utils.OptionStep) { for _, cveRemediationOption := range cveRemediationOptions { if cveRemediationOption.Type != utils.InLock { @@ -78,7 +83,7 @@ func getAffectComponentCveRemediationStepsByFixedVersion(cve string, component c continue } // We only want FixVersion step type - if step.StepType == utils.FixVersion && step.PkgVersion.Name == component.Name && step.PkgVersion.Version == component.Version { + if step.StepType == utils.FixVersion && step.PkgVersion.Name == component.Name && normalizeVersion(step.PkgVersion.Version) == normalizeVersion(component.Version) { steps = append(steps, step) } } diff --git a/utils/xray/remediation/cdxremediation_test.go b/utils/xray/remediation/cdxremediation_test.go index 4830ab562..1b21fbbdb 100644 --- a/utils/xray/remediation/cdxremediation_test.go +++ b/utils/xray/remediation/cdxremediation_test.go @@ -441,6 +441,54 @@ func TestMatchVulnerabilityToRemediationOptions(t *testing.T) { expectedAffectedVersions: nil, description: "Should ignore remediation steps when component name doesn't match", }, + { + name: "Go component with v-prefix version mismatch between API and BOM", + bom: &cyclonedx.BOM{ + Components: &[]cyclonedx.Component{ + { + BOMRef: "golang-component-ref", + Name: "golang.org/x/crypto", + Version: "0.33.0", + }, + }, + }, + vulnerability: &cyclonedx.Vulnerability{ + ID: "CVE-2023-1234", + Affects: &[]cyclonedx.Affects{ + { + Ref: "golang-component-ref", + }, + }, + }, + remediationOptions: utils.CveRemediationResponse{ + "CVE-2023-1234": []utils.Option{ + { + Type: utils.InLock, + Steps: map[utils.FixStrategy][]utils.OptionStep{ + utils.QuickestFixStrategy: { + { + StepType: utils.FixVersion, + PkgVersion: utils.PackageVersionKey{ + Name: "golang.org/x/crypto", + Version: "v0.33.0", + }, + UpgradeTo: utils.PackageVersionKey{ + Version: "v0.40.0", + }, + }, + }, + }, + }, + }, + }, + expectedAffectedVersions: []cyclonedx.AffectedVersions{ + { + Version: "v0.40.0", + Status: cyclonedx.VulnerabilityStatusNotAffected, + }, + }, + description: "Should match Go component when API returns v-prefixed version but BOM stores without prefix", + }, { name: "Component version mismatch should be ignored", bom: &cyclonedx.BOM{ From 0edf1b3225493658d611ce68a304368991482408 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 18 Mar 2026 13:37:37 +0200 Subject: [PATCH 2/4] added note --- utils/xray/remediation/cdxremediation.go | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/xray/remediation/cdxremediation.go b/utils/xray/remediation/cdxremediation.go index b3df11bbd..88ba9905b 100644 --- a/utils/xray/remediation/cdxremediation.go +++ b/utils/xray/remediation/cdxremediation.go @@ -59,6 +59,7 @@ func matchVulnerabilityToRemediationOptions(bom *cyclonedx.BOM, vulnerability *c } } +// TODO remove this when https://jfrog-int.atlassian.net/browse/XRAY-137306 is done, as fix versions should be already normalized when returning from remediation API. func normalizeVersion(version string) string { return strings.TrimPrefix(version, "v") } From a9d51c8dd7a2828cb9d71d5114258b0bd7615f0b Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 18 Mar 2026 15:24:05 +0200 Subject: [PATCH 3/4] fix component name normalization in CDX conversion --- .../simplejsonparser/simplejsonparser.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/utils/results/conversion/simplejsonparser/simplejsonparser.go b/utils/results/conversion/simplejsonparser/simplejsonparser.go index 7a2292e63..7c446ffd9 100644 --- a/utils/results/conversion/simplejsonparser/simplejsonparser.go +++ b/utils/results/conversion/simplejsonparser/simplejsonparser.go @@ -113,7 +113,7 @@ func (sjc *CmdResultsSimpleJsonConverter) ParseSbomLicenses(sbom *cyclonedx.BOM) LicenseKey: license.License.ID, LicenseName: name, ImpactedDependencyDetails: formats.ImpactedDependencyDetails{ - ImpactedDependencyName: strings.ReplaceAll(compName, "/", ":"), + ImpactedDependencyName: normalizeCdxComponentName(compName, compType), ImpactedDependencyVersion: compVersion, ImpactedDependencyType: results.FormalTechOrCdxCompType(compType, sjc.pretty), Components: results.ExtractComponentDirectComponentsInBOM(bomIndex, component, impactPaths), @@ -234,7 +234,7 @@ func (sjc *CmdResultsSimpleJsonConverter) createVulnerabilityOrViolationRowFromC Summary: summary, ImpactedDependencyDetails: formats.ImpactedDependencyDetails{ SeverityDetails: severityutils.GetAsDetails(severity, applicabilityStatus, sjc.pretty), - ImpactedDependencyName: strings.ReplaceAll(compName, "/", ":"), + ImpactedDependencyName: normalizeCdxComponentName(compName, compType), ImpactedDependencyVersion: compVersion, ImpactedDependencyType: results.FormalTechOrCdxCompType(compType, sjc.pretty), Components: directComponents, @@ -272,7 +272,7 @@ func (sjc *CmdResultsSimpleJsonConverter) createLicenseViolationRow(licenseKey, LicenseName: licenseName, ImpactedDependencyDetails: formats.ImpactedDependencyDetails{ SeverityDetails: severityutils.GetAsDetails(severity, jasutils.NotScanned, sjc.pretty), - ImpactedDependencyName: strings.ReplaceAll(compName, "/", ":"), + ImpactedDependencyName: normalizeCdxComponentName(compName, compType), ImpactedDependencyVersion: compVersion, ImpactedDependencyType: results.FormalTechOrCdxCompType(compType, sjc.pretty), Components: directComponents, @@ -288,7 +288,7 @@ func (sjc *CmdResultsSimpleJsonConverter) createOpRiskViolationRow(opRiskViolati ViolationContext: convertToViolationContext(opRiskViolation.Violation), ImpactedDependencyDetails: formats.ImpactedDependencyDetails{ SeverityDetails: severityutils.GetAsDetails(opRiskViolation.Severity, jasutils.NotScanned, sjc.pretty), - ImpactedDependencyName: strings.ReplaceAll(compName, "/", ":"), + ImpactedDependencyName: normalizeCdxComponentName(compName, compType), ImpactedDependencyVersion: compVersion, ImpactedDependencyType: results.FormalTechOrCdxCompType(compType, sjc.pretty), Components: opRiskViolation.DirectComponents, @@ -731,3 +731,14 @@ func sortSourceCodeRow(rows []formats.SourceCodeRow) { return rows[i].File > rows[j].File }) } + +// Converts a PURL-derived component name to Xray-compatible format. +// SplitPackageURL joins namespace and name with "/". +// For Maven/Gradle (package type "maven"), Xray and package updaters expect "groupId:artifactId" with ":" as the separator. +// For all other ecosystems (Go, npm, etc.) the "/" is semantically part of the package identifier and must be preserved. +func normalizeCdxComponentName(compName, compType string) string { + if compType == techutils.Maven.String() { + return strings.Replace(compName, "/", ":", 1) + } + return compName +} From 65aef03000cae9f91d250e8af5044723cab9d5f0 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Sun, 22 Mar 2026 11:12:04 +0200 Subject: [PATCH 4/4] fix incomplete logic in CDX mapping fix --- .../results/conversion/simplejsonparser/simplejsonparser.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/results/conversion/simplejsonparser/simplejsonparser.go b/utils/results/conversion/simplejsonparser/simplejsonparser.go index 7c446ffd9..ad9559057 100644 --- a/utils/results/conversion/simplejsonparser/simplejsonparser.go +++ b/utils/results/conversion/simplejsonparser/simplejsonparser.go @@ -735,10 +735,12 @@ func sortSourceCodeRow(rows []formats.SourceCodeRow) { // Converts a PURL-derived component name to Xray-compatible format. // SplitPackageURL joins namespace and name with "/". // For Maven/Gradle (package type "maven"), Xray and package updaters expect "groupId:artifactId" with ":" as the separator. +// For Debian (package type "deb"), Xray expects "distro:version:name" with ":" as the separator. // For all other ecosystems (Go, npm, etc.) the "/" is semantically part of the package identifier and must be preserved. func normalizeCdxComponentName(compName, compType string) string { - if compType == techutils.Maven.String() { - return strings.Replace(compName, "/", ":", 1) + switch compType { + case techutils.Maven.String(), techutils.Debian.String(): + return strings.ReplaceAll(compName, "/", ":") } return compName }