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,34 +1,35 @@
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Cas;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.TestUtilities;
using Xunit;
namespace StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.Cas;
public sealed class LocalCasClientTests
{
[Fact]
public async Task VerifyWriteAsync_WritesProbeObject()
{
await using var temp = new TempDirectory();
var client = new LocalCasClient(new LocalCasOptions
{
RootDirectory = temp.Path,
Algorithm = "sha256"
});
var result = await client.VerifyWriteAsync(CancellationToken.None);
Assert.Equal("sha256", result.Algorithm);
Assert.True(File.Exists(result.Path));
var bytes = await File.ReadAllBytesAsync(result.Path);
Assert.Equal("stellaops-buildx-probe"u8.ToArray(), bytes);
var expectedDigest = Convert.ToHexString(SHA256.HashData(bytes)).ToLowerInvariant();
Assert.Equal(expectedDigest, result.Digest);
}
}
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Cryptography;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Cas;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.TestUtilities;
using Xunit;
namespace StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.Cas;
public sealed class LocalCasClientTests
{
[Fact]
public async Task VerifyWriteAsync_WritesProbeObject()
{
await using var temp = new TempDirectory();
var client = new LocalCasClient(new LocalCasOptions
{
RootDirectory = temp.Path,
Algorithm = "sha256"
}, CryptoHashFactory.CreateDefault());
var result = await client.VerifyWriteAsync(CancellationToken.None);
Assert.Equal("sha256", result.Algorithm);
Assert.True(File.Exists(result.Path));
var bytes = await File.ReadAllBytesAsync(result.Path);
Assert.Equal("stellaops-buildx-probe"u8.ToArray(), bytes);
var expectedDigest = Convert.ToHexString(SHA256.HashData(bytes)).ToLowerInvariant();
Assert.Equal(expectedDigest, result.Digest);
}
}

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using StellaOps.Cryptography;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Descriptor;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Manifest;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.TestUtilities;
@@ -36,15 +37,49 @@ public sealed class DescriptorCommandSurfaceTests
var manifestOutputPath = Path.Combine(temp.Path, "out", "surface-manifest.json");
var repoRoot = TestPathHelper.FindRepositoryRoot();
var manifestDirectory = Path.Combine(repoRoot, "src", "Scanner", "StellaOps.Scanner.Sbomer.BuildXPlugin");
var pluginAssembly = typeof(BuildxPluginManifest).Assembly.Location;
var normalizedRoot = repoRoot.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var rootFolder = Path.GetFileName(normalizedRoot);
var actualRepoRoot = string.Equals(rootFolder, "src", StringComparison.OrdinalIgnoreCase)
? Directory.GetParent(normalizedRoot)?.FullName ?? normalizedRoot
: normalizedRoot;
var sourceRoot = string.Equals(rootFolder, "src", StringComparison.OrdinalIgnoreCase)
? normalizedRoot
: Path.Combine(actualRepoRoot, "src");
var pluginProjectRoot = Path.Combine(sourceRoot, "Scanner", "StellaOps.Scanner.Sbomer.BuildXPlugin");
var manifestDirectoryCandidates = new[]
{
Path.Combine(actualRepoRoot, "plugins", "scanner", "buildx", "StellaOps.Scanner.Sbomer.BuildXPlugin"),
pluginProjectRoot
};
var manifestDirectory = manifestDirectoryCandidates.FirstOrDefault(Directory.Exists)
?? throw new DirectoryNotFoundException(
$"BuildX manifest directory not found under '{string.Join("', '", manifestDirectoryCandidates)}'.");
var testsOutputDirectory = Path.GetDirectoryName(typeof(DescriptorCommandSurfaceTests).Assembly.Location)
?? throw new InvalidOperationException("Unable to resolve test assembly directory.");
var targetFramework = new DirectoryInfo(testsOutputDirectory).Name;
var configuration = Directory.GetParent(testsOutputDirectory)?.Name ?? "Debug";
var pluginAssembly = Path.Combine(
pluginProjectRoot,
"bin",
configuration,
targetFramework,
"StellaOps.Scanner.Sbomer.BuildXPlugin.dll");
if (!File.Exists(pluginAssembly))
{
throw new FileNotFoundException($"BuildX plug-in assembly not found at '{pluginAssembly}'.");
}
var psi = new ProcessStartInfo("dotnet")
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
WorkingDirectory = repoRoot
WorkingDirectory = actualRepoRoot
};
psi.ArgumentList.Add(pluginAssembly);
@@ -82,7 +117,9 @@ public sealed class DescriptorCommandSurfaceTests
var descriptor = JsonSerializer.Deserialize<DescriptorDocument>(stdout, new JsonSerializerOptions(JsonSerializerDefaults.Web));
Assert.NotNull(descriptor);
Assert.Equal("stellaops.buildx.descriptor.v1", descriptor!.Schema);
Assert.Equal("sha256:d07d06ae82e1789a5b505731f3ec3add106e23a55395213c9a881c7e816c695c", descriptor.Artifact.Digest);
var hash = CryptoHashFactory.CreateDefault();
var expectedDigest = ComputeSha256Digest(hash, sbomPath);
Assert.Equal(expectedDigest, descriptor.Artifact.Digest);
Assert.Contains("surface manifest stored", stderr, StringComparison.OrdinalIgnoreCase);
Assert.True(File.Exists(manifestOutputPath));
@@ -109,14 +146,21 @@ public sealed class DescriptorCommandSurfaceTests
throw new InvalidOperationException($"Unsupported CAS URI {casUri}.");
}
var slashIndex = casUri.IndexOf(/, prefix.Length);
var slashIndex = casUri.IndexOf('/', prefix.Length);
if (slashIndex < 0)
{
throw new InvalidOperationException($"CAS URI {casUri} does not contain a bucket path.");
}
var relative = casUri[(slashIndex + 1)..];
var localPath = Path.Combine(casRoot, relative.Replace(/, Path.DirectorySeparatorChar));
var localPath = Path.Combine(casRoot, relative.Replace('/', Path.DirectorySeparatorChar));
return localPath;
}
private static string ComputeSha256Digest(ICryptoHash hash, string filePath)
{
var bytes = File.ReadAllBytes(filePath);
var digest = hash.ComputeHash(bytes, HashAlgorithms.Sha256);
return $"sha256:{Convert.ToHexString(digest).ToLowerInvariant()}";
}
}

