feat: add security sink detection patterns for JavaScript/TypeScript
- Introduced `sink-detect.js` with various security sink detection patterns categorized by type (e.g., command injection, SQL injection, file operations). - Implemented functions to build a lookup map for fast sink detection and to match sink calls against known patterns. - Added `package-lock.json` for dependency management.
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
namespace StellaOps.Scanner.Benchmark.Metrics;
|
||||
|
||||
/// <summary>
|
||||
/// Benchmark metrics for comparing scanner accuracy.
|
||||
/// </summary>
|
||||
public sealed record BenchmarkMetrics
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of true positive findings.
|
||||
/// </summary>
|
||||
public required int TruePositives { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of false positive findings.
|
||||
/// </summary>
|
||||
public required int FalsePositives { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of true negative findings.
|
||||
/// </summary>
|
||||
public required int TrueNegatives { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of false negative findings (missed vulnerabilities).
|
||||
/// </summary>
|
||||
public required int FalseNegatives { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Precision = TP / (TP + FP).
|
||||
/// </summary>
|
||||
public double Precision => TruePositives + FalsePositives > 0
|
||||
? (double)TruePositives / (TruePositives + FalsePositives)
|
||||
: 0;
|
||||
|
||||
/// <summary>
|
||||
/// Recall = TP / (TP + FN).
|
||||
/// </summary>
|
||||
public double Recall => TruePositives + FalseNegatives > 0
|
||||
? (double)TruePositives / (TruePositives + FalseNegatives)
|
||||
: 0;
|
||||
|
||||
/// <summary>
|
||||
/// F1 Score = 2 * (Precision * Recall) / (Precision + Recall).
|
||||
/// </summary>
|
||||
public double F1Score => Precision + Recall > 0
|
||||
? 2 * (Precision * Recall) / (Precision + Recall)
|
||||
: 0;
|
||||
|
||||
/// <summary>
|
||||
/// Accuracy = (TP + TN) / (TP + TN + FP + FN).
|
||||
/// </summary>
|
||||
public double Accuracy
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = TruePositives + TrueNegatives + FalsePositives + FalseNegatives;
|
||||
return total > 0 ? (double)(TruePositives + TrueNegatives) / total : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The scanner tool name.
|
||||
/// </summary>
|
||||
public required string ToolName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The image reference that was scanned.
|
||||
/// </summary>
|
||||
public string? ImageRef { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp when the benchmark was run.
|
||||
/// </summary>
|
||||
public required DateTimeOffset Timestamp { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggregated metrics across multiple images.
|
||||
/// </summary>
|
||||
public sealed record AggregatedMetrics
|
||||
{
|
||||
/// <summary>
|
||||
/// The scanner tool name.
|
||||
/// </summary>
|
||||
public required string ToolName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Total images scanned.
|
||||
/// </summary>
|
||||
public required int TotalImages { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Sum of true positives across all images.
|
||||
/// </summary>
|
||||
public required int TotalTruePositives { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Sum of false positives across all images.
|
||||
/// </summary>
|
||||
public required int TotalFalsePositives { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Sum of true negatives across all images.
|
||||
/// </summary>
|
||||
public required int TotalTrueNegatives { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Sum of false negatives across all images.
|
||||
/// </summary>
|
||||
public required int TotalFalseNegatives { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Aggregate precision.
|
||||
/// </summary>
|
||||
public double Precision => TotalTruePositives + TotalFalsePositives > 0
|
||||
? (double)TotalTruePositives / (TotalTruePositives + TotalFalsePositives)
|
||||
: 0;
|
||||
|
||||
/// <summary>
|
||||
/// Aggregate recall.
|
||||
/// </summary>
|
||||
public double Recall => TotalTruePositives + TotalFalseNegatives > 0
|
||||
? (double)TotalTruePositives / (TotalTruePositives + TotalFalseNegatives)
|
||||
: 0;
|
||||
|
||||
/// <summary>
|
||||
/// Aggregate F1 score.
|
||||
/// </summary>
|
||||
public double F1Score => Precision + Recall > 0
|
||||
? 2 * (Precision * Recall) / (Precision + Recall)
|
||||
: 0;
|
||||
|
||||
/// <summary>
|
||||
/// Breakdown by severity.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, BenchmarkMetrics>? BySeverity { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Breakdown by ecosystem.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, BenchmarkMetrics>? ByEcosystem { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Individual image metrics.
|
||||
/// </summary>
|
||||
public IReadOnlyList<BenchmarkMetrics>? PerImageMetrics { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp when the aggregation was computed.
|
||||
/// </summary>
|
||||
public required DateTimeOffset Timestamp { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user