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

- 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:
master
2025-11-08 20:53:45 +02:00
parent 515975edc5
commit 536f6249a6
837 changed files with 37279 additions and 14675 deletions

View File

@@ -18,7 +18,8 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Spectre.Console;
using Spectre.Console.Rendering;
using StellaOps.Auth.Client;
@@ -28,7 +29,8 @@ using StellaOps.Cli.Services;
using StellaOps.Cli.Services.Models;
using StellaOps.Cli.Services.Models.AdvisoryAi;
using StellaOps.Cli.Telemetry;
using StellaOps.Cryptography;
using StellaOps.Cryptography;
using StellaOps.Cryptography.DependencyInjection;
using StellaOps.Cryptography.Kms;
namespace StellaOps.Cli.Commands;
@@ -6437,35 +6439,223 @@ internal static class CommandHandlers
return source;
}
private static async Task TriggerJobAsync(
IBackendOperationsClient client,
ILogger logger,
string jobKind,
IDictionary<string, object?> parameters,
CancellationToken cancellationToken)
{
JobTriggerResult result = await client.TriggerJobAsync(jobKind, parameters, cancellationToken).ConfigureAwait(false);
if (result.Success)
{
if (!string.IsNullOrWhiteSpace(result.Location))
{
logger.LogInformation("Job accepted. Track status at {Location}.", result.Location);
}
else if (result.Run is not null)
{
logger.LogInformation("Job accepted. RunId: {RunId} Status: {Status}", result.Run.RunId, result.Run.Status);
}
else
{
logger.LogInformation("Job accepted.");
}
Environment.ExitCode = 0;
}
else
{
logger.LogError("Job '{JobKind}' failed: {Message}", jobKind, result.Message);
Environment.ExitCode = 1;
}
}
}
private static async Task TriggerJobAsync(
IBackendOperationsClient client,
ILogger logger,
string jobKind,
IDictionary<string, object?> parameters,
CancellationToken cancellationToken)
{
JobTriggerResult result = await client.TriggerJobAsync(jobKind, parameters, cancellationToken).ConfigureAwait(false);
if (result.Success)
{
if (!string.IsNullOrWhiteSpace(result.Location))
{
logger.LogInformation("Job accepted. Track status at {Location}.", result.Location);
}
else if (result.Run is not null)
{
logger.LogInformation("Job accepted. RunId: {RunId} Status: {Status}", result.Run.RunId, result.Run.Status);
}
else
{
logger.LogInformation("Job accepted.");
}
Environment.ExitCode = 0;
}
else
{
logger.LogError("Job '{JobKind}' failed: {Message}", jobKind, result.Message);
Environment.ExitCode = 1;
}
}
public static Task HandleCryptoProvidersAsync(
IServiceProvider services,
bool verbose,
bool jsonOutput,
string? profileOverride,
CancellationToken cancellationToken)
{
using var scope = services.CreateScope();
var loggerFactory = scope.ServiceProvider.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger("crypto-providers");
var verbosity = scope.ServiceProvider.GetRequiredService<VerbosityState>();
var previousLevel = verbosity.MinimumLevel;
verbosity.MinimumLevel = verbose ? LogLevel.Debug : LogLevel.Information;
using var activity = CliActivitySource.Instance.StartActivity("cli.crypto.providers", ActivityKind.Internal);
using var duration = CliMetrics.MeasureCommandDuration("crypto providers");
try
{
var registry = scope.ServiceProvider.GetService<ICryptoProviderRegistry>();
if (registry is null)
{
logger.LogWarning("Crypto provider registry not available in this environment.");
AnsiConsole.MarkupLine("[yellow]Crypto subsystem is not configured in this environment.[/]");
return Task.CompletedTask;
}
var optionsMonitor = scope.ServiceProvider.GetService<IOptionsMonitor<CryptoProviderRegistryOptions>>();
var registryOptions = optionsMonitor?.CurrentValue ?? new CryptoProviderRegistryOptions();
var preferredOrder = DeterminePreferredOrder(registryOptions, profileOverride);
var providers = registry.Providers
.Select(provider => new ProviderInfo(
provider.Name,
provider.GetType().FullName ?? provider.GetType().Name,
DescribeProviderKeys(provider).ToList()))
.ToList();
if (jsonOutput)
{
var payload = new
{
activeProfile = registryOptions.ActiveProfile,
preferredOrder,
providers = providers.Select(info => new
{
info.Name,
info.Type,
keys = info.Keys.Select(k => new
{
k.KeyId,
k.AlgorithmId,
Metadata = k.Metadata
})
})
};
Console.WriteLine(JsonSerializer.Serialize(payload, new JsonSerializerOptions
{
WriteIndented = true
}));
Environment.ExitCode = 0;
return Task.CompletedTask;
}
RenderCryptoProviders(preferredOrder, providers);
Environment.ExitCode = 0;
}
finally
{
verbosity.MinimumLevel = previousLevel;
}
return Task.CompletedTask;
}
private static void RenderCryptoProviders(
IReadOnlyList<string> preferredOrder,
IReadOnlyCollection<ProviderInfo> providers)
{
if (preferredOrder.Count > 0)
{
AnsiConsole.MarkupLine("[cyan]Preferred order:[/] {0}", Markup.Escape(string.Join(", ", preferredOrder)));
}
else
{
AnsiConsole.MarkupLine("[yellow]Preferred order is not configured; using registration order.[/]");
}
var table = new Table().Border(TableBorder.Rounded);
table.AddColumn("Provider");
table.AddColumn("Type");
table.AddColumn("Keys");
foreach (var provider in providers)
{
var keySummary = provider.Keys.Count == 0
? "[grey]No signing keys exposed (managed externally).[/]"
: string.Join(Environment.NewLine, provider.Keys.Select(FormatDescriptor));
table.AddRow(
Markup.Escape(provider.Name),
Markup.Escape(provider.Type),
keySummary);
}
AnsiConsole.Write(table);
}
private static IReadOnlyList<CryptoProviderKeyDescriptor> DescribeProviderKeys(ICryptoProvider provider)
{
if (provider is ICryptoProviderDiagnostics diagnostics)
{
return diagnostics.DescribeKeys().ToList();
}
var signingKeys = provider.GetSigningKeys();
if (signingKeys.Count == 0)
{
return Array.Empty<CryptoProviderKeyDescriptor>();
}
var descriptors = new List<CryptoProviderKeyDescriptor>(signingKeys.Count);
foreach (var signingKey in signingKeys)
{
var metadata = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase)
{
["kind"] = signingKey.Kind.ToString(),
["createdAt"] = signingKey.CreatedAt.UtcDateTime.ToString("O"),
["providerHint"] = signingKey.Reference.ProviderHint
};
if (signingKey.ExpiresAt.HasValue)
{
metadata["expiresAt"] = signingKey.ExpiresAt.Value.UtcDateTime.ToString("O");
}
foreach (var pair in signingKey.Metadata)
{
metadata[$"meta.{pair.Key}"] = pair.Value;
}
descriptors.Add(new CryptoProviderKeyDescriptor(
provider.Name,
signingKey.Reference.KeyId,
signingKey.AlgorithmId,
metadata));
}
return descriptors;
}
private static IReadOnlyList<string> DeterminePreferredOrder(
CryptoProviderRegistryOptions? options,
string? overrideProfile)
{
if (options is null)
{
return Array.Empty<string>();
}
if (!string.IsNullOrWhiteSpace(overrideProfile) &&
options.Profiles.TryGetValue(overrideProfile, out var profile) &&
profile.PreferredProviders.Count > 0)
{
return profile.PreferredProviders
.Where(static provider => !string.IsNullOrWhiteSpace(provider))
.Select(static provider => provider.Trim())
.ToArray();
}
return options.ResolvePreferredProviders();
}
private static string FormatDescriptor(CryptoProviderKeyDescriptor descriptor)
{
if (descriptor.Metadata.Count == 0)
{
return $"{Markup.Escape(descriptor.KeyId)} ({Markup.Escape(descriptor.AlgorithmId)})";
}
var metadataText = string.Join(
", ",
descriptor.Metadata.Select(pair => $"{pair.Key}={pair.Value}"));
return $"{Markup.Escape(descriptor.KeyId)} ({Markup.Escape(descriptor.AlgorithmId)}){Environment.NewLine}[grey]{Markup.Escape(metadataText)}[/]";
}
private sealed record ProviderInfo(string Name, string Type, IReadOnlyList<CryptoProviderKeyDescriptor> Keys);
}