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

@@ -1,8 +1,8 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Cryptography;
namespace StellaOps.Scanner.Sbomer.BuildXPlugin.Surface;
@@ -67,11 +67,11 @@ internal static class SurfaceCasLayout
return $"cas://{normalizedBucket}/{normalizedKey}";
}
public static string ComputeDigest(ReadOnlySpan<byte> content)
public static string ComputeDigest(ICryptoHash hash, ReadOnlySpan<byte> content, string algorithmId = HashAlgorithms.Sha256)
{
Span<byte> hash = stackalloc byte[32];
SHA256.HashData(content, hash);
return $"{Sha256}:{Convert.ToHexString(hash).ToLowerInvariant()}";
var hex = hash.ComputeHashHex(content, algorithmId);
var prefix = algorithmId.Equals(HashAlgorithms.Sha256, StringComparison.OrdinalIgnoreCase) ? Sha256 : algorithmId.ToLowerInvariant();
return prefix + ":" + hex;
}
public static async Task<string> WriteBytesAsync(string rootDirectory, string objectKey, byte[] bytes, CancellationToken cancellationToken)

View File

@@ -6,6 +6,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Cryptography;
using StellaOps.Scanner.Surface.FS;
namespace StellaOps.Scanner.Sbomer.BuildXPlugin.Surface;
@@ -19,10 +20,12 @@ internal sealed class SurfaceManifestWriter
};
private readonly TimeProvider _timeProvider;
private readonly ICryptoHash _hash;
public SurfaceManifestWriter(TimeProvider timeProvider)
public SurfaceManifestWriter(TimeProvider timeProvider, ICryptoHash hash)
{
_timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
_hash = hash ?? throw new ArgumentNullException(nameof(hash));
}
public async Task<SurfaceManifestWriteResult?> WriteAsync(SurfaceOptions options, CancellationToken cancellationToken)
@@ -71,7 +74,7 @@ internal sealed class SurfaceManifestWriter
View: null,
CasKind: SurfaceCasKind.EntryTraceGraph,
FilePath: EnsurePath(options.EntryTraceGraphPath!, "EntryTrace graph path is required."));
artifacts.Add(await PersistArtifactAsync(descriptor, cacheRoot, bucket, rootPrefix, cancellationToken).ConfigureAwait(false));
artifacts.Add(await PersistArtifactAsync(descriptor, cacheRoot, bucket, rootPrefix, _hash, cancellationToken).ConfigureAwait(false));
}
if (!string.IsNullOrWhiteSpace(options.EntryTraceNdjsonPath))
@@ -83,7 +86,7 @@ internal sealed class SurfaceManifestWriter
View: null,
CasKind: SurfaceCasKind.EntryTraceNdjson,
FilePath: EnsurePath(options.EntryTraceNdjsonPath!, "EntryTrace NDJSON path is required."));
artifacts.Add(await PersistArtifactAsync(descriptor, cacheRoot, bucket, rootPrefix, cancellationToken).ConfigureAwait(false));
artifacts.Add(await PersistArtifactAsync(descriptor, cacheRoot, bucket, rootPrefix, _hash, cancellationToken).ConfigureAwait(false));
}
if (!string.IsNullOrWhiteSpace(options.LayerFragmentsPath))
@@ -95,7 +98,7 @@ internal sealed class SurfaceManifestWriter
View: "inventory",
CasKind: SurfaceCasKind.LayerFragments,
FilePath: EnsurePath(options.LayerFragmentsPath!, "Layer fragments path is required."));
artifacts.Add(await PersistArtifactAsync(descriptor, cacheRoot, bucket, rootPrefix, cancellationToken).ConfigureAwait(false));
artifacts.Add(await PersistArtifactAsync(descriptor, cacheRoot, bucket, rootPrefix, _hash, cancellationToken).ConfigureAwait(false));
}
if (artifacts.Count == 0)
@@ -127,7 +130,7 @@ internal sealed class SurfaceManifestWriter
};
var manifestBytes = JsonSerializer.SerializeToUtf8Bytes(manifestDocument, ManifestSerializerOptions);
var manifestDigest = SurfaceCasLayout.ComputeDigest(manifestBytes);
var manifestDigest = SurfaceCasLayout.ComputeDigest(_hash, manifestBytes);
var manifestKey = SurfaceCasLayout.BuildObjectKey(rootPrefix, SurfaceCasKind.Manifest, manifestDigest);
var manifestPath = await SurfaceCasLayout.WriteBytesAsync(cacheRoot, manifestKey, manifestBytes, cancellationToken).ConfigureAwait(false);
var manifestUri = SurfaceCasLayout.BuildCasUri(bucket, manifestKey);
@@ -157,6 +160,7 @@ internal sealed class SurfaceManifestWriter
string cacheRoot,
string bucket,
string rootPrefix,
ICryptoHash hash,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -167,7 +171,7 @@ internal sealed class SurfaceManifestWriter
}
var content = await File.ReadAllBytesAsync(descriptor.FilePath, cancellationToken).ConfigureAwait(false);
var digest = SurfaceCasLayout.ComputeDigest(content);
var digest = SurfaceCasLayout.ComputeDigest(hash, content);
var objectKey = SurfaceCasLayout.BuildObjectKey(rootPrefix, descriptor.CasKind, digest);
var filePath = await SurfaceCasLayout.WriteBytesAsync(cacheRoot, objectKey, content, cancellationToken).ConfigureAwait(false);
var uri = SurfaceCasLayout.BuildCasUri(bucket, objectKey);