/// <summary> /// Build and return a list of Sarif Result list from the find characterstics results /// </summary> /// <param name="purl"> </param> /// <param name="results"> </param> /// <returns> </returns> private static List <SarifResult> GetSarifResults(PackageURL purl, Dictionary <string, AnalyzeResult?> analysisResult, Options opts) { List <SarifResult> sarifResults = new List <SarifResult>(); if (analysisResult.HasAtLeastOneNonNullValue()) { foreach (var key in analysisResult.Keys) { var metadata = analysisResult?[key]?.Metadata; foreach (var result in metadata?.Matches ?? new List <MatchRecord>()) { var individualResult = new SarifResult() { Message = new Message() { Text = result.RuleDescription, Id = result.RuleId }, Kind = ResultKind.Informational, Level = opts.SarifLevel, Locations = SarifOutputBuilder.BuildPurlLocation(purl), Rule = new ReportingDescriptorReference() { Id = result.RuleId }, }; individualResult.SetProperty("Severity", result.Severity); individualResult.SetProperty("Confidence", result.Confidence); individualResult.Locations.Add(new CodeAnalysis.Sarif.Location() { PhysicalLocation = new PhysicalLocation() { Address = new Address() { FullyQualifiedName = result.FileName }, Region = new Region() { StartLine = result.StartLocationLine, EndLine = result.EndLocationLine, StartColumn = result.StartLocationColumn, EndColumn = result.EndLocationColumn, SourceLanguage = result.Language, Snippet = new ArtifactContent() { Text = result.Excerpt, Rendered = new MultiformatMessageString(result.Excerpt, $"`{result.Excerpt}`", null) } } } }); sarifResults.Add(individualResult); } } } return(sarifResults); }
public async Task <List <Dictionary <string, AnalyzeResult?> > > RunAsync(Options options) { // select output destination and format SelectOutput(options.OutputFile); IOutputBuilder outputBuilder = SelectFormat(options.Format); var finalResults = new List <Dictionary <string, AnalyzeResult?> >(); if (options.Targets is IList <string> targetList && targetList.Count > 0) { foreach (var target in targetList) { try { if (target.StartsWith("pkg:")) { var purl = new PackageURL(target); string downloadDirectory = options.DownloadDirectory == "." ? Directory.GetCurrentDirectory() : options.DownloadDirectory; var analysisResult = await AnalyzePackage(options, purl, downloadDirectory, options.UseCache == true); AppendOutput(outputBuilder, purl, analysisResult, options); finalResults.Add(analysisResult); } else if (Directory.Exists(target)) { var analysisResult = await AnalyzeDirectory(options, target); if (analysisResult != null) { var analysisResults = new Dictionary <string, AnalyzeResult?>() { { target, analysisResult } }; var purl = new PackageURL("generic", target); AppendOutput(outputBuilder, purl, analysisResults, options); } finalResults.Add(new Dictionary <string, AnalyzeResult?>() { { target, analysisResult } }); } else if (File.Exists(target)) { var analysisResult = await AnalyzeFile(options, target); if (analysisResult != null) { var analysisResults = new Dictionary <string, AnalyzeResult?>() { { target, analysisResult } }; var purl = new PackageURL("generic", target); AppendOutput(outputBuilder, purl, analysisResults, options); } finalResults.Add(new Dictionary <string, AnalyzeResult?>() { { target, analysisResult } }); } else { Logger.Warn("Package or file identifier was invalid."); } } catch (Exception ex) { Logger.Warn(ex, "Error processing {0}: {1}", target, ex.Message); } } outputBuilder.PrintOutput(); } RestoreOutput(); return(finalResults); }
/// <summary> /// Analyze a package by downloading it first. /// </summary> /// <param name="purl"> The package-url of the package to analyze. </param> /// <returns> List of tags identified </returns> public async Task <Dictionary <string, AnalyzeResult?> > AnalyzePackage(Options options, PackageURL purl, string?targetDirectoryName, bool doCaching = false) { Logger.Trace("AnalyzePackage({0})", purl.ToString()); var analysisResults = new Dictionary <string, AnalyzeResult?>(); var packageDownloader = new PackageDownloader(purl, targetDirectoryName, doCaching); // ensure that the cache directory has the required package, download it otherwise var directoryNames = await packageDownloader.DownloadPackageLocalCopy(purl, false, true); if (directoryNames.Count > 0) { foreach (var directoryName in directoryNames) { var singleResult = await AnalyzeDirectory(options, directoryName); analysisResults[directoryName] = singleResult; } } else { Logger.Warn("Error downloading {0}.", purl.ToString()); } packageDownloader.ClearPackageLocalCopyIfNoCaching(); return(analysisResults); }