View File

@@ -7,7 +7,8 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Time.Testing;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Descriptor;
using StellaOps.Cryptography;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Descriptor;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.TestUtilities;
using Xunit;
@@ -23,7 +24,7 @@ public sealed class DescriptorGeneratorTests
await File.WriteAllTextAsync(sbomPath, "{\"bomFormat\":\"CycloneDX\",\"specVersion\":\"1.5\"}");
var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 18, 12, 0, 0, TimeSpan.Zero));
var generator = new DescriptorGenerator(fakeTime);
var generator = CreateGenerator(fakeTime);
var request = new DescriptorRequest
{
@@ -72,7 +73,7 @@ public sealed class DescriptorGeneratorTests
await File.WriteAllTextAsync(sbomPath, "{\"bomFormat\":\"CycloneDX\",\"specVersion\":\"1.5\"}");
var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 18, 12, 0, 0, TimeSpan.Zero));
var generator = new DescriptorGenerator(fakeTime);
var generator = CreateGenerator(fakeTime);
var request = new DescriptorRequest
{
@@ -109,7 +110,7 @@ public sealed class DescriptorGeneratorTests
await File.WriteAllTextAsync(sbomPath, "{\"bomFormat\":\"CycloneDX\",\"specVersion\":\"1.5\"}");
var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 18, 12, 0, 0, TimeSpan.Zero));
var generator = new DescriptorGenerator(fakeTime);
var generator = CreateGenerator(fakeTime);
var baseline = new DescriptorRequest
{
@@ -133,7 +134,10 @@ public sealed class DescriptorGeneratorTests
Assert.NotEqual(baselineDocument.Provenance.ExpectedDsseSha256, variantDocument.Provenance.ExpectedDsseSha256);
}
private static string ComputeSha256File(string path)
private static DescriptorGenerator CreateGenerator(TimeProvider timeProvider)
=> new(timeProvider, CryptoHashFactory.CreateDefault());
private static string ComputeSha256File(string path)
{
using var stream = File.OpenRead(path);
var hash = SHA256.HashData(stream);

View File

@@ -7,8 +7,9 @@ using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Time.Testing;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Descriptor;
using Microsoft.Extensions.Time.Testing;
using StellaOps.Cryptography;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Descriptor;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.TestUtilities;
using Xunit;
@@ -48,7 +49,7 @@ public sealed class DescriptorGoldenTests
}.Validate();
var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 18, 12, 0, 0, TimeSpan.Zero));
var generator = new DescriptorGenerator(fakeTime);
var generator = CreateGenerator(fakeTime);
var document = await generator.CreateAsync(request, CancellationToken.None);
var actualJson = JsonSerializer.Serialize(document, SerializerOptions);
var normalizedJson = NormalizeDescriptorJson(actualJson, Path.GetFileName(sbomPath));
@@ -129,4 +130,6 @@ public sealed class DescriptorGoldenTests
break;
}
}
}
private static DescriptorGenerator CreateGenerator(TimeProvider timeProvider)
=> new(timeProvider, CryptoHashFactory.CreateDefault());
}

View File

@@ -3,6 +3,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Cryptography;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Surface;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.TestUtilities;
using Xunit;
@@ -42,7 +43,7 @@ public sealed class SurfaceManifestWriterTests
EntryTraceNdjsonPath: ndjsonPath,
ManifestOutputPath: manifestOutputPath);
var writer = new SurfaceManifestWriter(TimeProvider.System);
var writer = new SurfaceManifestWriter(TimeProvider.System, CryptoHashFactory.CreateDefault());
var result = await writer.WriteAsync(options, CancellationToken.None);
Assert.NotNull(result);
@@ -88,7 +89,7 @@ public sealed class SurfaceManifestWriterTests
EntryTraceNdjsonPath: null,
ManifestOutputPath: null);
var writer = new SurfaceManifestWriter(TimeProvider.System);
var writer = new SurfaceManifestWriter(TimeProvider.System, CryptoHashFactory.CreateDefault());
var result = await writer.WriteAsync(options, CancellationToken.None);
Assert.Null(result);
}