Skip to content

Commit

Permalink
Secret Token Validation feature (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
barv-jfrog authored Sep 18, 2024
1 parent faa71b4 commit be9cf8e
Show file tree
Hide file tree
Showing 27 changed files with 354 additions and 81 deletions.
39 changes: 25 additions & 14 deletions audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"encoding/json"
"fmt"
"github.com/jfrog/jfrog-cli-security/utils/jasutils"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -340,7 +341,7 @@ func TestXrayAuditMultiProjects(t *testing.T) {
defer securityTestUtils.CleanTestsHomeEnv()
output := securityTests.PlatformCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+string(format.SimpleJson), workingDirsFlag)
securityTestUtils.VerifySimpleJsonScanResults(t, output, 0, 35, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 1, 9, 6, 3, 0, 24, 2, 1)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 1, 9, 6, 3, 0, 24, 2, 1, 0)
}

func TestXrayAuditPipJson(t *testing.T) {
Expand Down Expand Up @@ -445,11 +446,11 @@ func addDummyPackageDescriptor(t *testing.T, hasPackageJson bool) {
func TestXrayAuditNotEntitledForJas(t *testing.T) {
cliToRun, cleanUp := securityTestUtils.InitTestWithMockCommandOrParams(t, getNoJasAuditMockCommand)
defer cleanUp()
output := testXrayAuditJas(t, cliToRun, filepath.Join("jas", "jas"), "3")
output := testXrayAuditJas(t, cliToRun, filepath.Join("jas", "jas"), "3", false)
// Verify that scan results are printed
securityTestUtils.VerifySimpleJsonScanResults(t, output, 0, 8, 0)
// Verify that JAS results are not printed
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 0, 0, 0, 0, 0, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 0, 0, 0, 0, 0, 0, 0)
}

func getNoJasAuditMockCommand() components.Command {
Expand All @@ -469,29 +470,35 @@ func getNoJasAuditMockCommand() components.Command {
}

func TestXrayAuditJasSimpleJson(t *testing.T) {
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("jas", "jas"), "3")
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("jas", "jas"), "3", false)
securityTestUtils.VerifySimpleJsonScanResults(t, output, 0, 8, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 1, 9, 6, 3, 1, 1, 2, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 1, 9, 6, 3, 1, 1, 2, 0, 0)
}

func TestXrayAuditJasSimpleJsonWithTokenValidation(t *testing.T) {
securityTestUtils.InitSecurityTest(t, jasutils.DynamicTokenValidationMinXrayVersion)
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("jas", "jas"), "3", true)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 0, 0, 0, 0, 0, 0, 5)
}

func TestXrayAuditJasSimpleJsonWithOneThread(t *testing.T) {
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("jas", "jas"), "1")
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("jas", "jas"), "1", false)
securityTestUtils.VerifySimpleJsonScanResults(t, output, 0, 8, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 1, 9, 6, 3, 1, 1, 2, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 1, 9, 6, 3, 1, 1, 2, 0, 0)
}

func TestXrayAuditJasSimpleJsonWithConfig(t *testing.T) {
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("jas", "jas-config"), "3")
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 1, 3, 1, 1, 2, 0)
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("jas", "jas-config"), "3", false)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 1, 3, 1, 1, 2, 0, 0)
}

func TestXrayAuditJasNoViolationsSimpleJson(t *testing.T) {
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("package-managers", "npm", "npm"), "3")
output := testXrayAuditJas(t, securityTests.PlatformCli, filepath.Join("package-managers", "npm", "npm"), "3", false)
securityTestUtils.VerifySimpleJsonScanResults(t, output, 0, 1, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 0, 0, 0, 0, 1, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 0, 0, 0, 0, 1, 0, 0)
}

func testXrayAuditJas(t *testing.T, testCli *coreTests.JfrogCli, project string, threads string) string {
func testXrayAuditJas(t *testing.T, testCli *coreTests.JfrogCli, project string, threads string, validateSecrets bool) string {
securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion)
tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t)
defer createTempDirCallback()
Expand All @@ -505,7 +512,11 @@ func testXrayAuditJas(t *testing.T, testCli *coreTests.JfrogCli, project string,
assert.NoError(t, err)
chdirCallback := clientTests.ChangeDirWithCallback(t, baseWd, tempDirPath)
defer chdirCallback()
return testCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+string(format.SimpleJson), "--threads="+threads)
args := []string{"audit", "--format=" + string(format.SimpleJson), "--threads=" + threads}
if validateSecrets {
args = append(args, "--secrets", "--validate-secrets")
}
return testCli.WithoutCredentials().RunCliCmdWithOutput(t, args...)
}

