private static void CheckAllowedPackages() { foreach (var pkg in _pkgs.Where(p => !_settings.ErrorSettings.AllowedPackages.Any(b => b.Id == p.Id && VersionRange.Parse(p.Version).Satisfies(new NuGetVersion(b.Version))))) { var msBuildMessage = MsBuild.Log(_nuGetFile, MsBuild.Category.Error, pkg.LineNumber, pkg.LinePosition, $"{pkg.Id} is not listed as an allowed package and may not be used in this project"); Console.WriteLine(msBuildMessage); Log.Logger.Debug(msBuildMessage); } }
private static void CheckBlockedPackages() { foreach (var pkg in _pkgs) { var blockedPackage = _settings.ErrorSettings.BlockedPackages.FirstOrDefault(b => b.Package.Id == pkg.Id && VersionRange.Parse(pkg.Version).Satisfies(new NuGetVersion(b.Package.Version))); if (blockedPackage == null) { continue; } var msBuildMessage = MsBuild.Log(_nuGetFile, MsBuild.Category.Error, pkg.LineNumber, pkg.LinePosition, $"{pkg.Id}: {(string.IsNullOrEmpty(blockedPackage.CustomErrorMessage) ? blockedPackage.CustomErrorMessage : "has been blocked and may not be used in this project")}"); Log.Logger.Debug(msBuildMessage); } }
public void BuildVulnerabilityReport( Dictionary <string, Dictionary <string, Vulnerability> > vulnerabilityDictionary, IEnumerable <NuGetPackage> pkgs, string nuGetFile, bool warnOnly, double cvss3Threshold) { var logBuilder = new StringBuilder(); foreach (var pkg in pkgs.Where(p => p.LineNumber != null && vulnerabilityDictionary.ContainsKey(p.Id.ToLower()))) { var vulnerabilities = vulnerabilityDictionary[pkg.Id.ToLower()]; logBuilder.AppendLine("*************************************"); warnOnly = warnOnly || !vulnerabilities.Any(v => v.Value.CvssScore >= cvss3Threshold); var dependantVulnerabilities = pkg.Dependencies.Where(dep => vulnerabilityDictionary.ContainsKey(dep)); var vulnTotalMSbuildMessage = MsBuild.Log(nuGetFile, warnOnly ? MsBuild.Category.Warning : MsBuild.Category.Error, pkg.LineNumber, pkg.LinePosition, $"{vulnerabilities.Count} vulnerabilities found for {pkg.Id} @ {pkg.Version}"); if (_separateMsBuildMessages) { MsBuildMessages.Add(vulnTotalMSbuildMessage); } else { logBuilder.AppendLine(vulnTotalMSbuildMessage); } if (dependantVulnerabilities.Any()) { var dependantVulnTotalMsBuildMessage = MsBuild.Log(nuGetFile, warnOnly ? MsBuild.Category.Warning : MsBuild.Category.Error, pkg.LineNumber, pkg.LinePosition, $"{dependantVulnerabilities.Count()} vulnerabilities found for dependencies of {pkg.Id} @ {pkg.Version}"); if (_separateMsBuildMessages) { MsBuildMessages.Add(dependantVulnTotalMsBuildMessage); } else { logBuilder.AppendLine(dependantVulnTotalMsBuildMessage); } } foreach (var cve in vulnerabilities.Keys) { warnOnly = warnOnly || vulnerabilities[cve].CvssScore <= cvss3Threshold; var vulnMsBuildMessage = MsBuild.Log(nuGetFile, warnOnly ? MsBuild.Category.Warning : MsBuild.Category.Error, cve, pkg.LineNumber, pkg.LinePosition, $"{vulnerabilities[cve].Description}"); if (_separateMsBuildMessages) { MsBuildMessages.Add(vulnMsBuildMessage); } else { logBuilder.AppendLine(vulnMsBuildMessage); } logBuilder.AppendLine($"Description: {vulnerabilities[cve].Description}"); logBuilder.AppendLine($"CVE: {cve}"); logBuilder.AppendLine($"CWE: {vulnerabilities[cve].Cwe}"); logBuilder.AppendLine($"CVSS Score: {vulnerabilities[cve].CvssScore}"); logBuilder.AppendLine($"CVSS Vector: {vulnerabilities[cve].Vector}"); if (vulnerabilities[cve].References != null && vulnerabilities[cve].References.Any()) { logBuilder.AppendLine("References:"); foreach (var reference in vulnerabilities[cve].References) { logBuilder.AppendLine(reference); } } logBuilder.AppendLine("---------------------------"); } foreach (var dependancy in dependantVulnerabilities) { vulnerabilities = vulnerabilityDictionary[dependancy]; foreach (var cve in vulnerabilities.Keys) { warnOnly = warnOnly || vulnerabilities[cve].CvssScore <= cvss3Threshold; var vulnMsBuildMessage = MsBuild.Log(nuGetFile, warnOnly ? MsBuild.Category.Warning : MsBuild.Category.Error, cve, pkg.LineNumber, pkg.LinePosition, $"{dependancy}: {vulnerabilities[cve].Description}"); if (_separateMsBuildMessages) { MsBuildMessages.Add(vulnMsBuildMessage); } else { logBuilder.AppendLine(vulnMsBuildMessage); } logBuilder.AppendLine($"Description: {vulnerabilities[cve].Description}"); logBuilder.AppendLine($"CVE: {cve}"); logBuilder.AppendLine($"CWE: {vulnerabilities[cve].Cwe}"); logBuilder.AppendLine($"CVSS Score: {vulnerabilities[cve].CvssScore}"); logBuilder.AppendLine($"CVSS Vector: {vulnerabilities[cve].Vector}"); // if (vulnerabilities[cve].Version?.Length > 0) // logBuilder.AppendLine($"Affected Version: {vulnerabilities[cve].Version}"); logBuilder.AppendLine("---------------------------"); } } } VulnerabilityReport = logBuilder.ToString(); }
/// <summary> /// args[0] is expected to be the path to the project file. /// </summary> /// <param name="args"></param> private static int Main(string[] args) { #if DOTNETTOOL if (args.Length == 0) { Console.WriteLine($"NuGetDefense v{Version}"); Console.WriteLine("-------------"); Console.WriteLine($"{Environment.NewLine}Usage:"); Console.WriteLine($"{Environment.NewLine} nugetdefense projectFile.proj TargetFrameworkMoniker"); Console.WriteLine($"{Environment.NewLine} nugetdefense SolutionFile.sln Release"); Console.WriteLine($"{Environment.NewLine} nugetdefense SolutionFile.sln Debug|Any CPU"); return(0); } #endif _settings = Settings.LoadSettings(Path.GetDirectoryName(args[0])); _projectFileName = Path.GetFileName(args[0]); ConfigureLogging(); try { Log.Logger.Verbose("Logging Configured"); Log.Logger.Verbose("Started NuGetDefense with arguments: {args}", args); var targetFramework = args.Length == 2 ? args[1] : ""; if (args[0].EndsWith(".sln", StringComparison.OrdinalIgnoreCase)) { var projects = DotNetSolution.Load(args[0]).Projects.Where(p => !p.Type.IsSolutionFolder).Select(p => p.Path).ToArray(); var specificFramework = !string.IsNullOrWhiteSpace(targetFramework); if (specificFramework) { Log.Logger.Information("Target Framework: {framework}", targetFramework); } _projects = LoadMultipleProjects(args[0], projects, specificFramework, targetFramework, true); } else if (_settings.CheckReferencedProjects) { var projects = new List <string> { args[0] }; GetProjectsReferenced(in args[0], in projects); var specificFramework = !string.IsNullOrWhiteSpace(targetFramework); if (specificFramework) { Log.Logger.Information("Target Framework: {framework}", targetFramework); } _projects = LoadMultipleProjects(args[0], projects.ToArray(), specificFramework, targetFramework, false); } else { var nugetFile = new NuGetFile(args[0]); _nuGetFile = nugetFile.Path; Log.Logger.Verbose("NuGetFile Path: {nugetFilePath}", _nuGetFile); Log.Logger.Information("Target Framework: {framework}", string.IsNullOrWhiteSpace(targetFramework) ? "Undefined" : targetFramework); Log.Logger.Verbose("Loading Packages"); Log.Logger.Verbose("Transitive Dependencies Included: {CheckTransitiveDependencies}", _settings.CheckTransitiveDependencies); if (_settings.CheckTransitiveDependencies && nugetFile.PackagesConfig) { var projects = DotNetProject.Load(args[0]).ProjectReferences.Select(p => p.FilePath).ToArray(); var specificFramework = !string.IsNullOrWhiteSpace(targetFramework); if (specificFramework) { Log.Logger.Information("Target Framework: {framework}", targetFramework); } _projects = LoadMultipleProjects(args[0], projects, specificFramework, targetFramework); } else { _projects = new Dictionary <string, NuGetPackage[]>(); _projects.Add(nugetFile.Path, nugetFile.LoadPackages(targetFramework, _settings.CheckTransitiveDependencies).Values.ToArray()); } } GetNonSensitivePackages(out var nonSensitivePackages); if (_settings.ErrorSettings.IgnoredPackages.Length > 0) { foreach (var(project, packages) in _projects.ToArray()) { IgnorePackages(in packages, _settings.ErrorSettings.IgnoredPackages, out var projPackages); _projects[project] = projPackages; } } Log.Logger.Information("Loaded {packageCount} packages", _projects.Sum(p => p.Value.Length)); if (_settings.ErrorSettings.BlockedPackages.Length > 0) { CheckBlockedPackages(); } if (_settings.ErrorSettings.AllowedPackages.Length > 0) { CheckAllowedPackages(); } Dictionary <string, Dictionary <string, Vulnerability> > vulnDict = null; if (_settings.OssIndex.Enabled) { Log.Logger.Verbose("Checking with OSSIndex for Vulnerabilities"); vulnDict = new Scanner(_nuGetFile, _settings.OssIndex.BreakIfCannotRun, UserAgentString, _settings.OssIndex.Username, _settings.OssIndex.ApiToken) .GetVulnerabilitiesForPackages(nonSensitivePackages.SelectMany(p => p.Value).ToArray()); } if (_settings.NVD.Enabled) { Log.Logger.Verbose("Checking the embedded NVD source for Vulnerabilities"); foreach (var(proj, pkgs) in _projects) { vulnDict = new NVD.Scanner(_nuGetFile, TimeSpan.FromSeconds(_settings.NVD.TimeoutInSeconds), _settings.NVD.BreakIfCannotRun, _settings.NVD.SelfUpdate) .GetVulnerabilitiesForPackages(pkgs, vulnDict); } } Log.Logger.Information("ignoring {ignoredCVECount} Vulnerabilities", _settings.ErrorSettings.IgnoredCvEs.Length); if (_settings.ErrorSettings.IgnoredCvEs.Length > 0) { VulnerabilityData.IgnoreCVEs(vulnDict, _settings.ErrorSettings.IgnoredCvEs); } ReportVulnerabilities(vulnDict); return(_settings.WarnOnly ? 0 : NumberOfVulnerabilities); } catch (Exception e) { var msBuildMessage = MsBuild.Log(_nuGetFile, MsBuild.Category.Error, $"Encountered a fatal exception while checking for Dependencies in {_nuGetFile}. Exception: {e}"); Console.WriteLine(msBuildMessage); Log.Logger.Fatal(msBuildMessage); return(-1); } }
public void BuildVulnerabilityTextReport(Dictionary <string, Dictionary <string, Vulnerability> > vulnerabilityDictionary, IEnumerable <NuGetPackage> pkgs, string nuGetFile, bool warnOnly, double cvss3Threshold, out int numberOfVulns) { numberOfVulns = 0; if (_separateMsBuildMessages) { MsBuildMessages = new List <string>(); } var logBuilder = new StringBuilder(VulnerabilityTextReport); var nuGetPackages = pkgs as NuGetPackage[] ?? pkgs.ToArray(); logBuilder.AppendLine($"{vulnerabilityDictionary.Sum(ve => ve.Value.Count)} vulnerabilities found in {nuGetPackages.Count()} packages for {nuGetFile}."); foreach (var pkg in nuGetPackages.Where(p => vulnerabilityDictionary.ContainsKey(p.PackageUrl.ToLower()))) { var vulnerabilities = vulnerabilityDictionary[pkg.PackageUrl.ToLower()]; logBuilder.AppendLine("*************************************"); warnOnly = warnOnly || !vulnerabilities.Any(v => v.Value.CvssScore >= cvss3Threshold); if (!warnOnly) { numberOfVulns++; } // TODO: Dependencies will need to be listed by package url when this is used. var dependantVulnerabilities = pkg.Dependencies.Where(dep => vulnerabilityDictionary.ContainsKey(dep)); var vulnTotalMSbuildMessage = MsBuild.Log(nuGetFile, warnOnly ? MsBuild.Category.Warning : MsBuild.Category.Error, pkg.LineNumber, pkg.LinePosition, $"{vulnerabilities.Count} vulnerabilities found for {pkg.Id} @ {pkg.Version}"); if (vulnerabilities.Any()) { if (_separateMsBuildMessages) { MsBuildMessages.Add(vulnTotalMSbuildMessage); } else { logBuilder.AppendLine(vulnTotalMSbuildMessage); } } var dependancies = dependantVulnerabilities as string[] ?? dependantVulnerabilities.ToArray(); if (dependancies.Any()) { var dependantVulnTotalMsBuildMessage = MsBuild.Log(nuGetFile, warnOnly ? MsBuild.Category.Warning : MsBuild.Category.Error, pkg.LineNumber, pkg.LinePosition, $"{dependancies.Count()} vulnerabilities found for dependencies of {pkg.Id} @ {pkg.Version}"); if (_separateMsBuildMessages) { MsBuildMessages.Add(dependantVulnTotalMsBuildMessage); } else { logBuilder.AppendLine(dependantVulnTotalMsBuildMessage); } } foreach (var cve in vulnerabilities.Keys) { warnOnly = warnOnly || vulnerabilities[cve].CvssScore <= cvss3Threshold && vulnerabilities[cve].CvssScore > -1; if (!warnOnly) { numberOfVulns++; } var vulnMsBuildMessage = MsBuild.Log(nuGetFile, warnOnly ? MsBuild.Category.Warning : MsBuild.Category.Error, cve, pkg.LineNumber, pkg.LinePosition, $"{vulnerabilities[cve].Description}"); if (_separateMsBuildMessages) { MsBuildMessages.Add(vulnMsBuildMessage); } else { logBuilder.AppendLine(vulnMsBuildMessage); } logBuilder.AppendLine($"Description: {vulnerabilities[cve].Description}"); logBuilder.AppendLine($"CVE: {cve}"); logBuilder.AppendLine($"CWE: {vulnerabilities[cve].Cwe}"); logBuilder.AppendLine($"CVSS Score: {vulnerabilities[cve].CvssScore}"); logBuilder.AppendLine($"CVSS Vector: {vulnerabilities[cve].Vector}"); if (vulnerabilities[cve].References != null && vulnerabilities[cve].References.Any()) { logBuilder.AppendLine("References:"); foreach (var reference in vulnerabilities[cve].References) { logBuilder.AppendLine(reference); } } logBuilder.AppendLine("---------------------------"); } foreach (var dependancy in dependancies) { vulnerabilities = vulnerabilityDictionary[dependancy]; foreach (var cve in vulnerabilities.Keys) { warnOnly = warnOnly || vulnerabilities[cve].CvssScore <= cvss3Threshold; if (!warnOnly) { numberOfVulns++; } var vulnMsBuildMessage = MsBuild.Log(nuGetFile, warnOnly ? MsBuild.Category.Warning : MsBuild.Category.Error, cve, pkg.LineNumber, pkg.LinePosition, $"{dependancy}: {vulnerabilities[cve].Description}"); if (_separateMsBuildMessages) { MsBuildMessages.Add(vulnMsBuildMessage); } else { logBuilder.AppendLine(vulnMsBuildMessage); } logBuilder.AppendLine($"Description: {vulnerabilities[cve].Description}"); logBuilder.AppendLine($"CVE: {cve}"); logBuilder.AppendLine($"CWE: {vulnerabilities[cve].Cwe}"); logBuilder.AppendLine($"CVSS Score: {vulnerabilities[cve].CvssScore}"); logBuilder.AppendLine($"CVSS Vector: {vulnerabilities[cve].Vector}"); // if (vulnerabilities[cve].Version?.Length > 0) // logBuilder.AppendLine($"Affected Version: {vulnerabilities[cve].Version}"); logBuilder.AppendLine("---------------------------"); } } } VulnerabilityTextReport = logBuilder.ToString(); }