Files
linqpad/Veracode/Veracode Module Analytics.linq
T

293 lines
12 KiB
C#

<Query Kind="Program">
<Reference>&lt;ProgramFilesX64&gt;\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll</Reference>
<NuGetReference>Amazon.Lambda.S3Events</NuGetReference>
<NuGetReference>AWSSDK.Core</NuGetReference>
<NuGetReference>AWSSDK.S3</NuGetReference>
<Namespace>Amazon</Namespace>
<Namespace>Amazon.Auth.AccessControlPolicy</Namespace>
<Namespace>Amazon.Auth.AccessControlPolicy.ActionIdentifiers</Namespace>
<Namespace>Amazon.Internal</Namespace>
<Namespace>Amazon.Lambda.S3Events</Namespace>
<Namespace>Amazon.MissingTypes</Namespace>
<Namespace>Amazon.Runtime</Namespace>
<Namespace>Amazon.Runtime.CredentialManagement</Namespace>
<Namespace>Amazon.Runtime.CredentialManagement.Internal</Namespace>
<Namespace>Amazon.Runtime.EventStreams</Namespace>
<Namespace>Amazon.Runtime.EventStreams.Internal</Namespace>
<Namespace>Amazon.Runtime.Internal</Namespace>
<Namespace>Amazon.Runtime.Internal.Auth</Namespace>
<Namespace>Amazon.Runtime.Internal.Settings</Namespace>
<Namespace>Amazon.Runtime.Internal.Transform</Namespace>
<Namespace>Amazon.Runtime.Internal.Util</Namespace>
<Namespace>Amazon.Runtime.SharedInterfaces</Namespace>
<Namespace>Amazon.Runtime.SharedInterfaces.Internal</Namespace>
<Namespace>Amazon.S3</Namespace>
<Namespace>Amazon.S3.Encryption</Namespace>
<Namespace>Amazon.S3.Encryption.Internal</Namespace>
<Namespace>Amazon.S3.Internal</Namespace>
<Namespace>Amazon.S3.IO</Namespace>
<Namespace>Amazon.S3.Model</Namespace>
<Namespace>Amazon.S3.Model.Internal.MarshallTransformations</Namespace>
<Namespace>Amazon.S3.Transfer</Namespace>
<Namespace>Amazon.S3.Util</Namespace>
<Namespace>Amazon.Util</Namespace>
<Namespace>Amazon.Util.Internal</Namespace>
<Namespace>Amazon.Util.Internal.PlatformServices</Namespace>
<Namespace>Newtonsoft.Json</Namespace>
<Namespace>Newtonsoft.Json.Converters</Namespace>
<Namespace>Newtonsoft.Json.Linq</Namespace>
<Namespace>Newtonsoft.Json.Schema</Namespace>
<Namespace>Newtonsoft.Json.Serialization</Namespace>
<Namespace>System</Namespace>
<Namespace>System.ComponentModel.Composition</Namespace>
<Namespace>System.ComponentModel.Composition.Hosting</Namespace>
<Namespace>System.ComponentModel.Composition.Primitives</Namespace>
<Namespace>System.ComponentModel.Composition.ReflectionModel</Namespace>
<Namespace>System.Diagnostics</Namespace>
<Namespace>System.Diagnostics.Tracing</Namespace>
<Namespace>System.IO.Compression</Namespace>
<Namespace>System.Net.Http</Namespace>
<Namespace>System.Net.Http.Headers</Namespace>
<Namespace>System.Numerics</Namespace>
<Namespace>ThirdParty.BouncyCastle.Asn1</Namespace>
<Namespace>ThirdParty.BouncyCastle.Asn1.Utilities</Namespace>
<Namespace>ThirdParty.BouncyCastle.Math</Namespace>
<Namespace>ThirdParty.BouncyCastle.OpenSsl</Namespace>
<Namespace>ThirdParty.BouncyCastle.Utilities.IO.Pem</Namespace>
<Namespace>ThirdParty.Ionic.Zlib</Namespace>
<Namespace>ThirdParty.Json.LitJson</Namespace>
<Namespace>ThirdParty.MD5</Namespace>
</Query>
//private string xmlAnalyticsFile = @"C:\Users\tlamb\Downloads\detailedreport_Strata_Jazz_Web_Jazz_web_201911511115217.xml";
private string xmlAnalyticsFile = @"C:\Users\tlamb\Downloads\detailedreport_Strata_Jazz_Web_Strata_Jazz_Web_201953102954843.xml";
public static class IntExtensions
{
public static string SeverityLabel(this int severity)
{
switch (severity)
{
case 5: return "Very High";
case 4: return "High";
case 3: return "Medium";
case 2: return "Low";
case 1: return "Very Low";
default: return "Informational";
}
}
}
internal class Module
{
public string name { get; set; }
public int score { get; set; }
public int totalNumberOfFlaws => flawsBySeverity.Values.Sum();
public int numberOfImportantFlaws => flawsBySeverity.Where(f => f.Key > 2).Select(f => f.Value).Sum();
private Dictionary<int, int> flawsBySeverity { get; set; }
public string flawsSummary => totalNumberOfFlaws > 0
? flawsBySeverity.Where(f => f.Value > 0).OrderByDescending(f => f.Key).Aggregate(new StringBuilder("Severity\n"), (x, y) =>
x.Append($"{y.Key.SeverityLabel()}: {y.Value}\r\n")).ToString().TrimEnd(new[] { '\r', '\n' })
: "";
public IEnumerable<ModuleFlaw> flaws { get; set; }
public string flawList => !flaws.Any()
? "" : flaws.Aggregate(new StringBuilder("path\tfile\tline\ttype\n"), (x, y) =>
x.AppendLine($"{(string.IsNullOrEmpty(y.sourcefile) ? "na" : Path.GetDirectoryName(y.sourcefile))}\t"
+ $"{(string.IsNullOrEmpty(y.sourcefile) ? "na" : Path.GetFileName(y.sourcefile))}\t{y.line}\t{y.type}")).ToString();
public Module(XElement module, IEnumerable<Cwe> cwes)
{
name = module.Attribute("name")?.Value;
score = Convert.ToInt32(module.Attribute("score")?.Value ?? "0");
flawsBySeverity = new Dictionary<int, int>();
flawsBySeverity[0] = Convert.ToInt32(module.Attribute("numflawssev0")?.Value ?? "0");
flawsBySeverity[1] = Convert.ToInt32(module.Attribute("numflawssev1")?.Value ?? "0");
flawsBySeverity[2] = Convert.ToInt32(module.Attribute("numflawssev2")?.Value ?? "0");
flawsBySeverity[3] = Convert.ToInt32(module.Attribute("numflawssev3")?.Value ?? "0");
flawsBySeverity[4] = Convert.ToInt32(module.Attribute("numflawssev4")?.Value ?? "0");
flawsBySeverity[5] = Convert.ToInt32(module.Attribute("numflawssev5")?.Value ?? "0");
var cx = cwes.Where(c => c.details.Any(d => d.module.Equals(name, StringComparison.CurrentCultureIgnoreCase)));
flaws = cx.SelectMany(c => c.details.Where(d => d.module.Equals(name, StringComparison.CurrentCultureIgnoreCase))
.Select(d => new ModuleFlaw(d)))
//.GroupBy(d => $"{d.type}{d.sourcefile}{d.line}").Select(grp => grp.First())
.OrderBy(grp => grp.sourcefile).ThenBy(grp => grp.line).ThenBy(grp => grp.type);
}
}
internal class ModuleFlaw
{
public string type { get; set; }
public string sourcefile { get; set; }
public int line { get; set; }
public bool hasMitigations { get; set; }
public ModuleFlaw(XElement element)
{
hasMitigations = element.Descendants().Any(sfd => sfd.Name.LocalName == "mitigations");
var regex = new Regex(@"\.!newinit_0_[0-9]|mscorlib_dll|system_xml_dll|system_web_dll|system_data_dll|system_directoryservices_dll|system_dll\.");
type = regex.Replace(element.Attribute("type")?.Value, "").Trim(new[] { '.' });
sourcefile = System.IO.Path.Combine((element.Attribute("sourcefilepath")?.Value ?? "").Replace("/jazz new", ""),
element.Attribute("sourcefile")?.Value ?? "");
line = Convert.ToInt32(element.Attribute("line")?.Value ?? "0");
}
public ModuleFlaw(Flaw flaw)
{
hasMitigations = flaw.hasMitigations;
type = flaw.type;
sourcefile = flaw.sourcefile;
line = flaw.line;
}
}
internal class Flaw : ModuleFlaw
{
public string module { get; set; }
public string description { get; set; }
public string grace_period_expires { get; set; }
public string remediation_status { get; set; }
public bool remediated => (remediation_status == "Fixed");
public Flaw(XElement element)
: base(element)
{
module = string.Join("\r\n", element.Attribute("module")?.Value.Split("/".ToCharArray()));
description = element.Attribute("description")?.Value;
DateTime parsedDate;
var theDate = System.Net.WebUtility.HtmlDecode(element.Attribute("grace_period_expires")?.Value).Replace(" UTC", "Z");
if (DateTime.TryParse(theDate, out parsedDate))
{
grace_period_expires = parsedDate.ToShortDateString();
}
else
{
grace_period_expires = string.Empty;
}
remediation_status = element.Attribute("remediation_status")?.Value;
}
}
internal class Cwe
{
public int id { get; set; }
public string category { get; set; }
public string name { get; set; }
public int severity { get; set; }
public int count { get; set; }
public string recommendation { get; set; }
public IEnumerable<Flaw> details { get; set; }
public Cwe(XElement module)
{
var categoryElement = module.Parent;
var severityElement = categoryElement.Parent;
severity = Convert.ToInt32(severityElement.Attribute("level")?.Value ?? "0");
category = categoryElement.Attribute("categoryname")?.Value ?? "";
var recommendations = categoryElement.Descendants().Where(d => d.Name.LocalName == "recommendations");
var content = recommendations.Descendants();
recommendation = string.Join("\r\n", content.ToList().Select(n => (n.Name.LocalName == "bulletitem" ? "- " : "") + n.Attribute("text")?.Value));
id = Convert.ToInt32(module.Attribute("cweid").Value);
name = module.Attribute("cwename").Value;
var staticFlaws = module.XPathSelectElements("./*").Where(m => m.Name.LocalName == "staticflaws");
var flaws = (staticFlaws.SelectMany(m => m.XPathSelectElements("./*").Where(sf => sf.Name.LocalName == "flaw")))?.ToList()
.Select(f => new Flaw(f));
//.GroupBy(grp => new { grp.module, grp.type, grp.description })
//.Select(x => x.First());
details = flaws
//.Where(f => !f.hasMitigations)
.OrderBy(d => d.type).ThenBy(d => d.module).ThenBy(d => d.description);
count = details.Count();
}
}
internal IEnumerable<Cwe> ParseVeracodeReport(XDocument xmlDoc)
{
return from module in xmlDoc.Descendants()
where module.Name.LocalName == "cwe"
&& module.Attributes().Any(a => a.Name == "cweid")
orderby Int32.Parse(module.Attribute("cweid").Value)
select new Cwe(module);
}
void Main()
{
XDocument xmlDoc = XDocument.Load(xmlAnalyticsFile);
//xmlDoc.DumpFormatted();
var cwes = ParseVeracodeReport(xmlDoc).Where(cwe => cwe.count > 0);
cwes
.SelectMany(c => c.details.Select(d => new
{
c.severity,
c.category,
c.id,
c.name,
d.type,
d.sourcefile,
line = d.line.ToString(),
d.hasMitigations,
d.module,
d.grace_period_expires,
d.remediation_status,
d.remediated
}))
.Where(c => !c.remediated)
.OrderByDescending(c => c.severity).ThenBy(c => c.category).ThenBy(c => c.module).ThenBy(c => c.sourcefile).ThenBy(c => c.type).ThenBy(c => c.line)
.GroupBy(c => new
{
Severity = c.severity.SeverityLabel(),
Category = c.category,
CWE_Id = c.id.ToString(),
Description = c.name
}, (key, group) => new
{
Severity = key,
Items = group.ToList().Select(g => new
{
g.type,
g.sourcefile,
g.line,
g.hasMitigations,
g.module,
g.grace_period_expires
})
})
.Dump();
// cwes.SelectMany(c => c.details.Select(d => new { c.category, c.name, d.type, d.sourcefile, line = d.line.ToString(), d.hasMitigations, d.module }))
// .Where(c => c.module.Contains(".dss."))
// .OrderBy(c => c.module).ThenBy(c => c.category).ThenBy(c => c.sourcefile).ThenBy(c => c.type).ThenBy(c => c.line)
// .Dump();
// cwes.Where(cwe => cwe.count > 1)
// .OrderByDescending(cwe => cwe.severity).ThenByDescending(cwe => cwe.count)
// .Select(cwe => new
// {
// severity = cwe.severity.SeverityLabel(),
// category_id = $"{cwe.category} ({cwe.id})",
// wo_Tests = cwe.count,
// cwe.name,
// cwe.recommendation })
// .Dump($"Summary: ({cwes.Where(cwe => cwe.count > 1).Count()})");
//
// var regex = new Regex(@"\.Test\.|\.IntegrationTests\.|\.UnitTests\.");
// var modules = from m in xmlDoc.Descendants()
// where m.Name.LocalName == "module" && m.Parent.Name.LocalName == "modules"
// select new Module(m, cwes);
// modules.Where(m => !regex.IsMatch(m.name) && m.totalNumberOfFlaws > 0)
// .Select(m => new {m.name, m.score, m.totalNumberOfFlaws, m.numberOfImportantFlaws, m.flawsSummary, m.flawList})
// .Dump($"Modules: ({modules.Count(m => !regex.IsMatch(m.name) && m.totalNumberOfFlaws > 0)})");
//
// modules.Where(m => !regex.IsMatch(m.name) && m.totalNumberOfFlaws > 0
// && new [] {"Strata.CS.Jazz.Biz.DSS.Episodes.EpisodeDefinition.dll","Strata.CS.Jazz.Biz.DSS.Episodes.dll","Strata.Administrator.Base.dll"}.Contains(m.name))
// .Select(m => new { m.name, m.flaws })
// .Dump($"Module Flaws: ({modules.Count(m => !regex.IsMatch(m.name) && m.totalNumberOfFlaws > 0)})");
//
// cwes.Where(cwe => cwe.count > 1)
// .OrderBy(cwe => cwe.id).ToList()
// .ForEach(cwe => cwe.details.Dump($"ID: {cwe.id} {cwe.name} ({cwe.count})"));
// //JsonConvert.SerializeObject(cwes, Newtonsoft.Json.Formatting.Indented).Dump("Json");
}