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:
@@ -1,28 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Concelier.Models;
|
||||
|
||||
namespace StellaOps.Concelier.Exporter.Json;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Cryptography;
|
||||
|
||||
namespace StellaOps.Concelier.Exporter.Json;
|
||||
|
||||
/// <summary>
|
||||
/// Writes canonical advisory snapshots into a vuln-list style directory tree with deterministic ordering.
|
||||
/// </summary>
|
||||
public sealed class JsonExportSnapshotBuilder
|
||||
{
|
||||
private static readonly Encoding Utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
|
||||
private readonly JsonExportOptions _options;
|
||||
private readonly IJsonExportPathResolver _pathResolver;
|
||||
|
||||
public JsonExportSnapshotBuilder(JsonExportOptions options, IJsonExportPathResolver pathResolver)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_pathResolver = pathResolver ?? throw new ArgumentNullException(nameof(pathResolver));
|
||||
}
|
||||
private static readonly Encoding Utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
|
||||
private readonly JsonExportOptions _options;
|
||||
private readonly IJsonExportPathResolver _pathResolver;
|
||||
private readonly ICryptoHash _hash;
|
||||
|
||||
public JsonExportSnapshotBuilder(
|
||||
JsonExportOptions options,
|
||||
IJsonExportPathResolver pathResolver,
|
||||
ICryptoHash? hash = null)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_pathResolver = pathResolver ?? throw new ArgumentNullException(nameof(pathResolver));
|
||||
_hash = hash ?? CryptoHashFactory.CreateDefault();
|
||||
}
|
||||
|
||||
public Task<JsonExportResult> WriteAsync(
|
||||
IReadOnlyCollection<Advisory> advisories,
|
||||
@@ -97,7 +102,7 @@ public sealed class JsonExportSnapshotBuilder
|
||||
await File.WriteAllBytesAsync(destination, bytes, cancellationToken).ConfigureAwait(false);
|
||||
File.SetLastWriteTimeUtc(destination, exportedAt.UtcDateTime);
|
||||
|
||||
var digest = ComputeDigest(bytes);
|
||||
var digest = ComputeDigest(bytes);
|
||||
files.Add(new JsonExportFile(entry.RelativePath, bytes.LongLength, digest));
|
||||
totalBytes += bytes.LongLength;
|
||||
}
|
||||
@@ -232,10 +237,9 @@ public sealed class JsonExportSnapshotBuilder
|
||||
|
||||
private sealed record PathResolution(Advisory Advisory, string RelativePath, IReadOnlyList<string> Segments);
|
||||
|
||||
private static string ComputeDigest(ReadOnlySpan<byte> payload)
|
||||
{
|
||||
var hash = SHA256.HashData(payload);
|
||||
var hex = Convert.ToHexString(hash).ToLowerInvariant();
|
||||
return $"sha256:{hex}";
|
||||
}
|
||||
}
|
||||
private string ComputeDigest(ReadOnlySpan<byte> payload)
|
||||
{
|
||||
var hex = _hash.ComputeHashHex(payload, HashAlgorithms.Sha256);
|
||||
return $"sha256:{hex}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Concelier.Core.Events;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Exporting;
|
||||
using StellaOps.Cryptography;
|
||||
using StellaOps.Plugin;
|
||||
|
||||
namespace StellaOps.Concelier.Exporter.Json;
|
||||
@@ -51,15 +53,16 @@ public sealed class JsonFeedExporter : IFeedExporter
|
||||
|
||||
public async Task ExportAsync(IServiceProvider services, CancellationToken cancellationToken)
|
||||
{
|
||||
var exportedAt = _timeProvider.GetUtcNow();
|
||||
var exportId = exportedAt.ToString(_options.DirectoryNameFormat, CultureInfo.InvariantCulture);
|
||||
var exportRoot = Path.GetFullPath(_options.OutputRoot);
|
||||
var exportedAt = _timeProvider.GetUtcNow();
|
||||
var exportId = exportedAt.ToString(_options.DirectoryNameFormat, CultureInfo.InvariantCulture);
|
||||
var exportRoot = Path.GetFullPath(_options.OutputRoot);
|
||||
|
||||
_logger.LogInformation("Starting JSON export {ExportId}", exportId);
|
||||
|
||||
var existingState = await _stateManager.GetAsync(ExporterId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var builder = new JsonExportSnapshotBuilder(_options, _pathResolver);
|
||||
var existingState = await _stateManager.GetAsync(ExporterId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var cryptoHash = services.GetRequiredService<ICryptoHash>();
|
||||
var builder = new JsonExportSnapshotBuilder(_options, _pathResolver, cryptoHash);
|
||||
var canonicalAdvisories = await MaterializeCanonicalAdvisoriesAsync(cancellationToken).ConfigureAwait(false);
|
||||
var result = await builder.WriteAsync(canonicalAdvisories, exportedAt, exportId, cancellationToken).ConfigureAwait(false);
|
||||
result = await JsonMirrorBundleWriter.WriteAsync(result, _options, services, _timeProvider, _logger, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -50,7 +50,8 @@ internal static class JsonMirrorBundleWriter
|
||||
ArgumentNullException.ThrowIfNull(timeProvider);
|
||||
ArgumentNullException.ThrowIfNull(logger);
|
||||
|
||||
var mirrorOptions = options.Mirror ?? new JsonExportOptions.JsonMirrorOptions();
|
||||
var cryptoHash = services.GetRequiredService<ICryptoHash>();
|
||||
var mirrorOptions = options.Mirror ?? new JsonExportOptions.JsonMirrorOptions();
|
||||
if (!mirrorOptions.Enabled || mirrorOptions.Domains.Count == 0)
|
||||
{
|
||||
return result;
|
||||
@@ -123,7 +124,7 @@ internal static class JsonMirrorBundleWriter
|
||||
await WriteFileAsync(bundlePath, bundleBytes, exportedAtUtc, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var bundleRelativePath = ToRelativePath(result.ExportDirectory, bundlePath);
|
||||
var bundleDigest = ComputeDigest(bundleBytes);
|
||||
var bundleDigest = ComputeDigest(cryptoHash, bundleBytes);
|
||||
var bundleLength = (long)bundleBytes.LongLength;
|
||||
additionalFiles.Add(new JsonExportFile(bundleRelativePath, bundleLength, bundleDigest));
|
||||
|
||||
@@ -142,7 +143,7 @@ internal static class JsonMirrorBundleWriter
|
||||
await WriteFileAsync(signaturePath, signatureBytes, exportedAtUtc, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var signatureRelativePath = ToRelativePath(result.ExportDirectory, signaturePath);
|
||||
var signatureDigest = ComputeDigest(signatureBytes);
|
||||
var signatureDigest = ComputeDigest(cryptoHash, signatureBytes);
|
||||
var signatureLength = (long)signatureBytes.LongLength;
|
||||
additionalFiles.Add(new JsonExportFile(signatureRelativePath, signatureLength, signatureDigest));
|
||||
|
||||
@@ -170,7 +171,7 @@ internal static class JsonMirrorBundleWriter
|
||||
await WriteFileAsync(manifestPath, manifestBytes, exportedAtUtc, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var manifestRelativePath = ToRelativePath(result.ExportDirectory, manifestPath);
|
||||
var manifestDigest = ComputeDigest(manifestBytes);
|
||||
var manifestDigest = ComputeDigest(cryptoHash, manifestBytes);
|
||||
var manifestLength = (long)manifestBytes.LongLength;
|
||||
additionalFiles.Add(new JsonExportFile(manifestRelativePath, manifestLength, manifestDigest));
|
||||
|
||||
@@ -198,7 +199,7 @@ internal static class JsonMirrorBundleWriter
|
||||
await WriteFileAsync(indexPath, indexBytes, exportedAtUtc, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var indexRelativePath = ToRelativePath(result.ExportDirectory, indexPath);
|
||||
var indexDigest = ComputeDigest(indexBytes);
|
||||
var indexDigest = ComputeDigest(cryptoHash, indexBytes);
|
||||
var indexLength = (long)indexBytes.LongLength;
|
||||
additionalFiles.Add(new JsonExportFile(indexRelativePath, indexLength, indexDigest));
|
||||
|
||||
@@ -490,11 +491,11 @@ internal static class JsonMirrorBundleWriter
|
||||
return relative.Replace(Path.DirectorySeparatorChar, '/');
|
||||
}
|
||||
|
||||
private static string ComputeDigest(ReadOnlySpan<byte> payload)
|
||||
{
|
||||
var hash = SHA256.HashData(payload);
|
||||
return $"sha256:{Convert.ToHexString(hash).ToLowerInvariant()}";
|
||||
}
|
||||
private static string ComputeDigest(ICryptoHash hash, ReadOnlySpan<byte> payload)
|
||||
{
|
||||
var hex = hash.ComputeHashHex(payload, HashAlgorithms.Sha256);
|
||||
return $"sha256:{hex}";
|
||||
}
|
||||
|
||||
private static void TrySetDirectoryTimestamp(string directory, DateTime exportedAtUtc)
|
||||
{
|
||||
|
||||
@@ -436,14 +436,14 @@ public sealed class VulnListJsonExportPathResolver : IJsonExportPathResolver
|
||||
var invalid = Path.GetInvalidFileNameChars();
|
||||
Span<char> buffer = stackalloc char[name.Length];
|
||||
var count = 0;
|
||||
foreach (var ch in name)
|
||||
{
|
||||
if (ch == '/' || ch == '\\' || Array.IndexOf(invalid, ch) >= 0)
|
||||
{
|
||||
buffer[count++] = '_';
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var ch in name)
|
||||
{
|
||||
if (ch == '/' || ch == '\\' || ch == ':' || Array.IndexOf(invalid, ch) >= 0)
|
||||
{
|
||||
buffer[count++] = '_';
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[count++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user