Files
git.stella-ops.org/src/Scanner/__Libraries/StellaOps.Scanner.Benchmark/Metrics/BenchmarkMetrics.cs
StellaOps Bot 5146204f1b 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.
2025-12-22 23:21:21 +02:00

153 lines
4.2 KiB
C#

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; }
}