feat: Implement IsolatedReplayContext for deterministic audit replay
- Added IsolatedReplayContext class to provide an isolated environment for replaying audit bundles without external calls. - Introduced methods for initializing the context, verifying input digests, and extracting inputs for policy evaluation. - Created supporting interfaces and options for context configuration. feat: Create ReplayExecutor for executing policy re-evaluation and verdict comparison - Developed ReplayExecutor class to handle the execution of replay processes, including input verification and verdict comparison. - Implemented detailed drift detection and error handling during replay execution. - Added interfaces for policy evaluation and replay execution options. feat: Add ScanSnapshotFetcher for fetching scan data and snapshots - Introduced ScanSnapshotFetcher class to retrieve necessary scan data and snapshots for audit bundle creation. - Implemented methods to fetch scan metadata, advisory feeds, policy snapshots, and VEX statements. - Created supporting interfaces for scan data, feed snapshots, and policy snapshots.
This commit is contained in:
@@ -107,3 +107,119 @@ public sealed record ReachabilityExplanationDto(
|
||||
[property: JsonPropertyName("why")] IReadOnlyList<ExplanationReasonDto>? Why = null,
|
||||
[property: JsonPropertyName("evidence")] EvidenceChainDto? Evidence = null,
|
||||
[property: JsonPropertyName("spineId")] string? SpineId = null);
|
||||
|
||||
// ============================================================
|
||||
// Three-Layer Reachability Stack Contracts
|
||||
// ============================================================
|
||||
|
||||
/// <summary>
|
||||
/// Three-layer reachability stack providing complete exploitability analysis.
|
||||
/// All three layers must align for a vulnerability to be considered exploitable.
|
||||
/// </summary>
|
||||
public sealed record ReachabilityStackDto(
|
||||
[property: JsonPropertyName("id")] string Id,
|
||||
[property: JsonPropertyName("findingId")] string FindingId,
|
||||
[property: JsonPropertyName("symbol")] VulnerableSymbolDto Symbol,
|
||||
[property: JsonPropertyName("layer1")] ReachabilityLayer1Dto Layer1,
|
||||
[property: JsonPropertyName("layer2")] ReachabilityLayer2Dto Layer2,
|
||||
[property: JsonPropertyName("layer3")] ReachabilityLayer3Dto Layer3,
|
||||
[property: JsonPropertyName("verdict")] string Verdict,
|
||||
[property: JsonPropertyName("explanation")] string Explanation,
|
||||
[property: JsonPropertyName("analyzedAt")] DateTimeOffset AnalyzedAt);
|
||||
|
||||
/// <summary>
|
||||
/// Vulnerable symbol being analyzed.
|
||||
/// </summary>
|
||||
public sealed record VulnerableSymbolDto(
|
||||
[property: JsonPropertyName("name")] string Name,
|
||||
[property: JsonPropertyName("library")] string? Library,
|
||||
[property: JsonPropertyName("version")] string? Version,
|
||||
[property: JsonPropertyName("vulnerabilityId")] string VulnerabilityId,
|
||||
[property: JsonPropertyName("type")] string Type);
|
||||
|
||||
/// <summary>
|
||||
/// Layer 1: Static call graph analysis - is the vulnerable function reachable from entrypoints?
|
||||
/// </summary>
|
||||
public sealed record ReachabilityLayer1Dto(
|
||||
[property: JsonPropertyName("isReachable")] bool IsReachable,
|
||||
[property: JsonPropertyName("confidence")] string Confidence,
|
||||
[property: JsonPropertyName("pathCount")] int PathCount,
|
||||
[property: JsonPropertyName("entrypointCount")] int EntrypointCount,
|
||||
[property: JsonPropertyName("analysisMethod")] string? AnalysisMethod = null,
|
||||
[property: JsonPropertyName("paths")] IReadOnlyList<CallPathDto>? Paths = null);
|
||||
|
||||
/// <summary>
|
||||
/// Layer 2: Binary resolution - does the dynamic loader actually link the symbol?
|
||||
/// </summary>
|
||||
public sealed record ReachabilityLayer2Dto(
|
||||
[property: JsonPropertyName("isResolved")] bool IsResolved,
|
||||
[property: JsonPropertyName("confidence")] string Confidence,
|
||||
[property: JsonPropertyName("reason")] string? Reason = null,
|
||||
[property: JsonPropertyName("resolution")] SymbolResolutionDto? Resolution = null,
|
||||
[property: JsonPropertyName("loaderRule")] LoaderRuleDto? LoaderRule = null);
|
||||
|
||||
/// <summary>
|
||||
/// Layer 3: Runtime gating - is execution blocked by feature flags, configs, or environment?
|
||||
/// </summary>
|
||||
public sealed record ReachabilityLayer3Dto(
|
||||
[property: JsonPropertyName("isGated")] bool IsGated,
|
||||
[property: JsonPropertyName("outcome")] string Outcome,
|
||||
[property: JsonPropertyName("confidence")] string Confidence,
|
||||
[property: JsonPropertyName("conditions")] IReadOnlyList<GatingConditionDto>? Conditions = null);
|
||||
|
||||
/// <summary>
|
||||
/// Call path from entrypoint to vulnerable symbol.
|
||||
/// </summary>
|
||||
public sealed record CallPathDto(
|
||||
[property: JsonPropertyName("entrypoint")] EntrypointDto? Entrypoint = null,
|
||||
[property: JsonPropertyName("sites")] IReadOnlyList<CallSiteDto>? Sites = null,
|
||||
[property: JsonPropertyName("confidence")] double Confidence = 0,
|
||||
[property: JsonPropertyName("hasConditionals")] bool HasConditionals = false);
|
||||
|
||||
/// <summary>
|
||||
/// Application entrypoint.
|
||||
/// </summary>
|
||||
public sealed record EntrypointDto(
|
||||
[property: JsonPropertyName("name")] string Name,
|
||||
[property: JsonPropertyName("type")] string Type,
|
||||
[property: JsonPropertyName("file")] string? File = null,
|
||||
[property: JsonPropertyName("description")] string? Description = null);
|
||||
|
||||
/// <summary>
|
||||
/// Call site in the call path.
|
||||
/// </summary>
|
||||
public sealed record CallSiteDto(
|
||||
[property: JsonPropertyName("method")] string Method,
|
||||
[property: JsonPropertyName("type")] string? Type = null,
|
||||
[property: JsonPropertyName("file")] string? File = null,
|
||||
[property: JsonPropertyName("line")] int? Line = null,
|
||||
[property: JsonPropertyName("callType")] string? CallType = null);
|
||||
|
||||
/// <summary>
|
||||
/// Symbol resolution details from binary analysis.
|
||||
/// </summary>
|
||||
public sealed record SymbolResolutionDto(
|
||||
[property: JsonPropertyName("symbolName")] string SymbolName,
|
||||
[property: JsonPropertyName("resolvedLibrary")] string? ResolvedLibrary = null,
|
||||
[property: JsonPropertyName("resolvedVersion")] string? ResolvedVersion = null,
|
||||
[property: JsonPropertyName("symbolVersion")] string? SymbolVersion = null,
|
||||
[property: JsonPropertyName("method")] string? Method = null);
|
||||
|
||||
/// <summary>
|
||||
/// Loader rule that applies to symbol resolution.
|
||||
/// </summary>
|
||||
public sealed record LoaderRuleDto(
|
||||
[property: JsonPropertyName("type")] string Type,
|
||||
[property: JsonPropertyName("value")] string Value,
|
||||
[property: JsonPropertyName("source")] string? Source = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gating condition that may block execution.
|
||||
/// </summary>
|
||||
public sealed record GatingConditionDto(
|
||||
[property: JsonPropertyName("type")] string Type,
|
||||
[property: JsonPropertyName("description")] string Description,
|
||||
[property: JsonPropertyName("configKey")] string? ConfigKey = null,
|
||||
[property: JsonPropertyName("envVar")] string? EnvVar = null,
|
||||
[property: JsonPropertyName("isBlocking")] bool IsBlocking = false,
|
||||
[property: JsonPropertyName("status")] string? Status = null);
|
||||
|
||||
Reference in New Issue
Block a user