func TestXrayAuditDetectTech(t *testing.T) {
Expand Down Expand Up @@ -577,5 +588,5 @@ func TestAuditOnEmptyProject(t *testing.T) {
chdirCallback := clientTests.ChangeDirWithCallback(t, baseWd, tempDirPath)
defer chdirCallback()
output := securityTests.PlatformCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+string(format.SimpleJson))
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 0, 0, 0, 0, 0, 0)
securityTestUtils.VerifySimpleJsonJasResults(t, output, 0, 0, 0, 0, 0, 0, 0, 0, 0)
}
6 changes: 4 additions & 2 deletions cli/docs/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const (
buildPrefix = "build-"
BuildVuln = buildPrefix + Vuln
ScanVuln = scanPrefix + Vuln
SecretValidation = "validate-secrets"

// Unique audit flags
auditPrefix = "audit-"
Expand Down Expand Up @@ -147,13 +148,13 @@ var commandFlags = map[string][]string{
url, user, password, accessToken, ServerId, Project, BuildVuln, OutputFormat, Fail, ExtendedTable, Rescan,
},
DockerScan: {
ServerId, Project, Watches, RepoPath, Licenses, OutputFormat, Fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, ScanVuln,
ServerId, Project, Watches, RepoPath, Licenses, OutputFormat, Fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, ScanVuln, SecretValidation,
},
Audit: {
url, user, password, accessToken, ServerId, InsecureTls, Project, Watches, RepoPath, Licenses, OutputFormat, ExcludeTestDeps,
useWrapperAudit, DepType, RequirementsFile, Fail, ExtendedTable, WorkingDirs, ExclusionsAudit, Mvn, Gradle, Npm,
Pnpm, Yarn, Go, Nuget, Pip, Pipenv, Poetry, MinSeverity, FixableOnly, ThirdPartyContextualAnalysis, Threads,
Sca, Iac, Sast, Secrets, WithoutCA, ScanVuln, OutputDir,
Sca, Iac, Sast, Secrets, WithoutCA, ScanVuln, SecretValidation, OutputDir,
},
CurationAudit: {
CurationOutput, WorkingDirs, Threads, RequirementsFile,
Expand Down Expand Up @@ -258,6 +259,7 @@ var flagsMap = map[string]components.Flag{
Sast: components.NewBoolFlag(Sast, fmt.Sprintf("Selective scanners mode: Execute SAST sub-scan. Can be combined with --%s, --%s and --%s.", Sca, Secrets, Iac)),
Secrets: components.NewBoolFlag(Secrets, fmt.Sprintf("Selective scanners mode: Execute Secrets sub-scan. Can be combined with --%s, --%s and --%s.", Sca, Sast, Iac)),
WithoutCA: components.NewBoolFlag(WithoutCA, fmt.Sprintf("Selective scanners mode: Disable Contextual Analysis scanner after SCA. Relevant only with --%s flag.", Sca)),
SecretValidation: components.NewBoolFlag(SecretValidation, fmt.Sprintf("Selective scanners mode: Execute Token validation sub-scan on secrets. Relevant only with --%s flag.", Secrets)),

// Git flags
InputFile: components.NewStringFlag(InputFile, "Path to an input file in YAML format contains multiple git providers. With this option, all other scm flags will be ignored and only git servers mentioned in the file will be examined.."),
Expand Down
10 changes: 8 additions & 2 deletions cli/scancommands.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,11 @@ func AuditCmd(c *components.Context) error {
return pluginsCommon.PrintHelpAndReturnError(fmt.Sprintf("flag '--%s' cannot be used without '--%s'", flags.WithoutCA, flags.Sca), c)
}

if c.GetBoolFlagValue(flags.SecretValidation) && !c.GetBoolFlagValue(flags.Secrets) {
// No secrets flag but secret validation is provided, error
return pluginsCommon.PrintHelpAndReturnError(fmt.Sprintf("flag '--%s' cannot be used without '--%s'", flags.SecretValidation, flags.Secrets), c)
}

allSubScans := utils.GetAllSupportedScans()
subScans := []utils.SubScanType{}
for _, subScan := range allSubScans {
Expand All @@ -420,7 +425,7 @@ func AuditCmd(c *components.Context) error {

func shouldAddSubScan(subScan utils.SubScanType, c *components.Context) bool {
return c.GetBoolFlagValue(subScan.String()) ||
(subScan == utils.ContextualAnalysisScan && c.GetBoolFlagValue(flags.Sca) && !c.GetBoolFlagValue(flags.WithoutCA))
(subScan == utils.ContextualAnalysisScan && c.GetBoolFlagValue(flags.Sca) && !c.GetBoolFlagValue(flags.WithoutCA)) || (subScan == utils.SecretTokenValidationScan && c.GetBoolFlagValue(flags.Secrets) && c.GetBoolFlagValue(flags.SecretValidation))
}

func reportErrorIfExists(err error, auditCmd *audit.AuditCommand) {
Expand Down Expand Up @@ -724,7 +729,8 @@ func DockerScan(c *components.Context, image string) error {
SetFixableOnly(c.GetBoolFlagValue(flags.FixableOnly)).
SetMinSeverityFilter(minSeverity).
SetThreads(threads).
SetAnalyticsMetricsService(xsc.NewAnalyticsMetricsService(serverDetails))
SetAnalyticsMetricsService(xsc.NewAnalyticsMetricsService(serverDetails)).
SetSecretValidation(c.GetBoolFlagValue(flags.SecretValidation))
if c.GetStringFlagValue(flags.Watches) != "" {
containerScanCommand.SetWatches(splitByCommaAndTrim(c.GetStringFlagValue(flags.Watches)))
}
Expand Down
5 changes: 3 additions & 2 deletions commands/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-security/utils/xray/scangraph"
"github.com/jfrog/jfrog-cli-security/utils/xsc"
"golang.org/x/exp/slices"

xrayutils "github.com/jfrog/jfrog-cli-security/utils/xray"
clientutils "github.com/jfrog/jfrog-client-go/utils"
Expand Down Expand Up @@ -185,8 +186,8 @@ func RunAudit(auditParams *AuditParams) (results *utils.Results, err error) {
if err != nil {
return
}
results.ExtendedScanResults.SecretValidation = jas.CheckForSecretValidation(xrayManager, auditParams.xrayVersion, slices.Contains(auditParams.AuditBasicParams.ScansToPerform(), utils.SecretTokenValidationScan))
results.MultiScanId = auditParams.commonGraphScanParams.MultiScanId

auditParallelRunner := utils.CreateSecurityParallelRunner(auditParams.threads)
auditParallelRunner.ErrWg.Add(1)
jfrogAppsConfig, err := jas.CreateJFrogAppsConfig(auditParams.workingDirs)
Expand Down Expand Up @@ -251,7 +252,7 @@ func downloadAnalyzerManagerAndRunScanners(auditParallelRunner *utils.SecurityPa
if err = jas.DownloadAnalyzerManagerIfNeeded(threadId); err != nil {
return fmt.Errorf("%s failed to download analyzer manager: %s", clientutils.GetLogMsgPrefix(threadId, false), err.Error())
}
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, serverDetails, jas.GetAnalyzerManagerXscEnvVars(auditParams.commonGraphScanParams.MultiScanId, scanResults.GetScaScannedTechnologies()...), auditParams.Exclusions()...)
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, serverDetails, jas.GetAnalyzerManagerXscEnvVars(auditParams.commonGraphScanParams.MultiScanId, scanResults.ExtendedScanResults.SecretValidation, scanResults.GetScaScannedTechnologies()...), auditParams.Exclusions()...)
if err != nil {
return fmt.Errorf("failed to create jas scanner: %s", err.Error())
}
Expand Down
4 changes: 2 additions & 2 deletions commands/audit/audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestAuditWithConfigProfile(t *testing.T) {
IsDefault: false,
},
expectedSastIssues: 0,
expectedSecretsIssues: 7,
expectedSecretsIssues: 16,
},
{
name: "Enable only sast scanner",
Expand Down Expand Up @@ -87,7 +87,7 @@ func TestAuditWithConfigProfile(t *testing.T) {
IsDefault: false,
},
expectedSastIssues: 1,
expectedSecretsIssues: 7,
expectedSecretsIssues: 16,
},
}

Expand Down
17 changes: 12 additions & 5 deletions commands/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type ScanCommand struct {
includeLicenses bool
fail bool
printExtendedTable bool
validateSecrets bool
bypassArchiveLimits bool
fixableOnly bool
progress ioUtils.ProgressMgr
Expand All @@ -83,6 +84,11 @@ func (scanCmd *ScanCommand) SetMinSeverityFilter(minSeverityFilter severityutils
return scanCmd
}

func (scanCmd *ScanCommand) SetSecretValidation(validateSecrets bool) *ScanCommand {
scanCmd.validateSecrets = validateSecrets
return scanCmd
}

func (scanCmd *ScanCommand) SetFixableOnly(fixable bool) *ScanCommand {
scanCmd.fixableOnly = fixable
return scanCmd
Expand Down Expand Up @@ -230,6 +236,7 @@ func (scanCmd *ScanCommand) RunAndRecordResults(cmdType utils.CommandType, recor
}

scanResults.ExtendedScanResults.EntitledForJas, err = jas.IsEntitledForJas(xrayManager, xrayVersion)
scanResults.ExtendedScanResults.SecretValidation = jas.CheckForSecretValidation(xrayManager, xrayVersion, scanCmd.validateSecrets)
errGroup := new(errgroup.Group)
if scanResults.ExtendedScanResults.EntitledForJas {
// Download (if needed) the analyzer manager in a background routine.
Expand Down Expand Up @@ -288,7 +295,7 @@ func (scanCmd *ScanCommand) RunAndRecordResults(cmdType utils.CommandType, recor
jasScanProducerErrors := make([][]formats.SimpleJsonError, threads)
// Start walking on the filesystem to "produce" files that match the given pattern
// while the consumer uses the indexer to index those files.
scanCmd.prepareScanTasks(fileProducerConsumer, indexedFileProducerConsumer, &JasScanProducerConsumer, scanResults.ExtendedScanResults.EntitledForJas, resultsArr, fileProducerErrors, indexedFileProducerErrors, jasScanProducerErrors, fileCollectingErrorsQueue, xrayVersion)
scanCmd.prepareScanTasks(fileProducerConsumer, indexedFileProducerConsumer, &JasScanProducerConsumer, scanResults.ExtendedScanResults.EntitledForJas, scanResults.ExtendedScanResults.SecretValidation, resultsArr, fileProducerErrors, indexedFileProducerErrors, jasScanProducerErrors, fileCollectingErrorsQueue, xrayVersion)
scanCmd.performScanTasks(fileProducerConsumer, indexedFileProducerConsumer, &JasScanProducerConsumer)

// Handle results
Expand Down Expand Up @@ -356,14 +363,14 @@ func (scanCmd *ScanCommand) CommandName() string {
return "xr_scan"
}

func (scanCmd *ScanCommand) prepareScanTasks(fileProducer, indexedFileProducer parallel.Runner, jasFileProducerConsumer *utils.SecurityParallelRunner, entitledForJas bool, resultsArr [][]*ScanInfo, fileErrors, indexedFileErrors, jasErrors [][]formats.SimpleJsonError, fileCollectingErrorsQueue *clientutils.ErrorsQueue, xrayVersion string) {
func (scanCmd *ScanCommand) prepareScanTasks(fileProducer, indexedFileProducer parallel.Runner, jasFileProducerConsumer *utils.SecurityParallelRunner, entitledForJas bool, validateSecrets bool, resultsArr [][]*ScanInfo, fileErrors, indexedFileErrors, jasErrors [][]formats.SimpleJsonError, fileCollectingErrorsQueue *clientutils.ErrorsQueue, xrayVersion string) {
go func() {
defer fileProducer.Done()
// Iterate over file-spec groups and produce indexing tasks.
// When encountering an error, log and move to next group.
specFiles := scanCmd.spec.Files
for i := range specFiles {
artifactHandlerFunc := scanCmd.createIndexerHandlerFunc(&specFiles[i], entitledForJas, indexedFileProducer, jasFileProducerConsumer, resultsArr, fileErrors, indexedFileErrors, jasErrors, xrayVersion)
artifactHandlerFunc := scanCmd.createIndexerHandlerFunc(&specFiles[i], entitledForJas, validateSecrets, indexedFileProducer, jasFileProducerConsumer, resultsArr, fileErrors, indexedFileErrors, jasErrors, xrayVersion)
taskHandler := getAddTaskToProducerFunc(fileProducer, artifactHandlerFunc)

err := collectFilesForIndexing(specFiles[i], taskHandler)
Expand All @@ -375,7 +382,7 @@ func (scanCmd *ScanCommand) prepareScanTasks(fileProducer, indexedFileProducer p
}()
}

func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, entitledForJas bool, indexedFileProducer parallel.Runner, jasFileProducerConsumer *utils.SecurityParallelRunner, resultsArr [][]*ScanInfo, fileErrors, indexedFileErrors, jasErrors [][]formats.SimpleJsonError, xrayVersion string) FileContext {
func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, entitledForJas bool, validateSecrets bool, indexedFileProducer parallel.Runner, jasFileProducerConsumer *utils.SecurityParallelRunner, resultsArr [][]*ScanInfo, fileErrors, indexedFileErrors, jasErrors [][]formats.SimpleJsonError, xrayVersion string) FileContext {
return func(filePath string) parallel.TaskFunc {
return func(threadId int) (err error) {
logMsgPrefix := clientutils.GetLogMsgPrefix(threadId, false)
Expand Down Expand Up @@ -445,7 +452,7 @@ func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, entitledFo
indexedFileErrors[threadId] = append(indexedFileErrors[threadId], formats.SimpleJsonError{FilePath: filePath, ErrorMessage: err.Error()})
}
scanner := &jas.JasScanner{}
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, scanCmd.serverDetails, jas.GetAnalyzerManagerXscEnvVars(scanResults.MultiScanId, techutils.Technology(graphScanResults.ScannedPackageType)))
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, scanCmd.serverDetails, jas.GetAnalyzerManagerXscEnvVars(scanResults.MultiScanId, validateSecrets, techutils.Technology(graphScanResults.ScannedPackageType)))
if err != nil {
log.Error(fmt.Sprintf("failed to create jas scanner: %s", err.Error()))
indexedFileErrors[threadId] = append(indexedFileErrors[threadId], formats.SimpleJsonError{FilePath: filePath, ErrorMessage: err.Error()})
Expand Down
18 changes: 14 additions & 4 deletions formats/conversion.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package formats

import (
"github.com/jfrog/jfrog-cli-security/utils/jasutils"
"strconv"
"strings"
)
Expand Down Expand Up @@ -143,12 +144,21 @@ func ConvertToOperationalRiskViolationScanTableRow(rows []OperationalRiskViolati

func ConvertToSecretsTableRow(rows []SourceCodeRow) (tableRows []secretsTableRow) {
for i := range rows {
var status string
var info string
if rows[i].Applicability != nil {
status = rows[i].Applicability.Status
info = rows[i].Applicability.ScannerDescription
}
tableRows = append(tableRows, secretsTableRow{
severity: rows[i].Severity,
file: rows[i].File,
lineColumn: strconv.Itoa(rows[i].StartLine) + ":" + strconv.Itoa(rows[i].StartColumn),
secret: rows[i].Snippet,
severity: rows[i].Severity,
file: rows[i].File,
lineColumn: strconv.Itoa(rows[i].StartLine) + ":" + strconv.Itoa(rows[i].StartColumn),
secret: rows[i].Snippet,
tokenValidation: jasutils.TokenValidationStatus(status).ToString(),
tokenInfo: info,
})

}
return
}
Expand Down
11 changes: 11 additions & 0 deletions formats/sarifutils/sarifutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ func AggregateMultipleRunsIntoSingle(runs []*sarif.Run, destination *sarif.Run)
}
}

func GetResultProperty(key string, result *sarif.Result) string {
if result != nil && result.Properties != nil && result.Properties[key] != nil {
status, ok := result.Properties[key].(string)
if !ok {
return ""
}
return status
}
return ""
}

func GetLocationRelatedCodeFlowsFromResult(location *sarif.Location, result *sarif.Result) (codeFlows []*sarif.CodeFlow) {
for _, codeFlow := range result.CodeFlows {
for _, stackTrace := range codeFlow.ThreadFlows {
Expand Down
14 changes: 14 additions & 0 deletions formats/sarifutils/test_sarifutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ func CreateDummyResult(markdown, msg, ruleId, level string) *sarif.Result {
}
}

func CreateResultWithProperties(msg, ruleId, level string, properties map[string]string, locations ...*sarif.Location) *sarif.Result {
result := &sarif.Result{
Message: *sarif.NewTextMessage(msg),
Level: &level,
RuleID: &ruleId,
Locations: locations,
}
result.Properties = map[string]interface{}{}
for key, val := range properties {
result.Properties[key] = val
}
return result
}

func CreateResultWithDummyLocationAmdProperty(fileName, property, value string) *sarif.Result {
resultWithLocation := CreateDummyResultInPath(fileName)
resultWithLocation.Properties = map[string]interface{}{property: value}
Expand Down
Loading

0 comments on commit be9cf8e

Please sign in to comment.