feat: Add VEX Status Chip component and integration tests for reachability drift detection
- Introduced `VexStatusChipComponent` to display VEX status with color coding and tooltips. - Implemented integration tests for reachability drift detection, covering various scenarios including drift detection, determinism, and error handling. - Enhanced `ScannerToSignalsReachabilityTests` with a null implementation of `ICallGraphSyncService` for better test isolation. - Updated project references to include the new Reachability Drift library.
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Security Atoms - Canonical propositions for vulnerability disposition.
|
||||
* Sprint: SPRINT_3600_0001_0001 (Trust Algebra and Lattice Engine)
|
||||
* Task: TRUST-002
|
||||
*
|
||||
* Defines the orthogonal atomic propositions used to represent security
|
||||
* knowledge about a Subject (artifact + component + vulnerability).
|
||||
*
|
||||
* External VEX formats (CycloneDX, OpenVEX, CSAF) are normalized into
|
||||
* these canonical atoms for uniform aggregation and decision making.
|
||||
*/
|
||||
|
||||
namespace StellaOps.Policy.TrustLattice;
|
||||
|
||||
/// <summary>
|
||||
/// Canonical security propositions for vulnerability disposition.
|
||||
/// Each atom is a boolean proposition that can have a K4 truth value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These atoms are intentionally orthogonal; external VEX formats
|
||||
/// are normalized into combinations of these atoms.
|
||||
/// </remarks>
|
||||
public enum SecurityAtom
|
||||
{
|
||||
/// <summary>
|
||||
/// PRESENT: The component instance exists in the artifact/context.
|
||||
/// False when component is not actually in the artifact despite declaration.
|
||||
/// </summary>
|
||||
Present = 1,
|
||||
|
||||
/// <summary>
|
||||
/// APPLIES: The vulnerability applies to this component (version/range/CPE match).
|
||||
/// False when version is outside affected range.
|
||||
/// </summary>
|
||||
Applies = 2,
|
||||
|
||||
/// <summary>
|
||||
/// REACHABLE: The vulnerable code is reachable in the given execution context.
|
||||
/// False when code paths to vulnerability are not exercised.
|
||||
/// </summary>
|
||||
Reachable = 3,
|
||||
|
||||
/// <summary>
|
||||
/// MITIGATED: Controls exist that prevent exploitation.
|
||||
/// True when compiler protections, runtime guards, WAF rules, etc. are active.
|
||||
/// </summary>
|
||||
Mitigated = 4,
|
||||
|
||||
/// <summary>
|
||||
/// FIXED: Remediation has been applied to the artifact.
|
||||
/// True when patches, upgrades, or other fixes are in place.
|
||||
/// </summary>
|
||||
Fixed = 5,
|
||||
|
||||
/// <summary>
|
||||
/// MISATTRIBUTED: The finding is a false association (false positive).
|
||||
/// True when the vulnerability was incorrectly linked to this component.
|
||||
/// </summary>
|
||||
Misattributed = 6,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for SecurityAtom.
|
||||
/// </summary>
|
||||
public static class SecurityAtomExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a human-readable display name for the atom.
|
||||
/// </summary>
|
||||
public static string ToDisplayName(this SecurityAtom atom) => atom switch
|
||||
{
|
||||
SecurityAtom.Present => "Component Present",
|
||||
SecurityAtom.Applies => "Vulnerability Applies",
|
||||
SecurityAtom.Reachable => "Code Reachable",
|
||||
SecurityAtom.Mitigated => "Mitigations Active",
|
||||
SecurityAtom.Fixed => "Remediation Applied",
|
||||
SecurityAtom.Misattributed => "False Association",
|
||||
_ => atom.ToString(),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns the canonical string representation for serialization.
|
||||
/// </summary>
|
||||
public static string ToCanonicalName(this SecurityAtom atom) => atom switch
|
||||
{
|
||||
SecurityAtom.Present => "PRESENT",
|
||||
SecurityAtom.Applies => "APPLIES",
|
||||
SecurityAtom.Reachable => "REACHABLE",
|
||||
SecurityAtom.Mitigated => "MITIGATED",
|
||||
SecurityAtom.Fixed => "FIXED",
|
||||
SecurityAtom.Misattributed => "MISATTRIBUTED",
|
||||
_ => atom.ToString().ToUpperInvariant(),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Parses a canonical name to SecurityAtom.
|
||||
/// </summary>
|
||||
public static SecurityAtom? FromCanonicalName(string name)
|
||||
{
|
||||
return name?.ToUpperInvariant() switch
|
||||
{
|
||||
"PRESENT" => SecurityAtom.Present,
|
||||
"APPLIES" => SecurityAtom.Applies,
|
||||
"REACHABLE" => SecurityAtom.Reachable,
|
||||
"MITIGATED" => SecurityAtom.Mitigated,
|
||||
"FIXED" => SecurityAtom.Fixed,
|
||||
"MISATTRIBUTED" => SecurityAtom.Misattributed,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all defined security atoms.
|
||||
/// </summary>
|
||||
public static IEnumerable<SecurityAtom> All()
|
||||
{
|
||||
yield return SecurityAtom.Present;
|
||||
yield return SecurityAtom.Applies;
|
||||
yield return SecurityAtom.Reachable;
|
||||
yield return SecurityAtom.Mitigated;
|
||||
yield return SecurityAtom.Fixed;
|
||||
yield return SecurityAtom.Misattributed;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user