Files
git.stella-ops.org/src/Scanner/__Libraries/StellaOps.Scanner.Reachability/Layer1/ILayer1Analyzer.cs

138 lines
4.0 KiB
C#

// SPDX-License-Identifier: BUSL-1.1
// Copyright (c) StellaOps
using System.Collections.Immutable;
using StellaOps.Scanner.Reachability.Stack;
namespace StellaOps.Scanner.Reachability.Layer1;
/// <summary>
/// Layer 1 analyzer: Static call graph reachability.
/// Determines if vulnerable symbols are reachable from application entrypoints
/// via static code analysis.
/// </summary>
public interface ILayer1Analyzer
{
/// <summary>
/// Analyzes static reachability of a vulnerable symbol.
/// </summary>
/// <param name="symbol">The vulnerable symbol to check</param>
/// <param name="graph">The call graph to analyze</param>
/// <param name="entrypoints">Known application entrypoints</param>
/// <param name="ct">Cancellation token</param>
/// <returns>Layer 1 reachability analysis result</returns>
Task<ReachabilityLayer1> AnalyzeAsync(
VulnerableSymbol symbol,
CallGraph graph,
ImmutableArray<Entrypoint> entrypoints,
CancellationToken ct = default);
}
/// <summary>
/// A call graph representing method/function calls in the application.
/// </summary>
public sealed record CallGraph
{
/// <summary>Unique identifier for this call graph</summary>
public required string Id { get; init; }
/// <summary>When this call graph was generated</summary>
public required DateTimeOffset GeneratedAt { get; init; }
/// <summary>All nodes in the graph</summary>
public ImmutableArray<CallGraphNode> Nodes { get; init; } = [];
/// <summary>All edges (calls) in the graph</summary>
public ImmutableArray<CallGraphEdge> Edges { get; init; } = [];
/// <summary>Source of this call graph</summary>
public required CallGraphSource Source { get; init; }
/// <summary>Language/platform this graph represents</summary>
public required string Language { get; init; }
}
/// <summary>
/// A node in the call graph (method/function).
/// </summary>
public sealed record CallGraphNode(
string Id,
string Name,
string? ClassName,
string? Namespace,
string? FileName,
int? LineNumber,
bool IsEntrypoint,
bool IsExternal
);
/// <summary>
/// An edge in the call graph (call from one method to another).
/// </summary>
public sealed record CallGraphEdge(
string FromNodeId,
string ToNodeId,
CallSiteType CallType,
int? LineNumber,
bool IsConditional
);
/// <summary>
/// Source of a call graph.
/// </summary>
public enum CallGraphSource
{
/// <summary>Roslyn/ILSpy analysis for .NET</summary>
DotNetAnalysis,
/// <summary>TypeScript/JavaScript AST analysis</summary>
NodeAnalysis,
/// <summary>javap/ASM analysis for Java</summary>
JavaAnalysis,
/// <summary>go/analysis for Go</summary>
GoAnalysis,
/// <summary>Python AST analysis</summary>
PythonAnalysis,
/// <summary>Binary disassembly</summary>
BinaryAnalysis,
/// <summary>Combined from multiple sources</summary>
Composite
}
/// <summary>
/// Input for Layer 1 analysis.
/// </summary>
public sealed record Layer1AnalysisInput
{
public required VulnerableSymbol Symbol { get; init; }
public required CallGraph Graph { get; init; }
public ImmutableArray<Entrypoint> Entrypoints { get; init; } = [];
public Layer1AnalysisOptions? Options { get; init; }
}
/// <summary>
/// Options for Layer 1 analysis.
/// </summary>
public sealed record Layer1AnalysisOptions
{
/// <summary>Maximum call path depth to explore</summary>
public int MaxPathDepth { get; init; } = 100;
/// <summary>Maximum number of paths to return</summary>
public int MaxPaths { get; init; } = 10;
/// <summary>Include paths through external libraries</summary>
public bool IncludeExternalPaths { get; init; } = true;
/// <summary>Consider reflection calls as potential paths</summary>
public bool ConsiderReflection { get; init; } = true;
/// <summary>Consider dynamic dispatch as potential paths</summary>
public bool ConsiderDynamicDispatch { get; init; } = true;
}