// ----------------------------------------------------------------------------- // VulnSurface.cs // Sprint: SPRINT_3700_0002_0001_vuln_surfaces_core // Description: Core models for vulnerability surface computation. // ----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Text.Json.Serialization; namespace StellaOps.Scanner.VulnSurfaces.Models; /// /// A vulnerability surface represents the specific methods that changed /// between a vulnerable and fixed version of a package. /// public sealed record VulnSurface { /// /// Database ID. /// [JsonPropertyName("surface_id")] public long SurfaceId { get; init; } /// /// CVE ID (e.g., "CVE-2024-12345"). /// [JsonPropertyName("cve_id")] public required string CveId { get; init; } /// /// Package identifier (PURL format preferred). /// [JsonPropertyName("package_id")] public required string PackageId { get; init; } /// /// Ecosystem (nuget, npm, maven, pypi). /// [JsonPropertyName("ecosystem")] public required string Ecosystem { get; init; } /// /// Vulnerable version analyzed. /// [JsonPropertyName("vuln_version")] public required string VulnVersion { get; init; } /// /// Fixed version used for diff. /// [JsonPropertyName("fixed_version")] public required string FixedVersion { get; init; } /// /// Sink methods (vulnerable code locations). /// [JsonPropertyName("sinks")] public IReadOnlyList Sinks { get; init; } = []; /// /// Number of trigger methods that can reach sinks. /// [JsonPropertyName("trigger_count")] public int TriggerCount { get; init; } /// /// Surface computation status. /// [JsonPropertyName("status")] public VulnSurfaceStatus Status { get; init; } /// /// Confidence score (0.0-1.0). /// [JsonPropertyName("confidence")] public double Confidence { get; init; } = 1.0; /// /// When the surface was computed. /// [JsonPropertyName("computed_at")] public DateTimeOffset ComputedAt { get; init; } /// /// Error message if computation failed. /// [JsonPropertyName("error")] public string? Error { get; init; } } /// /// A sink method - a specific method that was modified in the security fix. /// public sealed record VulnSurfaceSink { /// /// Database ID. /// [JsonPropertyName("sink_id")] public long SinkId { get; init; } /// /// Parent surface ID. /// [JsonPropertyName("surface_id")] public long SurfaceId { get; init; } /// /// Normalized method key. /// [JsonPropertyName("method_key")] public required string MethodKey { get; init; } /// /// Declaring type/class name. /// [JsonPropertyName("declaring_type")] public required string DeclaringType { get; init; } /// /// Method name. /// [JsonPropertyName("method_name")] public required string MethodName { get; init; } /// /// Method signature. /// [JsonPropertyName("signature")] public string? Signature { get; init; } /// /// Type of change detected. /// [JsonPropertyName("change_type")] public MethodChangeType ChangeType { get; init; } /// /// Hash of the method in vulnerable version. /// [JsonPropertyName("vuln_hash")] public string? VulnHash { get; init; } /// /// Hash of the method in fixed version. /// [JsonPropertyName("fixed_hash")] public string? FixedHash { get; init; } /// /// Whether this sink is directly exploitable. /// [JsonPropertyName("is_direct_exploit")] public bool IsDirectExploit { get; init; } } /// /// Status of vulnerability surface computation. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum VulnSurfaceStatus { /// /// Computation pending. /// Pending, /// /// Computation in progress. /// Computing, /// /// Successfully computed. /// Computed, /// /// Computation failed. /// Failed, /// /// No diff detected (versions identical). /// NoDiff, /// /// Package not found. /// PackageNotFound } /// /// Type of method change detected. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum MethodChangeType { /// /// Method body was modified. /// Modified, /// /// Method was added in fixed version. /// Added, /// /// Method was removed in fixed version. /// Removed, /// /// Method signature changed. /// SignatureChanged }