- Implemented comprehensive tests for verdict artifact generation to ensure deterministic outputs across various scenarios, including identical inputs, parallel execution, and change ordering. - Created helper methods for generating sample verdict inputs and computing canonical hashes. - Added tests to validate the stability of canonical hashes, proof spine ordering, and summary statistics. - Introduced a new PowerShell script to update SHA256 sums for files, ensuring accurate hash generation and file integrity checks.
519 lines
21 KiB
C#
519 lines
21 KiB
C#
// -----------------------------------------------------------------------------
|
|
// MergeExportSnapshotTests.cs
|
|
// Sprint: SPRINT_5100_0009_0002
|
|
// Task: CONCELIER-5100-011
|
|
// Description: Snapshot tests for merged normalized DB export (canonical JSON)
|
|
// -----------------------------------------------------------------------------
|
|
|
|
using FluentAssertions;
|
|
using Microsoft.Extensions.Time.Testing;
|
|
using StellaOps.Canonical.Json;
|
|
using StellaOps.Concelier.Merge.Services;
|
|
using StellaOps.Concelier.Models;
|
|
using Xunit;
|
|
|
|
namespace StellaOps.Concelier.Merge.Tests;
|
|
|
|
/// <summary>
|
|
/// Snapshot tests for merged advisory exports.
|
|
/// Verifies that merged advisories produce deterministic canonical JSON output.
|
|
/// </summary>
|
|
public sealed class MergeExportSnapshotTests
|
|
{
|
|
private static readonly DateTimeOffset FixedTime = new(2025, 1, 15, 12, 0, 0, TimeSpan.Zero);
|
|
|
|
#region Canonical JSON Snapshot Tests
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void MergedAdvisory_ProducesCanonicalJsonSnapshot()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (vendor, nvd) = CreateVendorAndNvdAdvisories();
|
|
|
|
// Act
|
|
var merged = merger.Merge(new[] { vendor, nvd }).Advisory;
|
|
var canonicalJson = CanonJson.Serialize(merged);
|
|
|
|
// Assert - verify canonical JSON structure (not exact match due to merge provenance timestamp)
|
|
canonicalJson.Should().Contain("\"advisoryKey\":\"CVE-2025-1000\"");
|
|
canonicalJson.Should().Contain("\"severity\":\"high\""); // Vendor takes precedence
|
|
canonicalJson.Should().Contain("\"exploitKnown\":false");
|
|
canonicalJson.Should().Contain("\"RHSA-2025:1000\""); // Vendor alias preserved
|
|
canonicalJson.Should().Contain("\"CVE-2025-1000\""); // CVE alias preserved
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void MergedAdvisory_CanonicalJsonIsDeterministic()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (vendor, nvd) = CreateVendorAndNvdAdvisories();
|
|
|
|
// Act - merge and serialize multiple times
|
|
var results = new List<string>();
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
timeProvider.SetUtcNow(FixedTime); // Reset for determinism
|
|
var merged = merger.Merge(new[] { vendor, nvd }).Advisory;
|
|
results.Add(CanonJson.Serialize(merged));
|
|
}
|
|
|
|
// Assert
|
|
results.Distinct().Should().HaveCount(1,
|
|
"canonical JSON should be identical across multiple merge runs");
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void MergedAdvisory_OrderedFieldsInCanonicalJson()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (vendor, nvd) = CreateVendorAndNvdAdvisories();
|
|
|
|
// Act
|
|
var merged = merger.Merge(new[] { vendor, nvd }).Advisory;
|
|
var canonicalJson = CanonJson.Serialize(merged);
|
|
|
|
// Assert - canonical JSON should have fields in deterministic order
|
|
var advisoryKeyIndex = canonicalJson.IndexOf("\"advisoryKey\"", StringComparison.Ordinal);
|
|
var titleIndex = canonicalJson.IndexOf("\"title\"", StringComparison.Ordinal);
|
|
var severityIndex = canonicalJson.IndexOf("\"severity\"", StringComparison.Ordinal);
|
|
|
|
advisoryKeyIndex.Should().BeGreaterOrEqualTo(0);
|
|
titleIndex.Should().BeGreaterOrEqualTo(0);
|
|
severityIndex.Should().BeGreaterOrEqualTo(0);
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void MergedAdvisory_AliasesOrderedDeterministically()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (a, b, c) = CreateThreeAdvisories();
|
|
|
|
// Act
|
|
var merged = merger.Merge(new[] { a, b, c }).Advisory;
|
|
|
|
// Assert - aliases should be collected from all sources
|
|
merged.Aliases.Should().Contain("CVE-2025-3000");
|
|
merged.Aliases.Should().Contain("RHSA-2025:3000");
|
|
merged.Aliases.Should().Contain("GHSA-3333-4444-5555");
|
|
merged.Aliases.Should().Contain("OSV-2025-3000");
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void MergedAdvisory_ProvenanceOrderedBySource()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (a, b, c) = CreateThreeAdvisories();
|
|
|
|
// Act
|
|
var merged = merger.Merge(new[] { a, b, c }).Advisory;
|
|
var canonicalJson = CanonJson.Serialize(merged);
|
|
|
|
// Assert - provenance should include all sources
|
|
merged.Provenance.Should().HaveCountGreaterThan(3); // Original + merge provenance
|
|
merged.Provenance.Should().Contain(p => p.Source == "redhat");
|
|
merged.Provenance.Should().Contain(p => p.Source == "ghsa");
|
|
merged.Provenance.Should().Contain(p => p.Source == "osv");
|
|
merged.Provenance.Should().Contain(p => p.Source == "merge");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Snapshot Serialization Tests
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void SnapshotSerializer_MergedAdvisory_ProducesDeterministicOutput()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (vendor, nvd) = CreateVendorAndNvdAdvisories();
|
|
var merged = merger.Merge(new[] { vendor, nvd }).Advisory;
|
|
|
|
// Act
|
|
var results = new List<string>();
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
results.Add(SnapshotSerializer.ToSnapshot(merged));
|
|
}
|
|
|
|
// Assert
|
|
results.Distinct().Should().HaveCount(1,
|
|
"SnapshotSerializer should produce identical output");
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void SnapshotSerializer_MergedAdvisory_ContainsExpectedFields()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (vendor, nvd) = CreateAdvisoriesWithCvss();
|
|
var merged = merger.Merge(new[] { vendor, nvd }).Advisory;
|
|
|
|
// Act
|
|
var snapshot = SnapshotSerializer.ToSnapshot(merged);
|
|
|
|
// Assert
|
|
snapshot.Should().Contain("CVE-2025-1000");
|
|
snapshot.Should().Contain("CVSS:3.1"); // CVSS vector preserved
|
|
snapshot.Should().Contain("redhat"); // Source provenance
|
|
snapshot.Should().Contain("nvd"); // Source provenance
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void SnapshotSerializer_MergedAdvisory_PreservesAffectedPackages()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (vendor, nvd) = CreateVendorAndNvdAdvisories();
|
|
var merged = merger.Merge(new[] { vendor, nvd }).Advisory;
|
|
|
|
// Act
|
|
var snapshot = SnapshotSerializer.ToSnapshot(merged);
|
|
|
|
// Assert
|
|
snapshot.Should().Contain("affectedPackages");
|
|
snapshot.Should().Contain("cpe:2.3:o:redhat:enterprise_linux:9");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Export Result Verification
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void MergedAdvisory_ExploitKnownFromKev_PreservedInSnapshot()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var baseAdvisory = CreateNvdAdvisory();
|
|
var kevAdvisory = CreateKevAdvisory();
|
|
|
|
// Act
|
|
var merged = merger.Merge(new[] { baseAdvisory, kevAdvisory }).Advisory;
|
|
var snapshot = SnapshotSerializer.ToSnapshot(merged);
|
|
|
|
// Assert
|
|
merged.ExploitKnown.Should().BeTrue("KEV should set exploitKnown to true");
|
|
snapshot.Should().Contain("\"exploitKnown\":true");
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void MergedAdvisory_CreditsFromMultipleSources_PreservedInSnapshot()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (ghsa, osv) = CreateAdvisoriesWithCredits();
|
|
|
|
// Act
|
|
var merged = merger.Merge(new[] { ghsa, osv }).Advisory;
|
|
var snapshot = SnapshotSerializer.ToSnapshot(merged);
|
|
|
|
// Assert
|
|
merged.Credits.Should().HaveCountGreaterThan(2, "credits from multiple sources should be merged");
|
|
snapshot.Should().Contain("credits");
|
|
snapshot.Should().Contain("researcher-a");
|
|
snapshot.Should().Contain("researcher-b");
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Lane", "Unit")]
|
|
[Trait("Category", "Snapshot")]
|
|
public void MergedAdvisory_ReferencesFromMultipleSources_PreservedInSnapshot()
|
|
{
|
|
// Arrange
|
|
var timeProvider = new FakeTimeProvider(FixedTime);
|
|
var merger = new AdvisoryPrecedenceMerger(new AffectedPackagePrecedenceResolver(), timeProvider);
|
|
|
|
var (ghsa, osv) = CreateAdvisoriesWithReferences();
|
|
|
|
// Act
|
|
var merged = merger.Merge(new[] { ghsa, osv }).Advisory;
|
|
var snapshot = SnapshotSerializer.ToSnapshot(merged);
|
|
|
|
// Assert
|
|
merged.References.Should().HaveCountGreaterThan(2, "references from multiple sources should be merged");
|
|
snapshot.Should().Contain("references");
|
|
snapshot.Should().Contain("github.com");
|
|
snapshot.Should().Contain("osv.dev");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helper Methods
|
|
|
|
private static (Advisory Vendor, Advisory Nvd) CreateVendorAndNvdAdvisories()
|
|
{
|
|
var vendorProvenance = new AdvisoryProvenance("redhat", "advisory", "RHSA-2025:1000", FixedTime);
|
|
var vendor = new Advisory(
|
|
"CVE-2025-1000",
|
|
"Red Hat Security Advisory",
|
|
"Vendor-confirmed impact",
|
|
"en",
|
|
FixedTime,
|
|
FixedTime,
|
|
"high",
|
|
exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-1000", "RHSA-2025:1000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: new[]
|
|
{
|
|
new AffectedPackage(
|
|
AffectedPackageTypes.Cpe,
|
|
"cpe:2.3:o:redhat:enterprise_linux:9:*:*:*:*:*:*:*",
|
|
null,
|
|
Array.Empty<AffectedVersionRange>(),
|
|
new[] { new AffectedPackageStatus("known_affected", vendorProvenance) },
|
|
new[] { vendorProvenance })
|
|
},
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { vendorProvenance });
|
|
|
|
var nvdProvenance = new AdvisoryProvenance("nvd", "document", "https://nvd.nist.gov", FixedTime);
|
|
var nvd = new Advisory(
|
|
"CVE-2025-1000",
|
|
"CVE-2025-1000",
|
|
"NVD summary",
|
|
"en",
|
|
FixedTime.AddDays(-1),
|
|
FixedTime,
|
|
"medium",
|
|
exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-1000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: new[]
|
|
{
|
|
new AffectedPackage(
|
|
AffectedPackageTypes.Cpe,
|
|
"cpe:2.3:o:redhat:enterprise_linux:9:*:*:*:*:*:*:*",
|
|
null,
|
|
new[] { new AffectedVersionRange("cpe", null, null, null, "<=9.0", nvdProvenance) },
|
|
Array.Empty<AffectedPackageStatus>(),
|
|
new[] { nvdProvenance })
|
|
},
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { nvdProvenance });
|
|
|
|
return (vendor, nvd);
|
|
}
|
|
|
|
private static (Advisory A, Advisory B, Advisory C) CreateThreeAdvisories()
|
|
{
|
|
var redhatProvenance = new AdvisoryProvenance("redhat", "advisory", "RHSA-2025:3000", FixedTime);
|
|
var redhat = new Advisory(
|
|
"CVE-2025-3000", "Red Hat Advisory", "Vendor summary", "en",
|
|
FixedTime, FixedTime, "high", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-3000", "RHSA-2025:3000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { redhatProvenance });
|
|
|
|
var ghsaProvenance = new AdvisoryProvenance("ghsa", "document", "https://github.com/advisories/GHSA-3333-4444-5555", FixedTime);
|
|
var ghsa = new Advisory(
|
|
"CVE-2025-3000", "GHSA Advisory", "GHSA summary", "en",
|
|
FixedTime.AddHours(1), FixedTime.AddHours(1), "high", exploitKnown: true,
|
|
aliases: new[] { "CVE-2025-3000", "GHSA-3333-4444-5555" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { ghsaProvenance });
|
|
|
|
var osvProvenance = new AdvisoryProvenance("osv", "document", "https://osv.dev/vulnerability/OSV-2025-3000", FixedTime);
|
|
var osv = new Advisory(
|
|
"CVE-2025-3000", "OSV Advisory", "OSV summary", "en",
|
|
FixedTime.AddHours(2), FixedTime.AddHours(2), "medium", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-3000", "OSV-2025-3000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { osvProvenance });
|
|
|
|
return (redhat, ghsa, osv);
|
|
}
|
|
|
|
private static (Advisory Vendor, Advisory Nvd) CreateAdvisoriesWithCvss()
|
|
{
|
|
var vendorProvenance = new AdvisoryProvenance("redhat", "advisory", "RHSA-2025:1000", FixedTime);
|
|
var vendor = new Advisory(
|
|
"CVE-2025-1000", "Red Hat Advisory", "Summary", "en",
|
|
FixedTime, FixedTime, "critical", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-1000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: new[]
|
|
{
|
|
new CvssMetric("3.1", "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", 9.8, "critical",
|
|
new AdvisoryProvenance("redhat", "cvss", "RHSA-2025:1000", FixedTime))
|
|
},
|
|
provenance: new[] { vendorProvenance });
|
|
|
|
var nvdProvenance = new AdvisoryProvenance("nvd", "document", "https://nvd.nist.gov", FixedTime);
|
|
var nvd = new Advisory(
|
|
"CVE-2025-1000", "CVE-2025-1000", "Summary", "en",
|
|
FixedTime, FixedTime, "high", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-1000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: new[]
|
|
{
|
|
new CvssMetric("3.1", "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N", 7.3, "high",
|
|
new AdvisoryProvenance("nvd", "cvss", "CVE-2025-1000", FixedTime))
|
|
},
|
|
provenance: new[] { nvdProvenance });
|
|
|
|
return (vendor, nvd);
|
|
}
|
|
|
|
private static Advisory CreateNvdAdvisory()
|
|
{
|
|
var nvdProvenance = new AdvisoryProvenance("nvd", "document", "https://nvd.nist.gov", FixedTime);
|
|
return new Advisory(
|
|
"CVE-2025-2000", "CVE-2025-2000", "NVD summary", "en",
|
|
FixedTime, FixedTime, "medium", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-2000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { nvdProvenance });
|
|
}
|
|
|
|
private static Advisory CreateKevAdvisory()
|
|
{
|
|
var kevProvenance = new AdvisoryProvenance("kev", "catalog", "CVE-2025-2000", FixedTime);
|
|
return new Advisory(
|
|
"CVE-2025-2000", "Known Exploited Vulnerability", null, null,
|
|
null, null, null, exploitKnown: true,
|
|
aliases: new[] { "CVE-2025-2000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { kevProvenance });
|
|
}
|
|
|
|
private static (Advisory Ghsa, Advisory Osv) CreateAdvisoriesWithCredits()
|
|
{
|
|
var ghsaProvenance = new AdvisoryProvenance("ghsa", "document", "https://github.com/advisories", FixedTime);
|
|
var ghsa = new Advisory(
|
|
"CVE-2025-2000", "GHSA Advisory", "Summary", "en",
|
|
FixedTime, FixedTime, "high", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-2000" },
|
|
credits: new[]
|
|
{
|
|
new AdvisoryCredit("researcher-a", "reporter", new[] { "https://example.com/a" },
|
|
new AdvisoryProvenance("ghsa", "credit", "researcher-a", FixedTime)),
|
|
new AdvisoryCredit("maintainer", "remediation_developer", new[] { "https://example.com/m" },
|
|
new AdvisoryProvenance("ghsa", "credit", "maintainer", FixedTime))
|
|
},
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { ghsaProvenance });
|
|
|
|
var osvProvenance = new AdvisoryProvenance("osv", "document", "https://osv.dev", FixedTime);
|
|
var osv = new Advisory(
|
|
"CVE-2025-2000", "OSV Advisory", "Summary", "en",
|
|
FixedTime, FixedTime, "high", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-2000" },
|
|
credits: new[]
|
|
{
|
|
new AdvisoryCredit("researcher-b", "reporter", new[] { "https://example.com/b" },
|
|
new AdvisoryProvenance("osv", "credit", "researcher-b", FixedTime))
|
|
},
|
|
references: Array.Empty<AdvisoryReference>(),
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { osvProvenance });
|
|
|
|
return (ghsa, osv);
|
|
}
|
|
|
|
private static (Advisory Ghsa, Advisory Osv) CreateAdvisoriesWithReferences()
|
|
{
|
|
var ghsaProvenance = new AdvisoryProvenance("ghsa", "document", "https://github.com/advisories", FixedTime);
|
|
var ghsa = new Advisory(
|
|
"CVE-2025-2000", "GHSA Advisory", "Summary", "en",
|
|
FixedTime, FixedTime, "high", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-2000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: new[]
|
|
{
|
|
new AdvisoryReference("https://github.com/org/repo/security/advisories/GHSA-xxxx", "advisory", "ghsa", "GitHub advisory", ghsaProvenance),
|
|
new AdvisoryReference("https://github.com/org/repo/pull/123", "fix", "ghsa", "Fix PR", ghsaProvenance)
|
|
},
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { ghsaProvenance });
|
|
|
|
var osvProvenance = new AdvisoryProvenance("osv", "document", "https://osv.dev", FixedTime);
|
|
var osv = new Advisory(
|
|
"CVE-2025-2000", "OSV Advisory", "Summary", "en",
|
|
FixedTime, FixedTime, "high", exploitKnown: false,
|
|
aliases: new[] { "CVE-2025-2000" },
|
|
credits: Array.Empty<AdvisoryCredit>(),
|
|
references: new[]
|
|
{
|
|
new AdvisoryReference("https://osv.dev/vulnerability/CVE-2025-2000", "advisory", "osv", "OSV entry", osvProvenance),
|
|
new AdvisoryReference("https://example.com/blog/vuln-disclosure", "article", "osv", "Blog post", osvProvenance)
|
|
},
|
|
affectedPackages: Array.Empty<AffectedPackage>(),
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: new[] { osvProvenance });
|
|
|
|
return (ghsa, osv);
|
|
}
|
|
|
|
#endregion
|
|
}
|