feat: add Attestation Chain and Triage Evidence API clients and models

- Implemented Attestation Chain API client with methods for verifying, fetching, and managing attestation chains.
- Created models for Attestation Chain, including DSSE envelope structures and verification results.
- Developed Triage Evidence API client for fetching finding evidence, including methods for evidence retrieval by CVE and component.
- Added models for Triage Evidence, encapsulating evidence responses, entry points, boundary proofs, and VEX evidence.
- Introduced mock implementations for both API clients to facilitate testing and development.
This commit is contained in:
master
2025-12-18 13:15:13 +02:00
parent 7d5250238c
commit 00d2c99af9
118 changed files with 13463 additions and 151 deletions

View File

@@ -0,0 +1,128 @@
// -----------------------------------------------------------------------------
// ScoreExplanationWeights.cs
// Sprint: SPRINT_3800_0001_0002_score_explanation_service
// Description: Configurable weights for additive score explanation.
// -----------------------------------------------------------------------------
using System;
namespace StellaOps.Signals.Options;
/// <summary>
/// Configurable weights for the additive score explanation model.
/// Total score is computed as sum of weighted contributions (0-100 range).
/// </summary>
public sealed class ScoreExplanationWeights
{
/// <summary>
/// Multiplier for CVSS base score (10.0 CVSS × 5.0 = 50 points max).
/// </summary>
public double CvssMultiplier { get; set; } = 5.0;
/// <summary>
/// Points when path reaches entrypoint directly.
/// </summary>
public double EntrypointReachability { get; set; } = 25.0;
/// <summary>
/// Points for direct reachability (caller directly invokes vulnerable code).
/// </summary>
public double DirectReachability { get; set; } = 20.0;
/// <summary>
/// Points for runtime-observed reachability.
/// </summary>
public double RuntimeReachability { get; set; } = 22.0;
/// <summary>
/// Points for unknown reachability status.
/// </summary>
public double UnknownReachability { get; set; } = 12.0;
/// <summary>
/// Points for unreachable paths (typically 0).
/// </summary>
public double UnreachableReachability { get; set; } = 0.0;
/// <summary>
/// Points for HTTP/HTTPS exposed entrypoints.
/// </summary>
public double HttpExposure { get; set; } = 15.0;
/// <summary>
/// Points for gRPC exposed entrypoints.
/// </summary>
public double GrpcExposure { get; set; } = 12.0;
/// <summary>
/// Points for internal-only exposure (not internet-facing).
/// </summary>
public double InternalExposure { get; set; } = 5.0;
/// <summary>
/// Points for CLI or scheduled task exposure.
/// </summary>
public double CliExposure { get; set; } = 3.0;
/// <summary>
/// Discount (negative) when auth gate is detected.
/// </summary>
public double AuthGateDiscount { get; set; } = -3.0;
/// <summary>
/// Discount (negative) when admin-only gate is detected.
/// </summary>
public double AdminGateDiscount { get; set; } = -5.0;
/// <summary>
/// Discount (negative) when feature flag gate is detected.
/// </summary>
public double FeatureFlagDiscount { get; set; } = -2.0;
/// <summary>
/// Discount (negative) when non-default config gate is detected.
/// </summary>
public double NonDefaultConfigDiscount { get; set; } = -2.0;
/// <summary>
/// Multiplier for EPSS probability (0.0-1.0 → 0-10 points).
/// </summary>
public double EpssMultiplier { get; set; } = 10.0;
/// <summary>
/// Bonus for known exploited vulnerabilities (KEV).
/// </summary>
public double KevBonus { get; set; } = 10.0;
/// <summary>
/// Minimum score floor.
/// </summary>
public double MinScore { get; set; } = 0.0;
/// <summary>
/// Maximum score ceiling.
/// </summary>
public double MaxScore { get; set; } = 100.0;
/// <summary>
/// Validates the configuration.
/// </summary>
public void Validate()
{
if (CvssMultiplier < 0)
throw new ArgumentOutOfRangeException(nameof(CvssMultiplier), CvssMultiplier, "Must be non-negative.");
if (MinScore >= MaxScore)
throw new ArgumentException("MinScore must be less than MaxScore.");
// Discounts should be negative or zero
if (AuthGateDiscount > 0)
throw new ArgumentOutOfRangeException(nameof(AuthGateDiscount), AuthGateDiscount, "Discounts should be negative or zero.");
if (AdminGateDiscount > 0)
throw new ArgumentOutOfRangeException(nameof(AdminGateDiscount), AdminGateDiscount, "Discounts should be negative or zero.");
if (FeatureFlagDiscount > 0)
throw new ArgumentOutOfRangeException(nameof(FeatureFlagDiscount), FeatureFlagDiscount, "Discounts should be negative or zero.");
}
}

View File

@@ -12,6 +12,11 @@ public sealed class SignalsScoringOptions
/// </summary>
public SignalsGateMultiplierOptions GateMultipliers { get; } = new();
/// <summary>
/// Score explanation weights for additive risk scoring (Sprint: SPRINT_3800_0001_0002).
/// </summary>
public ScoreExplanationWeights ExplanationWeights { get; } = new();
/// <summary>
/// Confidence assigned when a path exists from entry point to target.
/// </summary>
@@ -68,6 +73,7 @@ public sealed class SignalsScoringOptions
public void Validate()
{
GateMultipliers.Validate();
ExplanationWeights.Validate();
EnsurePercent(nameof(ReachableConfidence), ReachableConfidence);
EnsurePercent(nameof(UnreachableConfidence), UnreachableConfidence);