up
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"advisoryKey": "CVE-2025-4242",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "cpe",
|
||||
"identifier": "cpe:2.3:a:conflict:package:1.0:*:*:*:*:*:*:*",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "1.4",
|
||||
"introducedVersion": "1.0",
|
||||
"lastAffectedVersion": "1.0",
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": ">=1.0 <1.4 ==1.0",
|
||||
"exactValue": "1.0.0",
|
||||
"fixed": "1.4.0",
|
||||
"fixedInclusive": false,
|
||||
"introduced": "1.0.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": "1.0.0",
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "exact"
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"versionStartIncluding": "1.0",
|
||||
"versionEndExcluding": "1.4",
|
||||
"version": "1.0"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "nvd",
|
||||
"kind": "cpe",
|
||||
"value": "https://services.nvd.nist.gov/rest/json/cve/2.0?cveId=CVE-2025-4242",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-03-04T02:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": ">=1.0 <1.4 ==1.0",
|
||||
"rangeKind": "cpe"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "exact",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": "1.0.0",
|
||||
"notes": "nvd:CVE-2025-4242"
|
||||
}
|
||||
],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "nvd",
|
||||
"kind": "cpe",
|
||||
"value": "https://services.nvd.nist.gov/rest/json/cve/2.0?cveId=CVE-2025-4242",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-03-04T02:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CVE-2025-4242"
|
||||
],
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 9.8,
|
||||
"baseSeverity": "critical",
|
||||
"provenance": {
|
||||
"source": "nvd",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-03-04T02:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
||||
"version": "3.1"
|
||||
}
|
||||
],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2025-03-03T09:45:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "nvd",
|
||||
"kind": "document",
|
||||
"value": "https://services.nvd.nist.gov/rest/json/cve/2.0?cveId=CVE-2025-4242",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-03-03T10:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "nvd",
|
||||
"kind": "mapping",
|
||||
"value": "CVE-2025-4242",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-03-04T02:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-03-01T10:15:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "weakness",
|
||||
"provenance": {
|
||||
"source": "nvd",
|
||||
"kind": "reference",
|
||||
"value": "https://cwe.mitre.org/data/definitions/269.html",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-03-04T02:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "CWE-269",
|
||||
"summary": null,
|
||||
"url": "https://cwe.mitre.org/data/definitions/269.html"
|
||||
},
|
||||
{
|
||||
"kind": "vendor advisory",
|
||||
"provenance": {
|
||||
"source": "nvd",
|
||||
"kind": "reference",
|
||||
"value": "https://nvd.nist.gov/vuln/detail/CVE-2025-4242",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-03-04T02:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "NVD",
|
||||
"summary": null,
|
||||
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-4242"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "NVD baseline summary for conflict-package allowing container escape.",
|
||||
"title": "CVE-2025-4242"
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"advisoryKey": "GHSA-credit-parity",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"CVE-2025-5555",
|
||||
"GHSA-credit-parity"
|
||||
],
|
||||
"credits": [
|
||||
{
|
||||
"displayName": "Bob Maintainer",
|
||||
"role": "remediation_developer",
|
||||
"contacts": [
|
||||
"https://github.com/acme/bob-maintainer"
|
||||
],
|
||||
"provenance": {
|
||||
"source": "ghsa",
|
||||
"kind": "credit",
|
||||
"value": "ghsa:bob-maintainer",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"credits[]"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"displayName": "Alice Researcher",
|
||||
"role": "reporter",
|
||||
"contacts": [
|
||||
"mailto:alice.researcher@example.com"
|
||||
],
|
||||
"provenance": {
|
||||
"source": "ghsa",
|
||||
"kind": "credit",
|
||||
"value": "ghsa:alice-researcher",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"credits[]"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2025-10-10T12:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ghsa",
|
||||
"kind": "document",
|
||||
"value": "security/advisories/GHSA-credit-parity",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "ghsa",
|
||||
"kind": "mapping",
|
||||
"value": "GHSA-credit-parity",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-09T18:30:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "patch",
|
||||
"provenance": {
|
||||
"source": "ghsa",
|
||||
"kind": "reference",
|
||||
"value": "https://example.com/ghsa/patch",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://example.com/ghsa/patch"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "ghsa",
|
||||
"kind": "reference",
|
||||
"value": "https://github.com/advisories/GHSA-credit-parity",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://github.com/advisories/GHSA-credit-parity"
|
||||
}
|
||||
],
|
||||
"severity": "medium",
|
||||
"summary": "Credit parity regression fixture",
|
||||
"title": "Credit parity regression fixture"
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"advisoryKey": "CVE-2025-5555",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"CVE-2025-5555",
|
||||
"GHSA-credit-parity"
|
||||
],
|
||||
"credits": [
|
||||
{
|
||||
"displayName": "Bob Maintainer",
|
||||
"role": "remediation_developer",
|
||||
"contacts": [
|
||||
"https://github.com/acme/bob-maintainer"
|
||||
],
|
||||
"provenance": {
|
||||
"source": "nvd",
|
||||
"kind": "credit",
|
||||
"value": "nvd:bob-maintainer",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"credits[]"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"displayName": "Alice Researcher",
|
||||
"role": "reporter",
|
||||
"contacts": [
|
||||
"mailto:alice.researcher@example.com"
|
||||
],
|
||||
"provenance": {
|
||||
"source": "nvd",
|
||||
"kind": "credit",
|
||||
"value": "nvd:alice-researcher",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"credits[]"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2025-10-10T12:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "nvd",
|
||||
"kind": "document",
|
||||
"value": "https://services.nvd.nist.gov/vuln/detail/CVE-2025-5555",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "nvd",
|
||||
"kind": "mapping",
|
||||
"value": "CVE-2025-5555",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-09T18:30:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "report",
|
||||
"provenance": {
|
||||
"source": "nvd",
|
||||
"kind": "reference",
|
||||
"value": "https://example.com/nvd/reference",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://example.com/nvd/reference"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "nvd",
|
||||
"kind": "reference",
|
||||
"value": "https://services.nvd.nist.gov/vuln/detail/CVE-2025-5555",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://services.nvd.nist.gov/vuln/detail/CVE-2025-5555"
|
||||
}
|
||||
],
|
||||
"severity": "medium",
|
||||
"summary": "Credit parity regression fixture",
|
||||
"title": "Credit parity regression fixture"
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"advisoryKey": "GHSA-credit-parity",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"CVE-2025-5555",
|
||||
"GHSA-credit-parity"
|
||||
],
|
||||
"credits": [
|
||||
{
|
||||
"displayName": "Bob Maintainer",
|
||||
"role": "remediation_developer",
|
||||
"contacts": [
|
||||
"https://github.com/acme/bob-maintainer"
|
||||
],
|
||||
"provenance": {
|
||||
"source": "osv",
|
||||
"kind": "credit",
|
||||
"value": "osv:bob-maintainer",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"credits[]"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"displayName": "Alice Researcher",
|
||||
"role": "reporter",
|
||||
"contacts": [
|
||||
"mailto:alice.researcher@example.com"
|
||||
],
|
||||
"provenance": {
|
||||
"source": "osv",
|
||||
"kind": "credit",
|
||||
"value": "osv:alice-researcher",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"credits[]"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2025-10-10T12:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "osv",
|
||||
"kind": "document",
|
||||
"value": "https://osv.dev/vulnerability/GHSA-credit-parity",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "osv",
|
||||
"kind": "mapping",
|
||||
"value": "GHSA-credit-parity",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-09T18:30:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "osv",
|
||||
"kind": "reference",
|
||||
"value": "https://github.com/advisories/GHSA-credit-parity",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://github.com/advisories/GHSA-credit-parity"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "osv",
|
||||
"kind": "reference",
|
||||
"value": "https://osv.dev/vulnerability/GHSA-credit-parity",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-10T15:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://osv.dev/vulnerability/GHSA-credit-parity"
|
||||
}
|
||||
],
|
||||
"severity": "medium",
|
||||
"summary": "Credit parity regression fixture",
|
||||
"title": "Credit parity regression fixture"
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
using System.Text.Json;
|
||||
using StellaOps.Feedser.Models;
|
||||
using StellaOps.Feedser.Source.Nvd.Internal;
|
||||
using StellaOps.Feedser.Storage.Mongo.Documents;
|
||||
|
||||
namespace StellaOps.Feedser.Source.Nvd.Tests;
|
||||
|
||||
public sealed class NvdConflictFixtureTests
|
||||
{
|
||||
[Fact]
|
||||
public void ConflictFixture_MatchesSnapshot()
|
||||
{
|
||||
const string payload = """
|
||||
{
|
||||
"vulnerabilities": [
|
||||
{
|
||||
"cve": {
|
||||
"id": "CVE-2025-4242",
|
||||
"published": "2025-03-01T10:15:00Z",
|
||||
"lastModified": "2025-03-03T09:45:00Z",
|
||||
"descriptions": [
|
||||
{ "lang": "en", "value": "NVD baseline summary for conflict-package allowing container escape." }
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-4242",
|
||||
"source": "NVD",
|
||||
"tags": ["Vendor Advisory"]
|
||||
}
|
||||
],
|
||||
"weaknesses": [
|
||||
{
|
||||
"description": [
|
||||
{ "lang": "en", "value": "CWE-269" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"cvssMetricV31": [
|
||||
{
|
||||
"cvssData": {
|
||||
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
||||
"baseScore": 9.8,
|
||||
"baseSeverity": "CRITICAL"
|
||||
},
|
||||
"exploitabilityScore": 3.9,
|
||||
"impactScore": 5.9
|
||||
}
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"nodes": [
|
||||
{
|
||||
"cpeMatch": [
|
||||
{
|
||||
"criteria": "cpe:2.3:a:conflict:package:1.0:*:*:*:*:*:*:*",
|
||||
"vulnerable": true,
|
||||
"versionStartIncluding": "1.0",
|
||||
"versionEndExcluding": "1.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
|
||||
using var document = JsonDocument.Parse(payload);
|
||||
|
||||
var sourceDocument = new DocumentRecord(
|
||||
Id: Guid.Parse("1a6a0700-2dd0-4f69-bb37-64ca77e51c91"),
|
||||
SourceName: NvdConnectorPlugin.SourceName,
|
||||
Uri: "https://services.nvd.nist.gov/rest/json/cve/2.0?cveId=CVE-2025-4242",
|
||||
FetchedAt: new DateTimeOffset(2025, 3, 3, 10, 0, 0, TimeSpan.Zero),
|
||||
Sha256: "sha256-nvd-conflict-fixture",
|
||||
Status: "completed",
|
||||
ContentType: "application/json",
|
||||
Headers: null,
|
||||
Metadata: null,
|
||||
Etag: "\"etag-nvd-conflict\"",
|
||||
LastModified: new DateTimeOffset(2025, 3, 3, 9, 45, 0, TimeSpan.Zero),
|
||||
GridFsId: null);
|
||||
|
||||
var advisories = NvdMapper.Map(document, sourceDocument, new DateTimeOffset(2025, 3, 4, 2, 0, 0, TimeSpan.Zero));
|
||||
var advisory = Assert.Single(advisories);
|
||||
|
||||
var snapshot = SnapshotSerializer.ToSnapshot(advisory).Replace("\r\n", "\n").TrimEnd();
|
||||
var expectedPath = Path.Combine(AppContext.BaseDirectory, "Nvd", "Fixtures", "conflict-nvd.canonical.json");
|
||||
var expected = File.ReadAllText(expectedPath).Replace("\r\n", "\n").TrimEnd();
|
||||
|
||||
if (!string.Equals(expected, snapshot, StringComparison.Ordinal))
|
||||
{
|
||||
var actualPath = Path.Combine(AppContext.BaseDirectory, "Nvd", "Fixtures", "conflict-nvd.canonical.actual.json");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(actualPath)!);
|
||||
File.WriteAllText(actualPath, snapshot);
|
||||
}
|
||||
|
||||
Assert.Equal(expected, snapshot);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Feedser.Core;
|
||||
using StellaOps.Feedser.Exporter.Json;
|
||||
using StellaOps.Feedser.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Feedser.Source.Nvd.Tests.Nvd;
|
||||
|
||||
public sealed class NvdMergeExportParityTests
|
||||
{
|
||||
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web);
|
||||
|
||||
[Fact]
|
||||
public async Task CanonicalMerge_PreservesCreditsAndReferences_ExporterMaintainsParity()
|
||||
{
|
||||
var ghsa = LoadFixture("credit-parity.ghsa.json");
|
||||
var osv = LoadFixture("credit-parity.osv.json");
|
||||
var nvd = LoadFixture("credit-parity.nvd.json");
|
||||
|
||||
var merger = new CanonicalMerger();
|
||||
var result = merger.Merge("CVE-2025-5555", ghsa, nvd, osv);
|
||||
var merged = result.Advisory;
|
||||
|
||||
Assert.NotNull(merged);
|
||||
var creditKeys = merged!.Credits
|
||||
.Select(static credit => $"{credit.Role}|{credit.DisplayName}|{string.Join("|", credit.Contacts.OrderBy(static c => c, StringComparer.Ordinal))}")
|
||||
.ToHashSet(StringComparer.Ordinal);
|
||||
|
||||
Assert.Equal(2, creditKeys.Count);
|
||||
Assert.Contains("reporter|Alice Researcher|mailto:alice.researcher@example.com", creditKeys);
|
||||
Assert.Contains("remediation_developer|Bob Maintainer|https://github.com/acme/bob-maintainer", creditKeys);
|
||||
|
||||
var referenceUrls = merged.References.Select(static reference => reference.Url).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
Assert.Equal(5, referenceUrls.Count);
|
||||
Assert.Contains($"https://github.com/advisories/GHSA-credit-parity", referenceUrls);
|
||||
Assert.Contains("https://example.com/ghsa/patch", referenceUrls);
|
||||
Assert.Contains($"https://osv.dev/vulnerability/GHSA-credit-parity", referenceUrls);
|
||||
Assert.Contains($"https://services.nvd.nist.gov/vuln/detail/CVE-2025-5555", referenceUrls);
|
||||
Assert.Contains("https://example.com/nvd/reference", referenceUrls);
|
||||
|
||||
using var tempDirectory = new TempDirectory();
|
||||
var options = new JsonExportOptions { OutputRoot = tempDirectory.Path };
|
||||
var builder = new JsonExportSnapshotBuilder(options, new VulnListJsonExportPathResolver());
|
||||
var exportResult = await builder.WriteAsync(new[] { merged }, new DateTimeOffset(2025, 10, 11, 0, 0, 0, TimeSpan.Zero));
|
||||
|
||||
Assert.Single(exportResult.Files);
|
||||
var exportFile = exportResult.Files[0];
|
||||
var exportPath = Path.Combine(exportResult.ExportDirectory, exportFile.RelativePath.Replace('/', Path.DirectorySeparatorChar));
|
||||
Assert.True(File.Exists(exportPath));
|
||||
|
||||
var exported = JsonSerializer.Deserialize<Advisory>(await File.ReadAllTextAsync(exportPath), SerializerOptions);
|
||||
Assert.NotNull(exported);
|
||||
|
||||
var exportedCredits = exported!.Credits
|
||||
.Select(static credit => $"{credit.Role}|{credit.DisplayName}|{string.Join("|", credit.Contacts.OrderBy(static c => c, StringComparer.Ordinal))}")
|
||||
.ToHashSet(StringComparer.Ordinal);
|
||||
Assert.Equal(creditKeys, exportedCredits);
|
||||
|
||||
var exportedReferences = exported.References.Select(static reference => reference.Url).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
Assert.Equal(referenceUrls, exportedReferences);
|
||||
}
|
||||
|
||||
private static Advisory LoadFixture(string fileName)
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "Nvd", "Fixtures", fileName);
|
||||
return JsonSerializer.Deserialize<Advisory>(File.ReadAllText(path), SerializerOptions)
|
||||
?? throw new InvalidOperationException($"Failed to deserialize fixture '{fileName}'.");
|
||||
}
|
||||
|
||||
private sealed class TempDirectory : IDisposable
|
||||
{
|
||||
public TempDirectory()
|
||||
{
|
||||
Path = Directory.CreateTempSubdirectory("nvd-merge-export").FullName;
|
||||
}
|
||||
|
||||
public string Path { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path))
|
||||
{
|
||||
Directory.Delete(Path, recursive: true);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// best effort cleanup
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user