Skip to content

Commit a71f06e

Browse files
authored
Always output relative paths in commands (jfrog#580)
1 parent 015f1b4 commit a71f06e

File tree

9 files changed

+107
-66
lines changed

9 files changed

+107
-66
lines changed

jas/common.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ func processSarifRuns(sarifRuns []*sarif.Run, wd string, informationUrlSuffix st
236236
sarifRun.Results = excludeSuppressResults(sarifRun.Results)
237237
sarifRun.Results = excludeMinSeverityResults(sarifRun.Results, minSeverity)
238238
}
239+
sarifutils.ConvertRunsPathsToRelative(sarifRuns...)
239240
}
240241

241242
func fillMissingRequiredDriverInformation(defaultJasInformationUri, defaultVersion string, run *sarif.Run) {

jas/common_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/owenrumney/go-sarif/v3/pkg/report/v210/sarif"
1010
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
1112
"golang.org/x/exp/slices"
1213

1314
jfrogAppsConfig "github.com/jfrog/jfrog-apps-config/go"
@@ -19,6 +20,7 @@ import (
1920
"github.com/jfrog/jfrog-cli-security/utils/formats/sarifutils"
2021
"github.com/jfrog/jfrog-cli-security/utils/jasutils"
2122
"github.com/jfrog/jfrog-cli-security/utils/results"
23+
"github.com/jfrog/jfrog-cli-security/utils/severityutils"
2224
"github.com/jfrog/jfrog-cli-security/utils/techutils"
2325
)
2426

@@ -593,3 +595,48 @@ func TestGetResultsToCompare(t *testing.T) {
593595
})
594596
}
595597
}
598+
599+
func TestProcessSarifRuns(t *testing.T) {
600+
wd, err := os.Getwd()
601+
assert.NoError(t, err)
602+
603+
// Create dummy SARIF report.
604+
dummyReport := sarif.NewReport()
605+
dummyReport.AddRun(sarifutils.CreateRunWithDummyResults(
606+
// Result below the minimum severity.
607+
sarifutils.CreateResultWithOneLocation(fmt.Sprintf("file://%s", filepath.Join(wd, "file1")), 0, 1, 2, 3, "snippet", "rule1", "note"),
608+
// Suppressed result.
609+
sarifutils.CreateResultWithOneLocation(fmt.Sprintf("file://%s", filepath.Join(wd, "file3")), 0, 0, 0, 0, "snippet", "rule1", "warning").WithSuppressions([]*sarif.Suppression{sarif.NewSuppression()}),
610+
// Valid result.
611+
sarifutils.CreateResultWithOneLocation(fmt.Sprintf("file://%s", filepath.Join(wd, "dir", "file2")), 0, 0, 0, 0, "snippet", "rule1", "error"),
612+
))
613+
614+
processSarifRuns(dummyReport.Runs, wd, "docs URL", severityutils.High)
615+
run := dummyReport.Runs[0]
616+
617+
// Check Invocation added.
618+
require.NotNil(t, run.Invocations)
619+
require.Len(t, run.Invocations, 1)
620+
require.NotNil(t, run.Invocations[0].WorkingDirectory)
621+
require.NotNil(t, run.Invocations[0].WorkingDirectory.URI)
622+
require.Equal(t, *run.Invocations[0].WorkingDirectory.URI, utils.ToURI(wd))
623+
624+
// Check driver info.
625+
driver := run.Tool.Driver
626+
require.NotNil(t, driver)
627+
require.NotNil(t, driver.Version)
628+
require.NotEmpty(t, *driver.Version)
629+
require.NotNil(t, driver.InformationURI)
630+
require.NotEmpty(t, *driver.InformationURI)
631+
632+
// Check severity level mapping.
633+
require.Len(t, driver.Rules, 1)
634+
rule := driver.Rules[0]
635+
require.Equal(t, "8.9", sarifutils.GetRuleProperty(severityutils.SarifSeverityRuleProperty, rule))
636+
637+
// Check minimum severity and suppression filtering.
638+
require.Len(t, run.Results, 1)
639+
// Check file paths are relative and with / separators.
640+
result := run.Results[0]
641+
require.Equal(t, "dir/file2", sarifutils.GetLocationFileName(result.Locations[0]))
642+
}

sca/bom/buildinfo/technologies/gem/gem_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/jfrog/jfrog-cli-security/utils"
1313
)
1414

15-
var expectedUniqueDeps = []string{"rubygems://puma:5.6.9", "rubygems://nio4r:2.7.4"}
15+
var expectedUniqueDeps = []string{"rubygems://puma:5.6.9", "rubygems://nio4r:2.7.5"}
1616

