new advisories work and features gaps work

This commit is contained in:
master
2026-01-14 18:39:19 +02:00
parent 95d5898650
commit 15aeac8e8b
148 changed files with 16731 additions and 554 deletions

View File

@@ -0,0 +1,310 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (c) 2025 StellaOps
// Sprint: SPRINT_20260112_004_LB_attested_reduction_scoring (EWS-ATT-005)
// Description: Tests for attested-reduction scoring path
using StellaOps.Signals.EvidenceWeightedScore;
using Xunit;
namespace StellaOps.Signals.Tests.EvidenceWeightedScore;
[Trait("Category", "Unit")]
public sealed class AttestedReductionScoringTests
{
private readonly EvidenceWeightedScoreCalculator _calculator;
private readonly EvidenceWeightPolicy _policy;
public AttestedReductionScoringTests()
{
_calculator = new EvidenceWeightedScoreCalculator(TimeProvider.System);
_policy = new EvidenceWeightPolicy
{
Version = "ews.v1",
Profile = "test",
Weights = EvidenceWeights.Default,
AttestedReduction = AttestedReductionConfig.EnabledDefault
};
}
[Fact]
public void Calculate_WithAttestedReductionDisabled_UsesStandardPath()
{
var policy = _policy with { AttestedReduction = AttestedReductionConfig.Default };
var input = CreateInput(xpl: 0.5);
var result = _calculator.Calculate(input, policy);
Assert.DoesNotContain("attested-reduction", result.Flags);
}
[Fact]
public void Calculate_WithAttestedReductionEnabled_UsesAttestedPath()
{
var input = CreateInput(xpl: 0.5);
var result = _calculator.Calculate(input, _policy);
Assert.Contains("attested-reduction", result.Flags);
}
[Fact]
public void Calculate_AnchoredVexNotAffected_ReturnsZeroScore()
{
var input = CreateInput(
xpl: 0.8,
vexStatus: "not_affected",
vexAnchor: AnchorMetadata.CreateAnchored("sha256:abc", "vex/v1"));
var result = _calculator.Calculate(input, _policy);
Assert.Equal(0, result.Score);
Assert.Equal(ScoreBucket.Watchlist, result.Bucket);
Assert.Contains("anchored-vex", result.Flags);
Assert.Contains("vendor-na", result.Flags);
}
[Fact]
public void Calculate_AnchoredVexFixed_ReturnsZeroScore()
{
var input = CreateInput(
xpl: 0.9,
vexStatus: "fixed",
vexAnchor: AnchorMetadata.CreateAnchored("sha256:def", "vex/v1"));
var result = _calculator.Calculate(input, _policy);
Assert.Equal(0, result.Score);
Assert.Contains("anchored-vex", result.Flags);
}
[Fact]
public void Calculate_AnchoredAffectedWithRuntime_HardFails()
{
var input = CreateInput(
xpl: 0.5,
vexStatus: "affected",
vexAnchor: AnchorMetadata.CreateAnchored("sha256:ghi", "vex/v1"),
runtimeDetails: new RuntimeInput
{
Posture = RuntimePosture.EbpfDeep,
ObservationCount = 10,
RecencyFactor = 0.9,
DirectPathObserved = true,
Anchor = AnchorMetadata.CreateAnchored("sha256:jkl", "runtime/v1")
});
var result = _calculator.Calculate(input, _policy);
Assert.Equal(100, result.Score); // Hard fail = 1.0 * 100
Assert.Equal(ScoreBucket.ActNow, result.Bucket);
Assert.Contains("hard-fail", result.Flags);
Assert.Contains("anchored-vex", result.Flags);
Assert.Contains("anchored-runtime", result.Flags);
}
[Fact]
public void Calculate_UnanchoredVexNotAffected_DoesNotShortCircuit()
{
var input = CreateInput(
xpl: 0.5,
vexStatus: "not_affected",
vexAnchor: null); // No anchor
var result = _calculator.Calculate(input, _policy);
// Should not be 0 because VEX is not anchored
Assert.NotEqual(0, result.Score);
Assert.DoesNotContain("anchored-vex", result.Flags);
}
[Fact]
public void Calculate_AnchoredReachabilityNotReachable_AppliesBonus()
{
var input = CreateInput(
xpl: 0.5,
reachabilityDetails: new ReachabilityInput
{
State = ReachabilityState.NotReachable,
Confidence = 0.9,
Anchor = AnchorMetadata.CreateAnchored("sha256:mno", "reachability/v1")
});
var result = _calculator.Calculate(input, _policy);
Assert.Contains("anchored-reachability", result.Flags);
// Score should be affected by reachability bonus
}
[Fact]
public void Calculate_AnchoredBackportFixed_AppliesReduction()
{
var input = CreateInput(
xpl: 0.5,
backportDetails: new BackportInput
{
EvidenceTier = BackportEvidenceTier.SignedProof,
Status = BackportStatus.Fixed,
Confidence = 0.95,
Anchor = AnchorMetadata.CreateAnchored("sha256:pqr", "backport/v1")
});
var result = _calculator.Calculate(input, _policy);
Assert.Contains("anchored-backport", result.Flags);
// Score should be reduced by patch proof reduction
}
[Fact]
public void Calculate_WithAnchoredEvidence_ReducesEpssInfluence()
{
var input = CreateInput(
xpl: 0.8,
backportDetails: new BackportInput
{
EvidenceTier = BackportEvidenceTier.SignedProof,
Status = BackportStatus.NotAffected,
Confidence = 0.9,
Anchor = AnchorMetadata.CreateAnchored("sha256:stu", "backport/v1")
});
var result = _calculator.Calculate(input, _policy);
Assert.Contains("epss-reduced", result.Flags);
}
[Fact]
public void Calculate_PolicyDigest_IncludesAttestedReductionConfig()
{
var policy1 = _policy;
var policy2 = _policy with
{
AttestedReduction = _policy.AttestedReduction with { ReachabilityBonus = 0.5 }
};
var input = CreateInput(xpl: 0.5);
var result1 = _calculator.Calculate(input, policy1);
var result2 = _calculator.Calculate(input, policy2);
// Different attested-reduction config should produce different digests
Assert.NotEqual(result1.PolicyDigest, result2.PolicyDigest);
}
[Fact]
public void Calculate_AttestedReduction_IsDeterministic()
{
var input = CreateInput(
xpl: 0.5,
vexStatus: "affected",
backportDetails: new BackportInput
{
EvidenceTier = BackportEvidenceTier.VendorVex,
Status = BackportStatus.NotAffected,
Confidence = 0.8,
Anchor = AnchorMetadata.CreateAnchored("sha256:xyz", "backport/v1")
});
var result1 = _calculator.Calculate(input, _policy);
var result2 = _calculator.Calculate(input, _policy);
Assert.Equal(result1.Score, result2.Score);
Assert.Equal(result1.Bucket, result2.Bucket);
Assert.Equal(result1.PolicyDigest, result2.PolicyDigest);
}
[Fact]
public void Calculate_UnverifiedAnchor_DoesNotTriggerPrecedence()
{
var input = CreateInput(
xpl: 0.5,
vexStatus: "not_affected",
vexAnchor: new AnchorMetadata
{
IsAnchored = true,
DsseEnvelopeDigest = "sha256:abc",
PredicateType = "vex/v1",
VerificationStatus = AnchorVerificationStatus.Unverified // Not verified
});
var result = _calculator.Calculate(input, _policy);
// Should not short-circuit because anchor is unverified
Assert.NotEqual(0, result.Score);
Assert.DoesNotContain("anchored-vex", result.Flags);
}
[Fact]
public void Calculate_VerifiedAnchor_TriggersPrecedence()
{
var input = CreateInput(
xpl: 0.5,
vexStatus: "not_affected",
vexAnchor: new AnchorMetadata
{
IsAnchored = true,
DsseEnvelopeDigest = "sha256:abc",
PredicateType = "vex/v1",
VerificationStatus = AnchorVerificationStatus.Verified
});
var result = _calculator.Calculate(input, _policy);
Assert.Equal(0, result.Score);
Assert.Contains("anchored-vex", result.Flags);
}
[Theory]
[InlineData("not_affected", 0)]
[InlineData("fixed", 0)]
[InlineData("under_investigation", -1)] // -1 means not short-circuited
[InlineData("affected", -1)]
public void Calculate_VexStatusPrecedence_ReturnsExpectedScore(string vexStatus, int expectedScore)
{
var input = CreateInput(
xpl: 0.5,
vexStatus: vexStatus,
vexAnchor: AnchorMetadata.CreateAnchored("sha256:test", "vex/v1"));
var result = _calculator.Calculate(input, _policy);
if (expectedScore >= 0)
{
Assert.Equal(expectedScore, result.Score);
}
else
{
// Not short-circuited, should have some score
Assert.True(result.Score > 0 || result.Flags.Contains("hard-fail"));
}
}
private static EvidenceWeightedScoreInput CreateInput(
double xpl = 0.0,
double rch = 0.0,
double rts = 0.0,
double bkp = 0.0,
double src = 0.5,
double mit = 0.0,
string? vexStatus = null,
AnchorMetadata? vexAnchor = null,
ReachabilityInput? reachabilityDetails = null,
RuntimeInput? runtimeDetails = null,
BackportInput? backportDetails = null)
{
return new EvidenceWeightedScoreInput
{
FindingId = "CVE-2024-1234@pkg:test/lib@1.0.0",
Xpl = xpl,
Rch = rch,
Rts = rts,
Bkp = bkp,
Src = src,
Mit = mit,
VexStatus = vexStatus,
VexAnchor = vexAnchor,
ReachabilityDetails = reachabilityDetails,
RuntimeDetails = runtimeDetails,
BackportDetails = backportDetails
};
}
}