Add SBOM, symbols, traces, and VEX files for CVE-2022-21661 SQLi case
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Created CycloneDX and SPDX SBOM files for both reachable and unreachable images. - Added symbols.json detailing function entry and sink points in the WordPress code. - Included runtime traces for function calls in both reachable and unreachable scenarios. - Developed OpenVEX files indicating vulnerability status and justification for both cases. - Updated README for evaluator harness to guide integration with scanner output.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Policy.Engine.Domain;
|
||||
using StellaOps.Policy.Engine.Options;
|
||||
using StellaOps.Policy.Engine.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Tests;
|
||||
|
||||
public class PolicyActivationAuditorTests
|
||||
{
|
||||
[Fact]
|
||||
public void RecordActivation_WhenDisabled_DoesNothing()
|
||||
{
|
||||
var options = new PolicyEngineOptions();
|
||||
options.Activation.EmitAuditLogs = false;
|
||||
var logger = new TestLogger<PolicyActivationAuditor>();
|
||||
var auditor = new PolicyActivationAuditor(options, logger);
|
||||
var result = new PolicyActivationResult(PolicyActivationResultStatus.PackNotFound, null);
|
||||
|
||||
auditor.RecordActivation("pack", 1, "alice", null, result, null);
|
||||
|
||||
Assert.Empty(logger.Entries);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordActivation_WhenEnabled_WritesScopedLog()
|
||||
{
|
||||
var options = new PolicyEngineOptions();
|
||||
options.Activation.EmitAuditLogs = true;
|
||||
var logger = new TestLogger<PolicyActivationAuditor>();
|
||||
var auditor = new PolicyActivationAuditor(options, logger);
|
||||
|
||||
var revision = new PolicyRevisionRecord(1, true, PolicyRevisionStatus.Approved, DateTimeOffset.UtcNow);
|
||||
revision.AddApproval(new PolicyActivationApproval("alice", DateTimeOffset.UtcNow, "first"));
|
||||
var result = new PolicyActivationResult(PolicyActivationResultStatus.PendingSecondApproval, revision);
|
||||
|
||||
auditor.RecordActivation("pack-a", 3, "bob", "tenant-x", result, "please rollout");
|
||||
|
||||
var entry = Assert.Single(logger.Entries);
|
||||
Assert.Contains("pack-a", entry.Message);
|
||||
Assert.Contains("pendingsecondapproval", entry.Message.ToLowerInvariant());
|
||||
|
||||
var scope = Assert.IsType<Dictionary<string, object?>>(Assert.Single(entry.Scopes));
|
||||
Assert.Equal("tenant-x", scope["policy.tenant"]);
|
||||
Assert.Equal("bob", scope["policy.activation.actor"]);
|
||||
Assert.True((bool)scope["policy.activation.requires_two_person"]!);
|
||||
Assert.Equal(1, scope["policy.activation.approval_count"]);
|
||||
}
|
||||
|
||||
private sealed record LogEntry(LogLevel Level, string Message, IReadOnlyList<object?> Scopes);
|
||||
|
||||
private sealed class TestLogger<T> : ILogger<T>
|
||||
{
|
||||
private readonly Stack<object?> scopeStack = new();
|
||||
|
||||
public List<LogEntry> Entries { get; } = new();
|
||||
|
||||
IDisposable ILogger.BeginScope<TState>(TState state)
|
||||
{
|
||||
scopeStack.Push(state);
|
||||
return new DisposeAction(scopeStack);
|
||||
}
|
||||
|
||||
bool ILogger.IsEnabled(LogLevel logLevel) => true;
|
||||
|
||||
void ILogger.Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
Entries.Add(new LogEntry(logLevel, formatter(state, exception), scopeStack.Count > 0 ? new List<object?>(scopeStack) : new List<object?>()));
|
||||
}
|
||||
|
||||
private sealed class DisposeAction : IDisposable
|
||||
{
|
||||
private readonly Stack<object?> stack;
|
||||
|
||||
public DisposeAction(Stack<object?> stack)
|
||||
{
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (stack.Count > 0)
|
||||
{
|
||||
stack.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using StellaOps.Policy.Engine.Options;
|
||||
using StellaOps.Policy.Engine.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Tests;
|
||||
|
||||
public class PolicyActivationSettingsTests
|
||||
{
|
||||
[Fact]
|
||||
public void ResolveRequirement_WhenForceEnabled_IgnoresRequest()
|
||||
{
|
||||
var options = new PolicyEngineOptions();
|
||||
options.Activation.ForceTwoPersonApproval = true;
|
||||
var settings = new PolicyActivationSettings(options);
|
||||
|
||||
Assert.True(settings.ResolveRequirement(false));
|
||||
Assert.True(settings.ResolveRequirement(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResolveRequirement_UsesRequestedValue_WhenProvided()
|
||||
{
|
||||
var options = new PolicyEngineOptions();
|
||||
var settings = new PolicyActivationSettings(options);
|
||||
|
||||
Assert.True(settings.ResolveRequirement(true));
|
||||
Assert.False(settings.ResolveRequirement(false));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResolveRequirement_FallsBackToDefault_WhenRequestMissing()
|
||||
{
|
||||
var options = new PolicyEngineOptions();
|
||||
options.Activation.DefaultRequiresTwoPersonApproval = true;
|
||||
var settings = new PolicyActivationSettings(options);
|
||||
|
||||
Assert.True(settings.ResolveRequirement(null));
|
||||
|
||||
options.Activation.DefaultRequiresTwoPersonApproval = false;
|
||||
Assert.False(settings.ResolveRequirement(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Policy;
|
||||
using StellaOps.Policy.Engine.Compilation;
|
||||
using StellaOps.Policy.Engine.Options;
|
||||
using StellaOps.Policy.Engine.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Tests;
|
||||
|
||||
public sealed class PolicyCompilationServiceTests
|
||||
{
|
||||
private const string SimplePolicy = """
|
||||
policy "Sample" syntax "stella-dsl@1" {
|
||||
rule block_high priority 10 {
|
||||
when severity.normalized >= "High"
|
||||
then status := "blocked"
|
||||
because "Block high severity findings"
|
||||
}
|
||||
|
||||
rule warn_medium priority 20 {
|
||||
when severity.normalized >= "Medium"
|
||||
then status := "warn"
|
||||
because "Warn on medium severity findings"
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsComplexityReport_WhenWithinLimits()
|
||||
{
|
||||
var service = CreateService(maxComplexityScore: 1000, maxDurationMilliseconds: 1000, simulatedDurationMilliseconds: 12.3);
|
||||
var request = new PolicyCompileRequest(new PolicyDslPayload("stella-dsl@1", SimplePolicy));
|
||||
|
||||
var result = service.Compile(request);
|
||||
|
||||
Assert.True(result.Success);
|
||||
Assert.NotNull(result.Digest);
|
||||
Assert.NotNull(result.Complexity);
|
||||
Assert.True(result.Complexity!.Score > 0);
|
||||
Assert.True(result.Complexity.RuleCount >= 2);
|
||||
Assert.Equal(13, result.DurationMilliseconds);
|
||||
Assert.True(result.Diagnostics.IsDefaultOrEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_Fails_WhenComplexityExceedsThreshold()
|
||||
{
|
||||
var service = CreateService(maxComplexityScore: 1, maxDurationMilliseconds: 1000, simulatedDurationMilliseconds: 2);
|
||||
var request = new PolicyCompileRequest(new PolicyDslPayload("stella-dsl@1", SimplePolicy));
|
||||
|
||||
var result = service.Compile(request);
|
||||
|
||||
Assert.False(result.Success);
|
||||
Assert.NotNull(result.Complexity);
|
||||
Assert.Equal(2, result.DurationMilliseconds);
|
||||
var diagnostic = Assert.Single(result.Diagnostics);
|
||||
Assert.Equal(PolicyEngineDiagnosticCodes.CompilationComplexityExceeded, diagnostic.Code);
|
||||
Assert.Equal(PolicyIssueSeverity.Error, diagnostic.Severity);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_Fails_WhenDurationExceedsThreshold()
|
||||
{
|
||||
var service = CreateService(maxComplexityScore: 1000, maxDurationMilliseconds: 1, simulatedDurationMilliseconds: 5.2);
|
||||
var request = new PolicyCompileRequest(new PolicyDslPayload("stella-dsl@1", SimplePolicy));
|
||||
|
||||
var result = service.Compile(request);
|
||||
|
||||
Assert.False(result.Success);
|
||||
Assert.NotNull(result.Complexity);
|
||||
Assert.Equal(6, result.DurationMilliseconds);
|
||||
var diagnostic = Assert.Single(result.Diagnostics);
|
||||
Assert.Equal(PolicyEngineDiagnosticCodes.CompilationComplexityExceeded, diagnostic.Code);
|
||||
}
|
||||
|
||||
private static PolicyCompilationService CreateService(double maxComplexityScore, int maxDurationMilliseconds, double simulatedDurationMilliseconds)
|
||||
{
|
||||
var compiler = new PolicyCompiler();
|
||||
var analyzer = new PolicyComplexityAnalyzer();
|
||||
var options = new PolicyEngineOptions();
|
||||
options.Compilation.MaxComplexityScore = maxComplexityScore;
|
||||
options.Compilation.MaxDurationMilliseconds = maxDurationMilliseconds;
|
||||
var optionsMonitor = new StaticOptionsMonitor<PolicyEngineOptions>(options);
|
||||
var timeProvider = new FakeTimeProvider(simulatedDurationMilliseconds);
|
||||
return new PolicyCompilationService(compiler, analyzer, optionsMonitor, timeProvider);
|
||||
}
|
||||
|
||||
private sealed class StaticOptionsMonitor<T> : IOptionsMonitor<T>
|
||||
where T : class
|
||||
{
|
||||
public StaticOptionsMonitor(T value)
|
||||
{
|
||||
CurrentValue = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
public T CurrentValue { get; }
|
||||
|
||||
public T Get(string? name) => CurrentValue;
|
||||
|
||||
public IDisposable OnChange(Action<T, string> listener) => Disposable.Instance;
|
||||
|
||||
private sealed class Disposable : IDisposable
|
||||
{
|
||||
public static readonly Disposable Instance = new();
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeTimeProvider : TimeProvider
|
||||
{
|
||||
private readonly long elapsedCounts;
|
||||
private readonly long frequency = 1_000_000;
|
||||
private bool firstCall = true;
|
||||
|
||||
public FakeTimeProvider(double milliseconds)
|
||||
{
|
||||
elapsedCounts = (long)Math.Round(milliseconds * frequency / 1000d);
|
||||
}
|
||||
|
||||
public override long GetTimestamp()
|
||||
{
|
||||
if (firstCall)
|
||||
{
|
||||
firstCall = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return elapsedCounts;
|
||||
}
|
||||
|
||||
public override long TimestampFrequency => frequency;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user