1717
var expectedResult = &xrayUtils.GraphNode{
1818
Id: "root",
@@ -21,7 +21,7 @@ var expectedResult = &xrayUtils.GraphNode{
2121
Id: "rubygems://puma:5.6.9",
2222
Nodes: []*xrayUtils.GraphNode{
2323
{
24-
Id: "rubygems://nio4r:2.7.4",
24+
Id: "rubygems://nio4r:2.7.5",
2525
Nodes: []*xrayUtils.GraphNode{},
2626
},
2727
},
@@ -52,15 +52,15 @@ func TestBuildDependencyTree(t *testing.T) {
5252
}
5353

5454
// expectedUniqueDeps should be defined
55-
// expectedUniqueDeps := []string{"rubygems://puma:5.6.9", "rubygems://nio4r:2.7.4"}
55+
// expectedUniqueDeps := []string{"rubygems://puma:5.6.9", "rubygems://nio4r:2.7.5"}
5656
func TestCalculateUniqueDeps(t *testing.T) {
5757
var input = &xrayUtils.GraphNode{
5858
Nodes: []*xrayUtils.GraphNode{
5959
{
6060
Id: "rubygems://puma:5.6.9",
6161
Nodes: []*xrayUtils.GraphNode{
6262
{
63-
Id: "rubygems://nio4r:2.7.4",
63+
Id: "rubygems://nio4r:2.7.5",
6464
Nodes: []*xrayUtils.GraphNode{},
6565
},
6666
},

sca/bom/buildinfo/technologies/pnpm/pnpm_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func TestBuildDependencyTreeLimitedDepth(t *testing.T) {
4343
name: "With transitive dependencies",
4444
treeDepth: "1",
4545
expectedUniqueDeps: []string{
46-
"npm://axios:1.12.2",
46+
"npm://axios:1.13.1",
4747
"npm://balaganjs:1.0.0",
4848
"npm://yargs:13.3.0",
4949
"npm://zen-website:1.0.0",
@@ -53,7 +53,7 @@ func TestBuildDependencyTreeLimitedDepth(t *testing.T) {
5353
Nodes: []*xrayUtils.GraphNode{
5454
{
5555
Id: "npm://balaganjs:1.0.0",
56-
Nodes: []*xrayUtils.GraphNode{{Id: "npm://axios:1.12.2"}, {Id: "npm://yargs:13.3.0"}},
56+
Nodes: []*xrayUtils.GraphNode{{Id: "npm://axios:1.13.1"}, {Id: "npm://yargs:13.3.0"}},
5757
},
5858
},
5959
},

tests/testdata/output/audit/audit_simple_json.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"name": "lodash",
1111
"version": "4.17.0",
1212
"location": {
13-
"file": "Users/user/project-with-issues/package.json"
13+
"file": "package.json"
1414
}
1515
}
1616
],
@@ -58,7 +58,7 @@
5858
"name": "lodash",
5959
"version": "4.17.0",
6060
"location": {
61-
"file": "Users/user/project-with-issues/package.json"
61+
"file": "package.json"
6262
}
6363
}
6464
],
@@ -110,7 +110,7 @@
110110
"name": "lodash",
111111
"version": "4.17.0",
112112
"location": {
113-
"file": "Users/user/project-with-issues/package.json"
113+
"file": "package.json"
114114
}
115115
}
116116
],
@@ -170,7 +170,7 @@
170170
"name": "lodash",
171171
"version": "4.17.0",
172172
"location": {
173-
"file": "Users/user/project-with-issues/package.json"
173+
"file": "package.json"
174174
}
175175
}
176176
],
@@ -216,7 +216,7 @@
216216
"name": "jake",
217217
"version": "10.8.7",
218218
"location": {
219-
"file": "Users/user/project-with-issues/package.json"
219+
"file": "package.json"
220220
}
221221
}
222222
],
@@ -299,7 +299,7 @@
299299
"name": "lodash",
300300
"version": "4.17.0",
301301
"location": {
302-
"file": "Users/user/project-with-issues/package.json"
302+
"file": "package.json"
303303
}
304304
}
305305
],
@@ -349,7 +349,7 @@
349349
"name": "jake",
350350
"version": "10.8.7",
351351
"location": {
352-
"file": "Users/user/project-with-issues/package.json"
352+
"file": "package.json"
353353
}
354354
}
355355
],
@@ -425,7 +425,7 @@
425425
"name": "lodash",
426426
"version": "4.17.0",
427427
"location": {
428-
"file": "Users/user/project-with-issues/package.json"
428+
"file": "package.json"
429429
}
430430
}
431431
],
@@ -449,7 +449,7 @@
449449
"name": "lodash",
450450
"version": "4.17.0",
451451
"location": {
452-
"file": "Users/user/project-with-issues/package.json"
452+
"file": "package.json"
453453
}
454454
}
455455
],

utils/results/common.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ func getBestMatch(target ScanTarget, descriptors []string) string {
231231
bestMatch = descriptor
232232
}
233233
}
234+
if bestMatch != "" {
235+
// convert to relative path
236+
bestMatch = utils.GetRelativePath(bestMatch, target.Target)
237+
}
234238
return bestMatch
235239
}
236240

