feat: Add VEX compact fixture and implement offline verifier for Findings Ledger exports

- Introduced a new VEX compact fixture for testing purposes.
- Implemented `verify_export.py` script to validate Findings Ledger exports, ensuring deterministic ordering and applying redaction manifests.
- Added a lightweight stub `HarnessRunner` for unit tests to validate ledger hashing expectations.
- Documented tasks related to the Mirror Creator.
- Created models for entropy signals and implemented the `EntropyPenaltyCalculator` to compute penalties based on scanner outputs.
- Developed unit tests for `EntropyPenaltyCalculator` to ensure correct penalty calculations and handling of edge cases.
- Added tests for symbol ID normalization in the reachability scanner.
- Enhanced console status service with comprehensive unit tests for connection handling and error recovery.
- Included Cosign tool version 2.6.0 with checksums for various platforms.
This commit is contained in:
StellaOps Bot
2025-12-02 21:08:01 +02:00
parent 6d049905c7
commit 47168fec38
146 changed files with 4329 additions and 549 deletions

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@@ -37,33 +35,40 @@ public sealed class ReachabilityBuildStageExecutor : IScanStageExecutor
}
var nodeMap = entryTrace.Nodes.ToDictionary(n => n.Id);
var symbolMap = new Dictionary<int, string>(nodeMap.Count);
var unionNodes = new List<ReachabilityUnionNode>(entryTrace.Nodes.Length);
foreach (var node in entryTrace.Nodes)
{
var symbolId = ComputeSymbolId("shell", node.DisplayName, node.Kind.ToString());
var command = FormatCommand(node);
var symbolId = SymbolId.ForShell(node.DisplayName, command);
symbolMap[node.Id] = symbolId;
var source = node.Evidence is null
? null
: new ReachabilitySource("static", "entrytrace", node.Evidence.Path);
var attributes = new Dictionary<string, string>
{
["code_id"] = CodeId.FromSymbolId(symbolId)
};
unionNodes.Add(new ReachabilityUnionNode(
SymbolId: symbolId,
Lang: "shell",
Kind: node.Kind.ToString().ToLowerInvariant(),
Display: node.DisplayName,
Source: source));
Source: source,
Attributes: attributes));
}
var unionEdges = new List<ReachabilityUnionEdge>(entryTrace.Edges.Length);
foreach (var edge in entryTrace.Edges)
{
if (!nodeMap.TryGetValue(edge.FromNodeId, out var fromNode) || !nodeMap.TryGetValue(edge.ToNodeId, out var toNode))
if (!symbolMap.TryGetValue(edge.FromNodeId, out var fromId) || !symbolMap.TryGetValue(edge.ToNodeId, out var toId))
{
continue;
}
var fromId = ComputeSymbolId("shell", fromNode.DisplayName, fromNode.Kind.ToString());
var toId = ComputeSymbolId("shell", toNode.DisplayName, toNode.Kind.ToString());
unionEdges.Add(new ReachabilityUnionEdge(
From: fromId,
To: toId,
@@ -78,15 +83,13 @@ public sealed class ReachabilityBuildStageExecutor : IScanStageExecutor
return ValueTask.CompletedTask;
}
private static string ComputeSymbolId(string lang, string display, string kind)
private static string FormatCommand(EntryTraceNode node)
{
using var sha = SHA256.Create();
var input = Encoding.UTF8.GetBytes((display ?? string.Empty) + "|" + (kind ?? string.Empty));
var hash = sha.ComputeHash(input);
var base64 = Convert.ToBase64String(hash)
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
return $"sym:{lang}:{base64}";
if (!node.Arguments.IsDefaultOrEmpty && node.Arguments.Length > 0)
{
return string.Join(' ', node.Arguments);
}
return node.Kind.ToString();
}
}