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,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user