utils/results/conversion/sarifparser/sarifparser.go

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ func getComponentSarifLocation(cmtType utils.CommandType, component formats.Comp
615615
logicalLocations = append(logicalLocations, logicalLocation)
616616
}
617617
}
618-
location := sarif.NewLocation().WithPhysicalLocation(sarif.NewPhysicalLocation().WithArtifactLocation(sarif.NewArtifactLocation().WithURI("file://" + filePath)))
618+
location := sarif.NewLocation().WithPhysicalLocation(sarif.NewPhysicalLocation().WithArtifactLocation(sarif.NewArtifactLocation().WithURI(filepath.ToSlash(filePath))))
619619
if len(logicalLocations) > 0 {
620620
location.WithLogicalLocations(logicalLocations)
621621
}
@@ -696,9 +696,6 @@ func patchRunsToPassIngestionRules(baseJfrogUrl string, cmdType utils.CommandTyp
696696
// Patch changes may alter the original run, so we will create a new run for each
697697
for _, run := range runs {
698698
patched := sarifutils.CopyRun(run)
699-
// Since we run in temp directories files should be relative
700-
// Patch by converting the file paths to relative paths according to the invocations
701-
convertPaths(cmdType, subScanType, patched)
702699
if cmdType.IsTargetBinary() && subScanType == utils.SecretsScan {
703700
// Patch the tool name in case of binary scan
704701
sarifutils.SetRunToolName(BinarySecretScannerToolName, patched)
@@ -712,20 +709,6 @@ func patchRunsToPassIngestionRules(baseJfrogUrl string, cmdType utils.CommandTyp
712709
return patchedRuns
713710
}
714711

715-
func convertPaths(commandType utils.CommandType, subScanType utils.SubScanType, runs ...*sarif.Run) {
716-
// Convert base on invocation for source code
717-
sarifutils.ConvertRunsPathsToRelative(runs...)
718-
if !(commandType == utils.DockerImage && subScanType == utils.SecretsScan) {
719-
return
720-
}
721-
for _, run := range runs {
722-
for _, result := range run.Results {
723-
// For Docker secret scan, patch the logical location if not exists
724-
patchDockerSecretLocations(result)
725-
}
726-
}
727-
}
728-
729712
// Patch the URI to be the file path from sha<number>/<hash>/
730713
// Extract the layer from the location URI, adds it as a logical location kind "layer"
731714
func patchDockerSecretLocations(result *sarif.Result) {
@@ -780,6 +763,10 @@ func patchResults(commandType utils.CommandType, subScanType utils.SubScanType,
780763
log.Debug(fmt.Sprintf("[%s] Removing result [ruleId=%s] without locations: %s", subScanType.String(), sarifutils.GetResultRuleId(result), sarifutils.GetResultMsgText(result)))
781764
continue
782765
}
766+
if commandType == utils.DockerImage && subScanType == utils.SecretsScan {
767+
// For Docker secret scan, patch the logical location if not exists
768+
patchDockerSecretLocations(result)
769+
}
783770
patchResultMsg(result, target, commandType, subScanType, isJasViolations)
784771
if commandType.IsTargetBinary() {
785772
if patchBinaryPaths {
@@ -850,7 +837,8 @@ func getDockerfileLocationIfExists(run *sarif.Run) string {
850837
return location
851838
}
852839
}
853-
if workspace := os.Getenv(utils.CurrentGithubWorkflowWorkspaceEnvVar); workspace != "" {
840+
// Validate file path to prevent directory traversal
841+
if workspace := os.Getenv(utils.CurrentGithubWorkflowWorkspaceEnvVar); workspace != "" && !strings.Contains(workspace, "..") {
854842
if exists, err := fileutils.IsFileExists(filepath.Join(workspace, "Dockerfile"), false); err == nil && exists {
855843
return filepath.Join(workspace, "Dockerfile")
856844
}
@@ -862,7 +850,8 @@ func getGithubWorkflowsDirIfExists() string {
862850
if exists, err := fileutils.IsDirExists(GithubBaseWorkflowDir, false); err == nil && exists {
863851
return GithubBaseWorkflowDir
864852
}
865-
if workspace := os.Getenv(utils.CurrentGithubWorkflowWorkspaceEnvVar); workspace != "" {
853+
// Validate file path to prevent directory traversal
854+
if workspace := os.Getenv(utils.CurrentGithubWorkflowWorkspaceEnvVar); workspace != "" && !strings.Contains(workspace, "..") {
866855
if exists, err := fileutils.IsDirExists(filepath.Join(workspace, GithubBaseWorkflowDir), false); err == nil && exists {
867856
return filepath.Join(workspace, GithubBaseWorkflowDir)
868857
}

0 commit comments

Comments
 (0)