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:
@@ -0,0 +1,207 @@
|
||||
[
|
||||
{
|
||||
"advisoryKey": "acsc/multi/https-origin-example-advisories-info-bulletin",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"ACSC-2025-011",
|
||||
"Bulletin",
|
||||
"https://origin.example/advisories/info-bulletin"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/multi/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "multi",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/info-bulletin",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T02:30:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/info-bulletin",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "multi",
|
||||
"summary": "Information bulletin",
|
||||
"url": "https://origin.example/advisories/info-bulletin"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Serial number: ACSC-2025-011\n\nAdvisory type: Bulletin\n\nGeneral guidance bulletin.",
|
||||
"title": "Information bulletin"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "acsc/multi/https-origin-example-advisories-router-critical",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ExampleCo Router X",
|
||||
"platform": null,
|
||||
"versionRanges": [],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "affected",
|
||||
"value": "ExampleCo Router X",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ExampleCo Router Y",
|
||||
"platform": null,
|
||||
"versionRanges": [],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "affected",
|
||||
"value": "ExampleCo Router Y",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"ACSC-2025-010",
|
||||
"CVE-2025-0001",
|
||||
"https://origin.example/advisories/router-critical"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/multi/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "multi",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/router-critical",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T04:45:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/router-critical",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "multi",
|
||||
"summary": "Critical router vulnerability",
|
||||
"url": "https://origin.example/advisories/router-critical"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example/router/patch",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": "vendor patch",
|
||||
"url": "https://vendor.example/router/patch"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "Serial number: ACSC-2025-010\n\nSeverity: Critical\n\nSystems affected: ExampleCo Router X, ExampleCo Router Y\n\nRemote code execution on ExampleCo routers. See vendor patch.\n\nCVE references: CVE-2025-0001",
|
||||
"title": "Critical router vulnerability"
|
||||
}
|
||||
]
|
||||
@@ -1,201 +1,207 @@
|
||||
[
|
||||
{
|
||||
"advisoryKey": "acsc/multi/https-origin-example-advisories-info-bulletin",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"ACSC-2025-011",
|
||||
"Bulletin",
|
||||
"https://origin.example/advisories/info-bulletin"
|
||||
],
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/multi/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "multi",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/info-bulletin",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T02:30:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/info-bulletin",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "multi",
|
||||
"summary": "Information bulletin",
|
||||
"url": "https://origin.example/advisories/info-bulletin"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Serial number: ACSC-2025-011\n\nAdvisory type: Bulletin\n\nGeneral guidance bulletin.",
|
||||
"title": "Information bulletin"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "acsc/multi/https-origin-example-advisories-router-critical",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ExampleCo Router X",
|
||||
"platform": null,
|
||||
"versionRanges": [],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "affected",
|
||||
"value": "ExampleCo Router X",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ExampleCo Router Y",
|
||||
"platform": null,
|
||||
"versionRanges": [],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "affected",
|
||||
"value": "ExampleCo Router Y",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"ACSC-2025-010",
|
||||
"CVE-2025-0001",
|
||||
"https://origin.example/advisories/router-critical"
|
||||
],
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/multi/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "multi",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/router-critical",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T04:45:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/router-critical",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "multi",
|
||||
"summary": "Critical router vulnerability",
|
||||
"url": "https://origin.example/advisories/router-critical"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example/router/patch",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": "vendor patch",
|
||||
"url": "https://vendor.example/router/patch"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "Serial number: ACSC-2025-010\n\nSeverity: Critical\n\nSystems affected: ExampleCo Router X, ExampleCo Router Y\n\nRemote code execution on ExampleCo routers. See vendor patch.\n\nCVE references: CVE-2025-0001",
|
||||
"title": "Critical router vulnerability"
|
||||
}
|
||||
[
|
||||
{
|
||||
"advisoryKey": "acsc/multi/https-origin-example-advisories-info-bulletin",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"ACSC-2025-011",
|
||||
"Bulletin",
|
||||
"https://origin.example/advisories/info-bulletin"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/multi/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "multi",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/info-bulletin",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T02:30:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/info-bulletin",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "multi",
|
||||
"summary": "Information bulletin",
|
||||
"url": "https://origin.example/advisories/info-bulletin"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Serial number: ACSC-2025-011\n\nAdvisory type: Bulletin\n\nGeneral guidance bulletin.",
|
||||
"title": "Information bulletin"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "acsc/multi/https-origin-example-advisories-router-critical",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ExampleCo Router X",
|
||||
"platform": null,
|
||||
"versionRanges": [],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "affected",
|
||||
"value": "ExampleCo Router X",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ExampleCo Router Y",
|
||||
"platform": null,
|
||||
"versionRanges": [],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "affected",
|
||||
"value": "ExampleCo Router Y",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"ACSC-2025-010",
|
||||
"CVE-2025-0001",
|
||||
"https://origin.example/advisories/router-critical"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/multi/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "multi",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/router-critical",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T04:45:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/router-critical",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "multi",
|
||||
"summary": "Critical router vulnerability",
|
||||
"url": "https://origin.example/advisories/router-critical"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example/router/patch",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": "vendor patch",
|
||||
"url": "https://vendor.example/router/patch"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "Serial number: ACSC-2025-010\n\nSeverity: Critical\n\nSystems affected: ExampleCo Router X, ExampleCo Router Y\n\nRemote code execution on ExampleCo routers. See vendor patch.\n\nCVE references: CVE-2025-0001",
|
||||
"title": "Critical router vulnerability"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,91 @@
|
||||
[
|
||||
{
|
||||
"advisoryKey": "acsc/alerts/https-origin-example-advisories-example",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"ACSC-2025-001",
|
||||
"Alert",
|
||||
"https://origin.example/advisories/example"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/alerts/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "alerts",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/example",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T03:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/example",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "alerts",
|
||||
"summary": "ACSC-2025-001 Example Advisory",
|
||||
"url": "https://origin.example/advisories/example"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example/patch",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": "Vendor patch",
|
||||
"url": "https://vendor.example/patch"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Serial number: ACSC-2025-001\n\nAdvisory type: Alert\n\nFirst paragraph describing issue.\n\nSecond paragraph with Vendor patch.",
|
||||
"title": "ACSC-2025-001 Example Advisory"
|
||||
}
|
||||
]
|
||||
@@ -1,88 +1,91 @@
|
||||
[
|
||||
{
|
||||
"advisoryKey": "acsc/alerts/https-origin-example-advisories-example",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"ACSC-2025-001",
|
||||
"Alert",
|
||||
"https://origin.example/advisories/example"
|
||||
],
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/alerts/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "alerts",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/example",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T03:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/example",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "alerts",
|
||||
"summary": "ACSC-2025-001 Example Advisory",
|
||||
"url": "https://origin.example/advisories/example"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example/patch",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": "Vendor patch",
|
||||
"url": "https://vendor.example/patch"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Serial number: ACSC-2025-001\n\nAdvisory type: Alert\n\nFirst paragraph describing issue.\n\nSecond paragraph with Vendor patch.",
|
||||
"title": "ACSC-2025-001 Example Advisory"
|
||||
}
|
||||
[
|
||||
{
|
||||
"advisoryKey": "acsc/alerts/https-origin-example-advisories-example",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"ACSC-2025-001",
|
||||
"Alert",
|
||||
"https://origin.example/advisories/example"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "document",
|
||||
"value": "https://origin.example/feeds/alerts/rss",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "feed",
|
||||
"value": "alerts",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "acsc",
|
||||
"kind": "mapping",
|
||||
"value": "https://origin.example/advisories/example",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages",
|
||||
"aliases",
|
||||
"references",
|
||||
"summary"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-10-12T03:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://origin.example/advisories/example",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "alerts",
|
||||
"summary": "ACSC-2025-001 Example Advisory",
|
||||
"url": "https://origin.example/advisories/example"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "acsc",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example/patch",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": "Vendor patch",
|
||||
"url": "https://vendor.example/patch"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Serial number: ACSC-2025-001\n\nAdvisory type: Alert\n\nFirst paragraph describing issue.\n\nSecond paragraph with Vendor patch.",
|
||||
"title": "ACSC-2025-001 Example Advisory"
|
||||
}
|
||||
]
|
||||
@@ -10,7 +10,8 @@ using Microsoft.Extensions.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Concelier.Connector.Cccs;
|
||||
using StellaOps.Concelier.Connector.Cccs.Configuration;
|
||||
using StellaOps.Concelier.Connector.Common;
|
||||
@@ -79,11 +80,19 @@ public sealed class CccsConnectorTests : IAsyncLifetime
|
||||
await using var provider = await BuildServiceProviderAsync();
|
||||
SeedFeedResponses();
|
||||
|
||||
var connector = provider.GetRequiredService<CccsConnector>();
|
||||
await connector.FetchAsync(provider, CancellationToken.None);
|
||||
|
||||
var documentStore = provider.GetRequiredService<IDocumentStore>();
|
||||
var document = await documentStore.FindBySourceAndUriAsync(CccsConnectorPlugin.SourceName, "https://www.cyber.gc.ca/en/alerts-advisories/test-advisory", CancellationToken.None);
|
||||
var connector = provider.GetRequiredService<CccsConnector>();
|
||||
await connector.FetchAsync(provider, CancellationToken.None);
|
||||
|
||||
var mongo = provider.GetRequiredService<IMongoDatabase>();
|
||||
var docCollection = mongo.GetCollection<BsonDocument>("document");
|
||||
var documentsSnapshot = await docCollection.Find(FilterDefinition<BsonDocument>.Empty).ToListAsync();
|
||||
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.Combine(AppContext.BaseDirectory, "tmp"));
|
||||
var debugPath = System.IO.Path.Combine(AppContext.BaseDirectory, "tmp", "cccs-documents.json");
|
||||
await System.IO.File.WriteAllTextAsync(debugPath, documentsSnapshot.ToJson(new MongoDB.Bson.IO.JsonWriterSettings { Indent = true }));
|
||||
|
||||
var documentStore = provider.GetRequiredService<IDocumentStore>();
|
||||
var document = await documentStore.FindBySourceAndUriAsync(CccsConnectorPlugin.SourceName, "https://www.cyber.gc.ca/en/alerts-advisories/test-advisory", CancellationToken.None);
|
||||
document.Should().NotBeNull();
|
||||
document!.Status.Should().Be(DocumentStatuses.PendingParse);
|
||||
document.Metadata.Should().ContainKey("cccs.language").WhoseValue.Should().Be("en");
|
||||
|
||||
@@ -1,205 +1,226 @@
|
||||
[
|
||||
{
|
||||
"advisoryKey": "cert-fr/AV-2024.001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"identifier": "AV-2024.001",
|
||||
"platform": null,
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/"
|
||||
}
|
||||
],
|
||||
"statuses": [],
|
||||
"type": "vendor",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"certfr.summary": "Résumé de la première alerte.",
|
||||
"certfr.content": "AV-2024.001 Alerte CERT-FR AV-2024.001 L'exploitation active de la vulnérabilité est surveillée. Consultez les indications du fournisseur .",
|
||||
"certfr.reference.count": "1"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/"
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CERT-FR:AV-2024.001"
|
||||
],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "fr",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/"
|
||||
}
|
||||
],
|
||||
"published": "2024-10-03T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/"
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://vendor.example.com/patch"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/"
|
||||
},
|
||||
"sourceTag": "cert-fr",
|
||||
"summary": "Résumé de la première alerte.",
|
||||
"url": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Résumé de la première alerte.",
|
||||
"title": "AV-2024.001 - Première alerte"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "cert-fr/AV-2024.002",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"identifier": "AV-2024.002",
|
||||
"platform": null,
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/"
|
||||
}
|
||||
],
|
||||
"statuses": [],
|
||||
"type": "vendor",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"certfr.summary": "Résumé de la deuxième alerte.",
|
||||
"certfr.content": "AV-2024.002 Alerte CERT-FR AV-2024.002 Des correctifs sont disponibles pour plusieurs produits. Note de mise à jour Correctif",
|
||||
"certfr.reference.count": "2"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/"
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CERT-FR:AV-2024.002"
|
||||
],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "fr",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/"
|
||||
}
|
||||
],
|
||||
"published": "2024-10-03T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/"
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://support.example.com/kb/KB-1234"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/"
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://support.example.com/kb/KB-5678"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"source": "cert-fr",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/"
|
||||
},
|
||||
"sourceTag": "cert-fr",
|
||||
"summary": "Résumé de la deuxième alerte.",
|
||||
"url": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Résumé de la deuxième alerte.",
|
||||
"title": "AV-2024.002 - Deuxième alerte"
|
||||
}
|
||||
[
|
||||
{
|
||||
"advisoryKey": "cert-fr/AV-2024.001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "AV-2024.001",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"certfr.summary": "Résumé de la première alerte.",
|
||||
"certfr.content": "AV-2024.001 Alerte CERT-FR AV-2024.001 L'exploitation active de la vulnérabilité est surveillée. Consultez les indications du fournisseur .",
|
||||
"certfr.reference.count": "1"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CERT-FR:AV-2024.001"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "fr",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-10-03T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://vendor.example.com/patch"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "cert-fr",
|
||||
"summary": "Résumé de la première alerte.",
|
||||
"url": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.001/"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Résumé de la première alerte.",
|
||||
"title": "AV-2024.001 - Première alerte"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "cert-fr/AV-2024.002",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "AV-2024.002",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"certfr.summary": "Résumé de la deuxième alerte.",
|
||||
"certfr.content": "AV-2024.002 Alerte CERT-FR AV-2024.002 Des correctifs sont disponibles pour plusieurs produits. Note de mise à jour Correctif",
|
||||
"certfr.reference.count": "2"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CERT-FR:AV-2024.002"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "fr",
|
||||
"modified": null,
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-10-03T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://support.example.com/kb/KB-1234"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://support.example.com/kb/KB-5678"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "cert-fr",
|
||||
"kind": "document",
|
||||
"value": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-03T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "cert-fr",
|
||||
"summary": "Résumé de la deuxième alerte.",
|
||||
"url": "https://www.cert.ssi.gouv.fr/alerte/AV-2024.002/"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Résumé de la deuxième alerte.",
|
||||
"title": "AV-2024.002 - Deuxième alerte"
|
||||
}
|
||||
]
|
||||
@@ -1,128 +1,141 @@
|
||||
{
|
||||
"advisoryKey": "CIAD-2024-0005",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"identifier": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the",
|
||||
"platform": null,
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "affected",
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"source": "cert-in",
|
||||
"value": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the"
|
||||
}
|
||||
],
|
||||
"statuses": [],
|
||||
"type": "ics-vendor",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"certin.vendor": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the "
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "affected",
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"source": "cert-in",
|
||||
"value": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the"
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CIAD-2024-0005",
|
||||
"CVE-2024-9990",
|
||||
"CVE-2024-9991"
|
||||
],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-04-15T10:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-04-20T00:00:00+00:00",
|
||||
"source": "cert-in",
|
||||
"value": "https://cert-in.example/advisory/CIAD-2024-0005"
|
||||
},
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "mapping",
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"source": "cert-in",
|
||||
"value": "CIAD-2024-0005"
|
||||
}
|
||||
],
|
||||
"published": "2024-04-15T10:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"source": "cert-in",
|
||||
"value": "https://cert-in.example/advisory/CIAD-2024-0005"
|
||||
},
|
||||
"sourceTag": "cert-in",
|
||||
"summary": null,
|
||||
"url": "https://cert-in.example/advisory/CIAD-2024-0005"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"source": "cert-in",
|
||||
"value": "https://vendor.example.com/advisories/example-gateway-bulletin"
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://vendor.example.com/advisories/example-gateway-bulletin"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"source": "cert-in",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-9990"
|
||||
},
|
||||
"sourceTag": "CVE-2024-9990",
|
||||
"summary": null,
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-9990"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"source": "cert-in",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-9991"
|
||||
},
|
||||
"sourceTag": "CVE-2024-9991",
|
||||
"summary": null,
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-9991"
|
||||
}
|
||||
],
|
||||
"severity": "high",
|
||||
"summary": "Example Gateway devices vulnerable to remote code execution (CVE-2024-9990).",
|
||||
"title": "Multiple vulnerabilities in Example Gateway"
|
||||
{
|
||||
"advisoryKey": "CIAD-2024-0005",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"certin.vendor": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the "
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "affected",
|
||||
"value": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cert-in",
|
||||
"kind": "affected",
|
||||
"value": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CIAD-2024-0005",
|
||||
"CVE-2024-9990",
|
||||
"CVE-2024-9991"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-04-15T10:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cert-in",
|
||||
"kind": "document",
|
||||
"value": "https://cert-in.example/advisory/CIAD-2024-0005",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
{
|
||||
"source": "cert-in",
|
||||
"kind": "mapping",
|
||||
"value": "CIAD-2024-0005",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-04-15T10:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "reference",
|
||||
"value": "https://cert-in.example/advisory/CIAD-2024-0005",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "cert-in",
|
||||
"summary": null,
|
||||
"url": "https://cert-in.example/advisory/CIAD-2024-0005"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example.com/advisories/example-gateway-bulletin",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://vendor.example.com/advisories/example-gateway-bulletin"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "reference",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-9990",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "CVE-2024-9990",
|
||||
"summary": null,
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-9990"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "reference",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-9991",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "CVE-2024-9991",
|
||||
"summary": null,
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-9991"
|
||||
}
|
||||
],
|
||||
"severity": "high",
|
||||
"summary": "Example Gateway devices vulnerable to remote code execution (CVE-2024-9990).",
|
||||
"title": "Multiple vulnerabilities in Example Gateway"
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"advisoryKey": "CIAD-2024-0005",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"certin.vendor": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the "
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "affected",
|
||||
"value": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cert-in",
|
||||
"kind": "affected",
|
||||
"value": "Example Gateway Technologies Pvt Ltd Organisation: Partner Systems Inc. CVE-2024-9990 and CVE-2024-9991 allow remote attackers to execute arbitrary commands. Further information is available from the",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CIAD-2024-0005",
|
||||
"CVE-2024-9990",
|
||||
"CVE-2024-9991"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-04-15T10:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cert-in",
|
||||
"kind": "document",
|
||||
"value": "https://cert-in.example/advisory/CIAD-2024-0005",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
{
|
||||
"source": "cert-in",
|
||||
"kind": "mapping",
|
||||
"value": "CIAD-2024-0005",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-04-15T10:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "reference",
|
||||
"value": "https://cert-in.example/advisory/CIAD-2024-0005",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "cert-in",
|
||||
"summary": null,
|
||||
"url": "https://cert-in.example/advisory/CIAD-2024-0005"
|
||||
},
|
||||
{
|
||||
"kind": "reference",
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example.com/advisories/example-gateway-bulletin",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://vendor.example.com/advisories/example-gateway-bulletin"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "reference",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-9990",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "CVE-2024-9990",
|
||||
"summary": null,
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-9990"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "cert-in",
|
||||
"kind": "reference",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-9991",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "CVE-2024-9991",
|
||||
"summary": null,
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-9991"
|
||||
}
|
||||
],
|
||||
"severity": "high",
|
||||
"summary": "Example Gateway devices vulnerable to remote code execution (CVE-2024-9990).",
|
||||
"title": "Multiple vulnerabilities in Example Gateway"
|
||||
}
|
||||
@@ -1,221 +1,224 @@
|
||||
{
|
||||
"advisoryKey": "CVE-2024-0001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "examplevendor:exampleproduct",
|
||||
"platform": "linux",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "1.2.0",
|
||||
"introducedVersion": "1.0.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": "version=1.0.0, < 1.2.0",
|
||||
"exactValue": null,
|
||||
"fixed": "1.2.0",
|
||||
"fixedInclusive": false,
|
||||
"introduced": "1.0.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "range"
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vendor": "ExampleVendor",
|
||||
"product": "ExampleProduct",
|
||||
"platform": "linux",
|
||||
"version": "1.0.0",
|
||||
"lessThan": "1.2.0",
|
||||
"versionType": "semver"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "affected-range",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": "version=1.0.0, < 1.2.0",
|
||||
"rangeKind": "semver"
|
||||
},
|
||||
{
|
||||
"fixedVersion": "1.2.0",
|
||||
"introducedVersion": "1.2.0",
|
||||
"lastAffectedVersion": "1.2.0",
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": "version=1.2.0",
|
||||
"exactValue": null,
|
||||
"fixed": "1.2.0",
|
||||
"fixedInclusive": false,
|
||||
"introduced": "1.2.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": "1.2.0",
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "range"
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vendor": "ExampleVendor",
|
||||
"product": "ExampleProduct",
|
||||
"platform": "linux",
|
||||
"version": "1.2.0",
|
||||
"versionType": "semver"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "affected-range",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": "version=1.2.0",
|
||||
"rangeKind": "semver"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "exact",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": "1.2.0",
|
||||
"notes": "cve:cve-2024-0001:examplevendor:exampleproduct"
|
||||
},
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "range",
|
||||
"min": "1.0.0",
|
||||
"minInclusive": true,
|
||||
"max": "1.2.0",
|
||||
"maxInclusive": false,
|
||||
"value": null,
|
||||
"notes": "cve:cve-2024-0001:examplevendor:exampleproduct"
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "affected-status",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"status": "affected"
|
||||
},
|
||||
{
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "affected-status",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"status": "not_affected"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cve",
|
||||
"kind": "affected",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CVE-2024-0001",
|
||||
"GHSA-xxxx-yyyy-zzzz"
|
||||
],
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 9.8,
|
||||
"baseSeverity": "critical",
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "cvss",
|
||||
"value": "cve/CVE-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"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": "2024-09-15T12:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cve",
|
||||
"kind": "document",
|
||||
"value": "cve/CVE-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
{
|
||||
"source": "cve",
|
||||
"kind": "mapping",
|
||||
"value": "CVE-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-09-10T12:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "third-party-advisory",
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "reference",
|
||||
"value": "https://cve.example.com/CVE-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://cve.example.com/CVE-2024-0001"
|
||||
},
|
||||
{
|
||||
"kind": "vendor-advisory",
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "reference",
|
||||
"value": "https://example.com/security/advisory",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "Vendor Advisory",
|
||||
"summary": null,
|
||||
"url": "https://example.com/security/advisory"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "An example vulnerability allowing remote attackers to execute arbitrary code.",
|
||||
"title": "Example Product Remote Code Execution"
|
||||
{
|
||||
"advisoryKey": "CVE-2024-0001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "examplevendor:exampleproduct",
|
||||
"platform": "linux",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "1.2.0",
|
||||
"introducedVersion": "1.0.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": "version=1.0.0, < 1.2.0",
|
||||
"exactValue": null,
|
||||
"fixed": "1.2.0",
|
||||
"fixedInclusive": false,
|
||||
"introduced": "1.0.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "range"
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vendor": "ExampleVendor",
|
||||
"product": "ExampleProduct",
|
||||
"platform": "linux",
|
||||
"version": "1.0.0",
|
||||
"lessThan": "1.2.0",
|
||||
"versionType": "semver"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "affected-range",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": "version=1.0.0, < 1.2.0",
|
||||
"rangeKind": "semver"
|
||||
},
|
||||
{
|
||||
"fixedVersion": "1.2.0",
|
||||
"introducedVersion": "1.2.0",
|
||||
"lastAffectedVersion": "1.2.0",
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": "version=1.2.0",
|
||||
"exactValue": "1.2.0",
|
||||
"fixed": "1.2.0",
|
||||
"fixedInclusive": false,
|
||||
"introduced": "1.2.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": "1.2.0",
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "exact"
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vendor": "ExampleVendor",
|
||||
"product": "ExampleProduct",
|
||||
"platform": "linux",
|
||||
"version": "1.2.0",
|
||||
"versionType": "semver"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "affected-range",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": "version=1.2.0",
|
||||
"rangeKind": "semver"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "exact",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": "1.2.0",
|
||||
"notes": "cve:cve-2024-0001:examplevendor:exampleproduct"
|
||||
},
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "range",
|
||||
"min": "1.0.0",
|
||||
"minInclusive": true,
|
||||
"max": "1.2.0",
|
||||
"maxInclusive": false,
|
||||
"value": null,
|
||||
"notes": "cve:cve-2024-0001:examplevendor:exampleproduct"
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "affected-status",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"status": "affected"
|
||||
},
|
||||
{
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "affected-status",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"status": "not_affected"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cve",
|
||||
"kind": "affected",
|
||||
"value": "examplevendor:exampleproduct",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CVE-2024-0001",
|
||||
"GHSA-xxxx-yyyy-zzzz"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 9.8,
|
||||
"baseSeverity": "critical",
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "cvss",
|
||||
"value": "cve/CVE-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
||||
"version": "3.1"
|
||||
}
|
||||
],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-09-15T12:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "cve",
|
||||
"kind": "document",
|
||||
"value": "cve/CVE-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
{
|
||||
"source": "cve",
|
||||
"kind": "mapping",
|
||||
"value": "CVE-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-09-10T12:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "third-party-advisory",
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "reference",
|
||||
"value": "https://cve.example.com/CVE-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://cve.example.com/CVE-2024-0001"
|
||||
},
|
||||
{
|
||||
"kind": "vendor-advisory",
|
||||
"provenance": {
|
||||
"source": "cve",
|
||||
"kind": "reference",
|
||||
"value": "https://example.com/security/advisory",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-01T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "Vendor Advisory",
|
||||
"summary": null,
|
||||
"url": "https://example.com/security/advisory"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "An example vulnerability allowing remote attackers to execute arbitrary code.",
|
||||
"title": "Example Product Remote Code Execution"
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public class IcsCisaConnectorMappingTests
|
||||
Assert.Equal("ControlSuite", productPackage.Identifier);
|
||||
var range = Assert.Single(productPackage.VersionRanges);
|
||||
Assert.Equal("product", range.RangeKind);
|
||||
Assert.Equal("4.2.0", range.RangeExpression);
|
||||
Assert.Equal("4.2", range.RangeExpression);
|
||||
Assert.NotNull(range.Primitives);
|
||||
Assert.Equal("Example Corp", range.Primitives!.VendorExtensions!["ics.vendors"]);
|
||||
Assert.Equal("ControlSuite", range.Primitives.VendorExtensions!["ics.product"]);
|
||||
@@ -129,7 +129,7 @@ public class IcsCisaConnectorMappingTests
|
||||
var productPackage = Assert.Single(packages);
|
||||
Assert.Equal("Control Suite Firmware", productPackage.Identifier);
|
||||
var range = Assert.Single(productPackage.VersionRanges);
|
||||
Assert.Equal("1.0.0 - 2.0.0", range.RangeExpression);
|
||||
Assert.Equal("1.0 - 2.0", range.RangeExpression);
|
||||
Assert.NotNull(range.Primitives);
|
||||
Assert.Equal("ics-cisa:ICSA-25-789-03:control-suite-firmware", range.Provenance.Value);
|
||||
var rule = Assert.Single(productPackage.NormalizedVersions);
|
||||
|
||||
@@ -0,0 +1,557 @@
|
||||
{
|
||||
"advisoryKey": "acme-controller-2024",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "2024",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "2024"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "2024",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "2024",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "7777 can allow authenticated attackers to execute arbitrary commands",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "7777 can allow authenticated attackers to execute arbitrary commands"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "7777 can allow authenticated attackers to execute arbitrary commands",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "7777 can allow authenticated attackers to execute arbitrary commands",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "7777)",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "7777)"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "7777)",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "7777)",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "8888",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "8888"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "8888",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "8888",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "ACME Corp",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "ACME Corp"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "ACME Corp",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "ACME Corp",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "ACME Corp Affected models",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "ACME Corp Affected models"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "ACME Corp Affected models",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "ACME Corp Affected models",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "ACME Corp industrial",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "ACME Corp industrial"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "ACME Corp industrial",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "ACME Corp industrial",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "Additional details are provided in CVE",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "Additional details are provided in CVE"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "Additional details are provided in CVE",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "Additional details are provided in CVE",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "Exploitation of CVE",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "Exploitation of CVE"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "Exploitation of CVE",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "Exploitation of CVE",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "Vendor",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "Vendor"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "Vendor",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "Vendor",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "X100, X200",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": null,
|
||||
"vendorExtensions": {
|
||||
"ics.vendor": "X100, X200"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "X100, X200",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": null,
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "affected",
|
||||
"value": "X100, X200",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CVE-2024-7777",
|
||||
"CVE-2024-8888",
|
||||
"acme-controller-2024"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-10-15T10:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "document",
|
||||
"value": "https://ics-cert.example/advisories/acme-controller-2024/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
{
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "mapping",
|
||||
"value": "acme-controller-2024",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-10-15T10:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "reference",
|
||||
"value": "https://ics-cert.example/advisories/acme-controller-2024/",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "kaspersky-ics",
|
||||
"summary": null,
|
||||
"url": "https://ics-cert.example/advisories/acme-controller-2024/"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "reference",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-7777",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "CVE-2024-7777",
|
||||
"summary": null,
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-7777"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "ics-kaspersky",
|
||||
"kind": "reference",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-8888",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-10-20T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "CVE-2024-8888",
|
||||
"summary": null,
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-8888"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "ACME Corp industrial controllers allow remote compromise (CVE-2024-7777).",
|
||||
"title": "ACME Corp controllers multiple vulnerabilities"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,87 +1,97 @@
|
||||
{
|
||||
"advisoryKey": "JVNDB-2024-123456",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"CVE-2024-5555",
|
||||
"JVNDB-2024-123456"
|
||||
],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 8.8,
|
||||
"baseSeverity": "high",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "cvss",
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"source": "jvn",
|
||||
"value": "Base"
|
||||
},
|
||||
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
|
||||
"version": "3.1"
|
||||
}
|
||||
],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-03-10T02:30:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-03-10T00:00:00+00:00",
|
||||
"source": "jvn",
|
||||
"value": "https://jvndb.jvn.jp/myjvn?method=getVulnDetailInfo&feed=hnd&lang=en&vulnId=JVNDB-2024-123456"
|
||||
},
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "mapping",
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"source": "jvn",
|
||||
"value": "JVNDB-2024-123456"
|
||||
}
|
||||
],
|
||||
"published": "2024-03-09T02:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "weakness",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"source": "jvn",
|
||||
"value": "https://cwe.mitre.org/data/definitions/287.html"
|
||||
},
|
||||
"sourceTag": "CWE-287",
|
||||
"summary": "JVNDB",
|
||||
"url": "https://cwe.mitre.org/data/definitions/287.html"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"source": "jvn",
|
||||
"value": "https://vendor.example.com/advisories/EX-2024-01"
|
||||
},
|
||||
"sourceTag": "EX-2024-01",
|
||||
"summary": "Example ICS Vendor Advisory",
|
||||
"url": "https://vendor.example.com/advisories/EX-2024-01"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"source": "jvn",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-5555"
|
||||
},
|
||||
"sourceTag": "CVE-2024-5555",
|
||||
"summary": "Common Vulnerabilities and Exposures (CVE)",
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-5555"
|
||||
}
|
||||
],
|
||||
"severity": "high",
|
||||
"summary": "Imaginary ICS Controller provided by Example Industrial Corporation contains an authentication bypass vulnerability.",
|
||||
"title": "Example vulnerability in Imaginary ICS Controller"
|
||||
{
|
||||
"advisoryKey": "JVNDB-2024-123456",
|
||||
"affectedPackages": [],
|
||||
"aliases": [
|
||||
"CVE-2024-5555",
|
||||
"JVNDB-2024-123456"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 8.8,
|
||||
"baseSeverity": "high",
|
||||
"provenance": {
|
||||
"source": "jvn",
|
||||
"kind": "cvss",
|
||||
"value": "Base",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
|
||||
"version": "3.1"
|
||||
}
|
||||
],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-03-10T02:30:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "jvn",
|
||||
"kind": "document",
|
||||
"value": "https://jvndb.jvn.jp/myjvn?method=getVulnDetailInfo&feed=hnd&lang=en&vulnId=JVNDB-2024-123456",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-03-10T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
{
|
||||
"source": "jvn",
|
||||
"kind": "mapping",
|
||||
"value": "JVNDB-2024-123456",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-03-09T02:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "weakness",
|
||||
"provenance": {
|
||||
"source": "jvn",
|
||||
"kind": "reference",
|
||||
"value": "https://cwe.mitre.org/data/definitions/287.html",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "CWE-287",
|
||||
"summary": "JVNDB",
|
||||
"url": "https://cwe.mitre.org/data/definitions/287.html"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "jvn",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example.com/advisories/EX-2024-01",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "EX-2024-01",
|
||||
"summary": "Example ICS Vendor Advisory",
|
||||
"url": "https://vendor.example.com/advisories/EX-2024-01"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "jvn",
|
||||
"kind": "reference",
|
||||
"value": "https://www.cve.org/CVERecord?id=CVE-2024-5555",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-03-10T00:01:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "CVE-2024-5555",
|
||||
"summary": "Common Vulnerabilities and Exposures (CVE)",
|
||||
"url": "https://www.cve.org/CVERecord?id=CVE-2024-5555"
|
||||
}
|
||||
],
|
||||
"severity": "high",
|
||||
"summary": "Imaginary ICS Controller provided by Example Industrial Corporation contains an authentication bypass vulnerability.",
|
||||
"title": "Example vulnerability in Imaginary ICS Controller"
|
||||
}
|
||||
@@ -1,335 +1,338 @@
|
||||
[
|
||||
{
|
||||
"advisoryKey": "BDU:2025-00001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ООО «1С-Софт» 1С:Предприятие",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": null,
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-range",
|
||||
"value": "8.2.19.116",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": "8.2.19.116",
|
||||
"rangeKind": "string"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "ru-bdu.raw",
|
||||
"type": "exact",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": "8.2.19.116",
|
||||
"notes": null
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-status",
|
||||
"value": "Подтверждена производителем",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "affected"
|
||||
},
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-fix-status",
|
||||
"value": "Уязвимость устранена",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "fixed"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-bdu",
|
||||
"kind": "package",
|
||||
"value": "ООО «1С-Софт» 1С:Предприятие",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ООО «1С-Софт» 1С:Предприятие",
|
||||
"platform": "Windows",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": null,
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-range",
|
||||
"value": "8.2.18.96",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": "8.2.18.96",
|
||||
"rangeKind": "string"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "ru-bdu.raw",
|
||||
"type": "exact",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": "8.2.18.96",
|
||||
"notes": null
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-status",
|
||||
"value": "Подтверждена производителем",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "affected"
|
||||
},
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-fix-status",
|
||||
"value": "Уязвимость устранена",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "fixed"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-bdu",
|
||||
"kind": "package",
|
||||
"value": "ООО «1С-Софт» 1С:Предприятие",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"BDU:2025-00001",
|
||||
"CVE-2009-3555",
|
||||
"CVE-2015-0206",
|
||||
"PT-2015-0206"
|
||||
],
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 7.5,
|
||||
"baseSeverity": "high",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:2.0/AV:N/AC:L/AU:N/C:P/I:P/A:P",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:2.0/AV:N/AC:L/AU:N/C:P/I:P/A:P",
|
||||
"version": "2.0"
|
||||
},
|
||||
{
|
||||
"baseScore": 9.8,
|
||||
"baseSeverity": "critical",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"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-10-14T08: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": true,
|
||||
"language": "ru",
|
||||
"modified": "2013-01-12T00:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-bdu",
|
||||
"kind": "advisory",
|
||||
"value": "BDU:2025-00001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2013-01-12T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "source",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "http://mirror.example/ru-bdu/BDU-2025-00001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-bdu",
|
||||
"summary": null,
|
||||
"url": "http://mirror.example/ru-bdu/BDU-2025-00001"
|
||||
},
|
||||
{
|
||||
"kind": "source",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://advisories.example/BDU-2025-00001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-bdu",
|
||||
"summary": null,
|
||||
"url": "https://advisories.example/BDU-2025-00001"
|
||||
},
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://bdu.fstec.ru/vul/2025-00001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-bdu",
|
||||
"summary": null,
|
||||
"url": "https://bdu.fstec.ru/vul/2025-00001"
|
||||
},
|
||||
{
|
||||
"kind": "cwe",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://cwe.mitre.org/data/definitions/310.html",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "cwe",
|
||||
"summary": "Проблемы использования криптографии",
|
||||
"url": "https://cwe.mitre.org/data/definitions/310.html"
|
||||
},
|
||||
{
|
||||
"kind": "cve",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://nvd.nist.gov/vuln/detail/CVE-2009-3555",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "cve",
|
||||
"summary": "CVE-2009-3555",
|
||||
"url": "https://nvd.nist.gov/vuln/detail/CVE-2009-3555"
|
||||
},
|
||||
{
|
||||
"kind": "cve",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://nvd.nist.gov/vuln/detail/CVE-2015-0206",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "cve",
|
||||
"summary": "CVE-2015-0206",
|
||||
"url": "https://nvd.nist.gov/vuln/detail/CVE-2015-0206"
|
||||
},
|
||||
{
|
||||
"kind": "external",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://ptsecurity.com/PT-2015-0206",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "positivetechnologiesadvisory",
|
||||
"summary": "PT-2015-0206",
|
||||
"url": "https://ptsecurity.com/PT-2015-0206"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "Удалённый злоумышленник может вызвать отказ в обслуживании или получить доступ к данным.",
|
||||
"title": "Множественные уязвимости криптопровайдера"
|
||||
}
|
||||
[
|
||||
{
|
||||
"advisoryKey": "BDU:2025-00001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ООО «1С-Софт» 1С:Предприятие",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": null,
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-range",
|
||||
"value": "8.2.19.116",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": "8.2.19.116",
|
||||
"rangeKind": "string"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "ru-bdu.raw",
|
||||
"type": "exact",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": "8.2.19.116",
|
||||
"notes": null
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-status",
|
||||
"value": "Подтверждена производителем",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "affected"
|
||||
},
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-fix-status",
|
||||
"value": "Уязвимость устранена",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "fixed"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-bdu",
|
||||
"kind": "package",
|
||||
"value": "ООО «1С-Софт» 1С:Предприятие",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "ООО «1С-Софт» 1С:Предприятие",
|
||||
"platform": "Windows",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": null,
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-range",
|
||||
"value": "8.2.18.96",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": "8.2.18.96",
|
||||
"rangeKind": "string"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "ru-bdu.raw",
|
||||
"type": "exact",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": "8.2.18.96",
|
||||
"notes": null
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-status",
|
||||
"value": "Подтверждена производителем",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "affected"
|
||||
},
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "package-fix-status",
|
||||
"value": "Уязвимость устранена",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "fixed"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-bdu",
|
||||
"kind": "package",
|
||||
"value": "ООО «1С-Софт» 1С:Предприятие",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"BDU:2025-00001",
|
||||
"CVE-2009-3555",
|
||||
"CVE-2015-0206",
|
||||
"PT-2015-0206"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 7.5,
|
||||
"baseSeverity": "high",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:2.0/AV:N/AC:L/AU:N/C:P/I:P/A:P",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:2.0/AV:N/AC:L/AU:N/C:P/I:P/A:P",
|
||||
"version": "2.0"
|
||||
},
|
||||
{
|
||||
"baseScore": 9.8,
|
||||
"baseSeverity": "critical",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"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-10-14T08: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"
|
||||
}
|
||||
],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": true,
|
||||
"language": "ru",
|
||||
"modified": "2013-01-12T00:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-bdu",
|
||||
"kind": "advisory",
|
||||
"value": "BDU:2025-00001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2013-01-12T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "source",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "http://mirror.example/ru-bdu/BDU-2025-00001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-bdu",
|
||||
"summary": null,
|
||||
"url": "http://mirror.example/ru-bdu/BDU-2025-00001"
|
||||
},
|
||||
{
|
||||
"kind": "source",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://advisories.example/BDU-2025-00001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-bdu",
|
||||
"summary": null,
|
||||
"url": "https://advisories.example/BDU-2025-00001"
|
||||
},
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://bdu.fstec.ru/vul/2025-00001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-bdu",
|
||||
"summary": null,
|
||||
"url": "https://bdu.fstec.ru/vul/2025-00001"
|
||||
},
|
||||
{
|
||||
"kind": "cwe",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://cwe.mitre.org/data/definitions/310.html",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "cwe",
|
||||
"summary": "Проблемы использования криптографии",
|
||||
"url": "https://cwe.mitre.org/data/definitions/310.html"
|
||||
},
|
||||
{
|
||||
"kind": "cve",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://nvd.nist.gov/vuln/detail/CVE-2009-3555",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "cve",
|
||||
"summary": "CVE-2009-3555",
|
||||
"url": "https://nvd.nist.gov/vuln/detail/CVE-2009-3555"
|
||||
},
|
||||
{
|
||||
"kind": "cve",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://nvd.nist.gov/vuln/detail/CVE-2015-0206",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "cve",
|
||||
"summary": "CVE-2015-0206",
|
||||
"url": "https://nvd.nist.gov/vuln/detail/CVE-2015-0206"
|
||||
},
|
||||
{
|
||||
"kind": "external",
|
||||
"provenance": {
|
||||
"source": "ru-bdu",
|
||||
"kind": "reference",
|
||||
"value": "https://ptsecurity.com/PT-2015-0206",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-14T08:00:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "positivetechnologiesadvisory",
|
||||
"summary": "PT-2015-0206",
|
||||
"url": "https://ptsecurity.com/PT-2015-0206"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "Удалённый злоумышленник может вызвать отказ в обслуживании или получить доступ к данным.",
|
||||
"title": "Множественные уязвимости криптопровайдера"
|
||||
}
|
||||
]
|
||||
@@ -1,11 +1,11 @@
|
||||
[
|
||||
{
|
||||
"metadata": {
|
||||
"ru-bdu.identifier": "BDU:2025-00001",
|
||||
"ru-bdu.name": "Множественные уязвимости криптопровайдера"
|
||||
},
|
||||
"sha256": "c43df9c4a75a74b281ff09122bb8f63096a0a73b30df74d73c3bc997019bd4d4",
|
||||
"status": "mapped",
|
||||
"uri": "https://bdu.fstec.ru/vul/2025-00001"
|
||||
}
|
||||
[
|
||||
{
|
||||
"metadata": {
|
||||
"ru-bdu.identifier": "BDU:2025-00001",
|
||||
"ru-bdu.name": "Множественные уязвимости криптопровайдера"
|
||||
},
|
||||
"sha256": "c43df9c4a75a74b281ff09122bb8f63096a0a73b30df74d73c3bc997019bd4d4",
|
||||
"status": "mapped",
|
||||
"uri": "https://bdu.fstec.ru/vul/2025-00001"
|
||||
}
|
||||
]
|
||||
@@ -1,86 +1,86 @@
|
||||
[
|
||||
{
|
||||
"documentUri": "https://bdu.fstec.ru/vul/2025-00001",
|
||||
"payload": {
|
||||
"identifier": "BDU:2025-00001",
|
||||
"name": "Множественные уязвимости криптопровайдера",
|
||||
"description": "Удалённый злоумышленник может вызвать отказ в обслуживании или получить доступ к данным.",
|
||||
"solution": "Установить обновление 8.2.19.116 защищённого комплекса.",
|
||||
"identifyDate": "2013-01-12T00:00:00+00:00",
|
||||
"severityText": "Высокий уровень опасности (базовая оценка CVSS 2.0 составляет 7,5)",
|
||||
"cvssVector": "AV:N/AC:L/Au:N/C:P/I:P/A:P",
|
||||
"cvssScore": 7.5,
|
||||
"cvss3Vector": "AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
||||
"cvss3Score": 9.8,
|
||||
"exploitStatus": "Существует в открытом доступе",
|
||||
"incidentCount": 0,
|
||||
"fixStatus": "Уязвимость устранена",
|
||||
"vulStatus": "Подтверждена производителем",
|
||||
"vulClass": "Уязвимость кода",
|
||||
"vulState": "Опубликована",
|
||||
"other": "Язык разработки ПО – С",
|
||||
"software": [
|
||||
{
|
||||
"vendor": "ООО «1С-Софт»",
|
||||
"name": "1С:Предприятие",
|
||||
"version": "8.2.18.96",
|
||||
"platform": "Windows",
|
||||
"types": [
|
||||
"Прикладное ПО информационных систем"
|
||||
]
|
||||
},
|
||||
{
|
||||
"vendor": "ООО «1С-Софт»",
|
||||
"name": "1С:Предприятие",
|
||||
"version": "8.2.19.116",
|
||||
"platform": "Не указана",
|
||||
"types": [
|
||||
"Прикладное ПО информационных систем"
|
||||
]
|
||||
}
|
||||
],
|
||||
"environment": [
|
||||
{
|
||||
"vendor": "Microsoft Corp",
|
||||
"name": "Windows",
|
||||
"version": "-",
|
||||
"platform": "64-bit"
|
||||
},
|
||||
{
|
||||
"vendor": "Microsoft Corp",
|
||||
"name": "Windows",
|
||||
"version": "-",
|
||||
"platform": "32-bit"
|
||||
}
|
||||
],
|
||||
"cwes": [
|
||||
{
|
||||
"identifier": "CWE-310",
|
||||
"name": "Проблемы использования криптографии"
|
||||
}
|
||||
],
|
||||
"sources": [
|
||||
"https://advisories.example/BDU-2025-00001",
|
||||
"http://mirror.example/ru-bdu/BDU-2025-00001"
|
||||
],
|
||||
"identifiers": [
|
||||
{
|
||||
"type": "CVE",
|
||||
"value": "CVE-2015-0206",
|
||||
"link": "https://nvd.nist.gov/vuln/detail/CVE-2015-0206"
|
||||
},
|
||||
{
|
||||
"type": "CVE",
|
||||
"value": "CVE-2009-3555",
|
||||
"link": "https://nvd.nist.gov/vuln/detail/CVE-2009-3555"
|
||||
},
|
||||
{
|
||||
"type": "Positive Technologies Advisory",
|
||||
"value": "PT-2015-0206",
|
||||
"link": "https://ptsecurity.com/PT-2015-0206"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemaVersion": "ru-bdu.v1"
|
||||
}
|
||||
[
|
||||
{
|
||||
"documentUri": "https://bdu.fstec.ru/vul/2025-00001",
|
||||
"payload": {
|
||||
"identifier": "BDU:2025-00001",
|
||||
"name": "Множественные уязвимости криптопровайдера",
|
||||
"description": "Удалённый злоумышленник может вызвать отказ в обслуживании или получить доступ к данным.",
|
||||
"solution": "Установить обновление 8.2.19.116 защищённого комплекса.",
|
||||
"identifyDate": "2013-01-12T00:00:00+00:00",
|
||||
"severityText": "Высокий уровень опасности (базовая оценка CVSS 2.0 составляет 7,5)",
|
||||
"cvssVector": "AV:N/AC:L/Au:N/C:P/I:P/A:P",
|
||||
"cvssScore": 7.5,
|
||||
"cvss3Vector": "AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
||||
"cvss3Score": 9.8,
|
||||
"exploitStatus": "Существует в открытом доступе",
|
||||
"incidentCount": 0,
|
||||
"fixStatus": "Уязвимость устранена",
|
||||
"vulStatus": "Подтверждена производителем",
|
||||
"vulClass": "Уязвимость кода",
|
||||
"vulState": "Опубликована",
|
||||
"other": "Язык разработки ПО – С",
|
||||
"software": [
|
||||
{
|
||||
"vendor": "ООО «1С-Софт»",
|
||||
"name": "1С:Предприятие",
|
||||
"version": "8.2.18.96",
|
||||
"platform": "Windows",
|
||||
"types": [
|
||||
"Прикладное ПО информационных систем"
|
||||
]
|
||||
},
|
||||
{
|
||||
"vendor": "ООО «1С-Софт»",
|
||||
"name": "1С:Предприятие",
|
||||
"version": "8.2.19.116",
|
||||
"platform": "Не указана",
|
||||
"types": [
|
||||
"Прикладное ПО информационных систем"
|
||||
]
|
||||
}
|
||||
],
|
||||
"environment": [
|
||||
{
|
||||
"vendor": "Microsoft Corp",
|
||||
"name": "Windows",
|
||||
"version": "-",
|
||||
"platform": "64-bit"
|
||||
},
|
||||
{
|
||||
"vendor": "Microsoft Corp",
|
||||
"name": "Windows",
|
||||
"version": "-",
|
||||
"platform": "32-bit"
|
||||
}
|
||||
],
|
||||
"cwes": [
|
||||
{
|
||||
"identifier": "CWE-310",
|
||||
"name": "Проблемы использования криптографии"
|
||||
}
|
||||
],
|
||||
"sources": [
|
||||
"https://advisories.example/BDU-2025-00001",
|
||||
"http://mirror.example/ru-bdu/BDU-2025-00001"
|
||||
],
|
||||
"identifiers": [
|
||||
{
|
||||
"type": "CVE",
|
||||
"value": "CVE-2015-0206",
|
||||
"link": "https://nvd.nist.gov/vuln/detail/CVE-2015-0206"
|
||||
},
|
||||
{
|
||||
"type": "CVE",
|
||||
"value": "CVE-2009-3555",
|
||||
"link": "https://nvd.nist.gov/vuln/detail/CVE-2009-3555"
|
||||
},
|
||||
{
|
||||
"type": "Positive Technologies Advisory",
|
||||
"value": "PT-2015-0206",
|
||||
"link": "https://ptsecurity.com/PT-2015-0206"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemaVersion": "ru-bdu.v1"
|
||||
}
|
||||
]
|
||||
@@ -1,11 +1,11 @@
|
||||
[
|
||||
{
|
||||
"headers": {
|
||||
"accept": "application/zip,application/octet-stream,application/x-zip-compressed",
|
||||
"accept-Language": "ru-RU,ru; q=0.9,en-US; q=0.6,en; q=0.4",
|
||||
"user-Agent": "StellaOps/Concelier,(+https://stella-ops.org)"
|
||||
},
|
||||
"method": "GET",
|
||||
"uri": "https://bdu.fstec.ru/files/documents/vulxml.zip"
|
||||
}
|
||||
[
|
||||
{
|
||||
"headers": {
|
||||
"accept": "application/zip,application/octet-stream,application/x-zip-compressed",
|
||||
"accept-Language": "ru-RU,ru; q=0.9,en-US; q=0.6,en; q=0.4",
|
||||
"user-Agent": "StellaOps/Concelier,(+https://stella-ops.org)"
|
||||
},
|
||||
"method": "GET",
|
||||
"uri": "https://bdu.fstec.ru/files/documents/vulxml.zip"
|
||||
}
|
||||
]
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lastSuccessfulFetch": "2025-10-14T08:00:00.0000000+00:00",
|
||||
"pendingDocuments": [],
|
||||
"pendingMappings": []
|
||||
{
|
||||
"lastSuccessfulFetch": "2025-10-14T08:00:00.0000000+00:00",
|
||||
"pendingDocuments": [],
|
||||
"pendingMappings": []
|
||||
}
|
||||
@@ -1,303 +1,313 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Concelier.Connector.Common.Testing;
|
||||
using StellaOps.Concelier.Connector.Ru.Bdu;
|
||||
using StellaOps.Concelier.Connector.Ru.Bdu.Configuration;
|
||||
using StellaOps.Concelier.Connector.Ru.Bdu.Internal;
|
||||
using StellaOps.Concelier.Storage.Mongo;
|
||||
using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Documents;
|
||||
using StellaOps.Concelier.Storage.Mongo.Dtos;
|
||||
using StellaOps.Concelier.Testing;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ru.Bdu.Tests;
|
||||
|
||||
[Collection("mongo-fixture")]
|
||||
public sealed class RuBduConnectorSnapshotTests : IAsyncLifetime
|
||||
{
|
||||
private const string UpdateFixturesVariable = "UPDATE_BDU_FIXTURES";
|
||||
private static readonly Uri ArchiveUri = new("https://bdu.fstec.ru/files/documents/vulxml.zip");
|
||||
|
||||
private readonly MongoIntegrationFixture _fixture;
|
||||
private ConnectorTestHarness? _harness;
|
||||
|
||||
public RuBduConnectorSnapshotTests(MongoIntegrationFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FetchParseMap_ProducesDeterministicSnapshots()
|
||||
{
|
||||
var harness = await EnsureHarnessAsync();
|
||||
harness.Handler.AddResponse(ArchiveUri, BuildArchiveResponse);
|
||||
|
||||
var connector = harness.ServiceProvider.GetRequiredService<RuBduConnector>();
|
||||
await connector.FetchAsync(harness.ServiceProvider, CancellationToken.None);
|
||||
|
||||
var stateRepository = harness.ServiceProvider.GetRequiredService<ISourceStateRepository>();
|
||||
var initialState = await stateRepository.TryGetAsync(RuBduConnectorPlugin.SourceName, CancellationToken.None);
|
||||
Assert.NotNull(initialState);
|
||||
var cursorBeforeParse = initialState!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromBson(initialState.Cursor);
|
||||
Assert.NotEmpty(cursorBeforeParse.PendingDocuments);
|
||||
var expectedDocumentIds = cursorBeforeParse.PendingDocuments.ToArray();
|
||||
|
||||
await connector.ParseAsync(harness.ServiceProvider, CancellationToken.None);
|
||||
await connector.MapAsync(harness.ServiceProvider, CancellationToken.None);
|
||||
|
||||
var documentsCollection = _fixture.Database.GetCollection<BsonDocument>(MongoStorageDefaults.Collections.Document);
|
||||
var documentCount = await documentsCollection.CountDocumentsAsync(Builders<BsonDocument>.Filter.Empty);
|
||||
Assert.True(documentCount > 0, "Expected persisted documents after map stage");
|
||||
|
||||
var documentsSnapshot = await BuildDocumentsSnapshotAsync(harness.ServiceProvider, expectedDocumentIds);
|
||||
WriteOrAssertSnapshot(documentsSnapshot, "ru-bdu-documents.snapshot.json");
|
||||
|
||||
var dtoSnapshot = await BuildDtoSnapshotAsync(harness.ServiceProvider);
|
||||
WriteOrAssertSnapshot(dtoSnapshot, "ru-bdu-dtos.snapshot.json");
|
||||
|
||||
var advisoriesSnapshot = await BuildAdvisoriesSnapshotAsync(harness.ServiceProvider);
|
||||
WriteOrAssertSnapshot(advisoriesSnapshot, "ru-bdu-advisories.snapshot.json");
|
||||
|
||||
var stateSnapshot = await BuildStateSnapshotAsync(harness.ServiceProvider);
|
||||
WriteOrAssertSnapshot(stateSnapshot, "ru-bdu-state.snapshot.json");
|
||||
|
||||
var requestsSnapshot = BuildRequestsSnapshot(harness.Handler.Requests);
|
||||
WriteOrAssertSnapshot(requestsSnapshot, "ru-bdu-requests.snapshot.json");
|
||||
|
||||
harness.Handler.AssertNoPendingResponses();
|
||||
}
|
||||
|
||||
public Task InitializeAsync() => Task.CompletedTask;
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
if (_harness is not null)
|
||||
{
|
||||
await _harness.DisposeAsync();
|
||||
_harness = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<ConnectorTestHarness> EnsureHarnessAsync()
|
||||
{
|
||||
if (_harness is not null)
|
||||
{
|
||||
return _harness;
|
||||
}
|
||||
|
||||
var initialTime = new DateTimeOffset(2025, 10, 14, 8, 0, 0, TimeSpan.Zero);
|
||||
var harness = new ConnectorTestHarness(_fixture, initialTime, RuBduOptions.HttpClientName);
|
||||
await harness.EnsureServiceProviderAsync(services =>
|
||||
{
|
||||
services.AddLogging(builder =>
|
||||
{
|
||||
builder.ClearProviders();
|
||||
builder.AddProvider(NullLoggerProvider.Instance);
|
||||
});
|
||||
|
||||
services.AddRuBduConnector(options =>
|
||||
{
|
||||
options.BaseAddress = new Uri("https://bdu.fstec.ru/");
|
||||
options.DataArchivePath = "files/documents/vulxml.zip";
|
||||
options.MaxVulnerabilitiesPerFetch = 25;
|
||||
options.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
var cacheRoot = Path.Combine(Path.GetTempPath(), "stellaops-tests", _fixture.Database.DatabaseNamespace.DatabaseName, "ru-bdu");
|
||||
Directory.CreateDirectory(cacheRoot);
|
||||
options.CacheDirectory = cacheRoot;
|
||||
});
|
||||
|
||||
services.Configure<HttpClientFactoryOptions>(RuBduOptions.HttpClientName, options =>
|
||||
{
|
||||
options.HttpMessageHandlerBuilderActions.Add(builder => builder.PrimaryHandler = harness.Handler);
|
||||
});
|
||||
});
|
||||
|
||||
_harness = harness;
|
||||
return harness;
|
||||
}
|
||||
|
||||
private static HttpResponseMessage BuildArchiveResponse()
|
||||
{
|
||||
var archiveBytes = CreateArchiveBytes();
|
||||
var response = new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{
|
||||
Content = new ByteArrayContent(archiveBytes),
|
||||
};
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
|
||||
response.Content.Headers.LastModified = new DateTimeOffset(2025, 10, 14, 9, 30, 0, TimeSpan.Zero);
|
||||
response.Content.Headers.ContentLength = archiveBytes.Length;
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<string> BuildDocumentsSnapshotAsync(IServiceProvider provider, IReadOnlyCollection<Guid> documentIds)
|
||||
{
|
||||
var documentStore = provider.GetRequiredService<IDocumentStore>();
|
||||
var records = new List<object>(documentIds.Count);
|
||||
|
||||
foreach (var documentId in documentIds)
|
||||
{
|
||||
var record = await documentStore.FindAsync(documentId, CancellationToken.None);
|
||||
if (record is null)
|
||||
{
|
||||
var existing = await _fixture.Database
|
||||
.GetCollection<BsonDocument>("documents")
|
||||
.Find(Builders<BsonDocument>.Filter.Empty)
|
||||
.Project(Builders<BsonDocument>.Projection.Include("Uri"))
|
||||
.ToListAsync(CancellationToken.None);
|
||||
var uris = existing
|
||||
.Select(document => document.GetValue("Uri", BsonValue.Create(string.Empty)).AsString)
|
||||
.ToArray();
|
||||
throw new XunitException($"Document id not found: {documentId}. Known URIs: {string.Join(", ", uris)}");
|
||||
}
|
||||
|
||||
records.Add(new
|
||||
{
|
||||
record.Uri,
|
||||
record.Status,
|
||||
record.Sha256,
|
||||
Metadata = record.Metadata is null
|
||||
? null
|
||||
: record.Metadata
|
||||
.OrderBy(static pair => pair.Key, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(static pair => pair.Key, static pair => pair.Value, StringComparer.OrdinalIgnoreCase)
|
||||
});
|
||||
}
|
||||
|
||||
var ordered = records
|
||||
.OrderBy(static entry => entry?.GetType().GetProperty("Uri")?.GetValue(entry)?.ToString(), StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
|
||||
return SnapshotSerializer.ToSnapshot(ordered);
|
||||
}
|
||||
|
||||
private async Task<string> BuildDtoSnapshotAsync(IServiceProvider provider)
|
||||
{
|
||||
var dtoStore = provider.GetRequiredService<IDtoStore>();
|
||||
var documentStore = provider.GetRequiredService<IDocumentStore>();
|
||||
var records = await dtoStore.GetBySourceAsync(RuBduConnectorPlugin.SourceName, 25, CancellationToken.None);
|
||||
|
||||
var entries = new List<object>(records.Count);
|
||||
foreach (var record in records.OrderBy(static r => r.DocumentId))
|
||||
{
|
||||
var document = await documentStore.FindAsync(record.DocumentId, CancellationToken.None);
|
||||
Assert.NotNull(document);
|
||||
|
||||
var payload = BsonTypeMapper.MapToDotNetValue(record.Payload);
|
||||
entries.Add(new
|
||||
{
|
||||
DocumentUri = document!.Uri,
|
||||
record.SchemaVersion,
|
||||
Payload = payload,
|
||||
});
|
||||
}
|
||||
|
||||
return SnapshotSerializer.ToSnapshot(entries.OrderBy(static entry => entry.GetType().GetProperty("DocumentUri")!.GetValue(entry)?.ToString(), StringComparer.Ordinal).ToArray());
|
||||
}
|
||||
|
||||
private async Task<string> BuildAdvisoriesSnapshotAsync(IServiceProvider provider)
|
||||
{
|
||||
var advisoryStore = provider.GetRequiredService<IAdvisoryStore>();
|
||||
var advisories = await advisoryStore.GetRecentAsync(25, CancellationToken.None);
|
||||
var ordered = advisories
|
||||
.OrderBy(static advisory => advisory.AdvisoryKey, StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
return SnapshotSerializer.ToSnapshot(ordered);
|
||||
}
|
||||
|
||||
private async Task<string> BuildStateSnapshotAsync(IServiceProvider provider)
|
||||
{
|
||||
var stateRepository = provider.GetRequiredService<ISourceStateRepository>();
|
||||
var state = await stateRepository.TryGetAsync(RuBduConnectorPlugin.SourceName, CancellationToken.None);
|
||||
Assert.NotNull(state);
|
||||
|
||||
var cursor = state!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromBson(state.Cursor);
|
||||
var snapshot = new
|
||||
{
|
||||
PendingDocuments = cursor.PendingDocuments.Select(static guid => guid.ToString()).OrderBy(static id => id, StringComparer.Ordinal).ToArray(),
|
||||
PendingMappings = cursor.PendingMappings.Select(static guid => guid.ToString()).OrderBy(static id => id, StringComparer.Ordinal).ToArray(),
|
||||
LastSuccessfulFetch = cursor.LastSuccessfulFetch?.ToUniversalTime().ToString("O"),
|
||||
};
|
||||
|
||||
return SnapshotSerializer.ToSnapshot(snapshot);
|
||||
}
|
||||
|
||||
private static string BuildRequestsSnapshot(IReadOnlyCollection<CannedHttpMessageHandler.CannedRequestRecord> requests)
|
||||
{
|
||||
var ordered = requests
|
||||
.Select(record => new
|
||||
{
|
||||
Method = record.Method.Method,
|
||||
Uri = record.Uri.ToString(),
|
||||
Headers = record.Headers
|
||||
.OrderBy(static kvp => kvp.Key, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(static kvp => kvp.Key, static kvp => kvp.Value, StringComparer.OrdinalIgnoreCase),
|
||||
})
|
||||
.OrderBy(static entry => entry.Uri, StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
|
||||
return SnapshotSerializer.ToSnapshot(ordered);
|
||||
}
|
||||
|
||||
private static string ReadFixtureText(string filename)
|
||||
{
|
||||
var path = GetSourceFixturePath(filename);
|
||||
return File.ReadAllText(path, Encoding.UTF8);
|
||||
}
|
||||
|
||||
private static byte[] CreateArchiveBytes()
|
||||
{
|
||||
var xml = ReadFixtureText("export-sample.xml");
|
||||
using var buffer = new MemoryStream();
|
||||
using (var archive = new ZipArchive(buffer, ZipArchiveMode.Create, leaveOpen: true))
|
||||
{
|
||||
var entry = archive.CreateEntry("export/export.xml", CompressionLevel.NoCompression);
|
||||
entry.LastWriteTime = new DateTimeOffset(2025, 10, 14, 9, 0, 0, TimeSpan.Zero);
|
||||
using var entryStream = entry.Open();
|
||||
using var writer = new StreamWriter(entryStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
|
||||
writer.Write(xml);
|
||||
}
|
||||
|
||||
return buffer.ToArray();
|
||||
}
|
||||
|
||||
private static bool ShouldUpdateFixtures()
|
||||
=> !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(UpdateFixturesVariable));
|
||||
|
||||
private static void WriteOrAssertSnapshot(string content, string filename)
|
||||
{
|
||||
var path = GetSourceFixturePath(filename);
|
||||
if (ShouldUpdateFixtures())
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
|
||||
File.WriteAllText(path, content, Encoding.UTF8);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(File.Exists(path), $"Snapshot '{filename}' is missing. Run {UpdateFixturesVariable}=1 dotnet test to regenerate fixtures.");
|
||||
var expected = File.ReadAllText(path, Encoding.UTF8);
|
||||
Assert.Equal(expected, content);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetSourceFixturePath(string relativeName)
|
||||
=> Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "Fixtures", relativeName));
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Concelier.Connector.Common.Testing;
|
||||
using StellaOps.Concelier.Connector.Ru.Bdu;
|
||||
using StellaOps.Concelier.Connector.Ru.Bdu.Configuration;
|
||||
using StellaOps.Concelier.Connector.Ru.Bdu.Internal;
|
||||
using StellaOps.Concelier.Storage.Mongo;
|
||||
using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Documents;
|
||||
using StellaOps.Concelier.Storage.Mongo.Dtos;
|
||||
using StellaOps.Concelier.Testing;
|
||||
using StellaOps.Cryptography.DependencyInjection;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ru.Bdu.Tests;
|
||||
|
||||
[Collection("mongo-fixture")]
|
||||
public sealed class RuBduConnectorSnapshotTests : IAsyncLifetime
|
||||
{
|
||||
private const string UpdateFixturesVariable = "UPDATE_BDU_FIXTURES";
|
||||
private static readonly Uri ArchiveUri = new("https://bdu.fstec.ru/files/documents/vulxml.zip");
|
||||
|
||||
private readonly MongoIntegrationFixture _fixture;
|
||||
private ConnectorTestHarness? _harness;
|
||||
|
||||
public RuBduConnectorSnapshotTests(MongoIntegrationFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FetchParseMap_ProducesDeterministicSnapshots()
|
||||
{
|
||||
var harness = await EnsureHarnessAsync();
|
||||
harness.Handler.AddResponse(ArchiveUri, BuildArchiveResponse);
|
||||
|
||||
var connector = harness.ServiceProvider.GetRequiredService<RuBduConnector>();
|
||||
await connector.FetchAsync(harness.ServiceProvider, CancellationToken.None);
|
||||
|
||||
var stateRepository = harness.ServiceProvider.GetRequiredService<ISourceStateRepository>();
|
||||
var initialState = await stateRepository.TryGetAsync(RuBduConnectorPlugin.SourceName, CancellationToken.None);
|
||||
Assert.NotNull(initialState);
|
||||
var cursorBeforeParse = initialState!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromBson(initialState.Cursor);
|
||||
Assert.NotEmpty(cursorBeforeParse.PendingDocuments);
|
||||
var expectedDocumentIds = cursorBeforeParse.PendingDocuments.ToArray();
|
||||
|
||||
await connector.ParseAsync(harness.ServiceProvider, CancellationToken.None);
|
||||
await connector.MapAsync(harness.ServiceProvider, CancellationToken.None);
|
||||
|
||||
var documentsCollection = _fixture.Database.GetCollection<BsonDocument>(MongoStorageDefaults.Collections.Document);
|
||||
var documentCount = await documentsCollection.CountDocumentsAsync(Builders<BsonDocument>.Filter.Empty);
|
||||
Assert.True(documentCount > 0, "Expected persisted documents after map stage");
|
||||
|
||||
var documentsSnapshot = await BuildDocumentsSnapshotAsync(harness.ServiceProvider, expectedDocumentIds);
|
||||
WriteOrAssertSnapshot(documentsSnapshot, "ru-bdu-documents.snapshot.json");
|
||||
|
||||
var dtoSnapshot = await BuildDtoSnapshotAsync(harness.ServiceProvider);
|
||||
WriteOrAssertSnapshot(dtoSnapshot, "ru-bdu-dtos.snapshot.json");
|
||||
|
||||
var advisoriesSnapshot = await BuildAdvisoriesSnapshotAsync(harness.ServiceProvider);
|
||||
WriteOrAssertSnapshot(advisoriesSnapshot, "ru-bdu-advisories.snapshot.json");
|
||||
|
||||
var stateSnapshot = await BuildStateSnapshotAsync(harness.ServiceProvider);
|
||||
WriteOrAssertSnapshot(stateSnapshot, "ru-bdu-state.snapshot.json");
|
||||
|
||||
var requestsSnapshot = BuildRequestsSnapshot(harness.Handler.Requests);
|
||||
WriteOrAssertSnapshot(requestsSnapshot, "ru-bdu-requests.snapshot.json");
|
||||
|
||||
harness.Handler.AssertNoPendingResponses();
|
||||
}
|
||||
|
||||
public Task InitializeAsync() => Task.CompletedTask;
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
if (_harness is not null)
|
||||
{
|
||||
await _harness.DisposeAsync();
|
||||
_harness = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<ConnectorTestHarness> EnsureHarnessAsync()
|
||||
{
|
||||
if (_harness is not null)
|
||||
{
|
||||
return _harness;
|
||||
}
|
||||
|
||||
var initialTime = new DateTimeOffset(2025, 10, 14, 8, 0, 0, TimeSpan.Zero);
|
||||
var harness = new ConnectorTestHarness(_fixture, initialTime, RuBduOptions.HttpClientName);
|
||||
await harness.EnsureServiceProviderAsync(services =>
|
||||
{
|
||||
services.AddLogging(builder =>
|
||||
{
|
||||
builder.ClearProviders();
|
||||
builder.AddProvider(NullLoggerProvider.Instance);
|
||||
});
|
||||
|
||||
services.AddStellaOpsCrypto();
|
||||
services.AddRuBduConnector(options =>
|
||||
{
|
||||
options.BaseAddress = new Uri("https://bdu.fstec.ru/");
|
||||
options.DataArchivePath = "files/documents/vulxml.zip";
|
||||
options.MaxVulnerabilitiesPerFetch = 25;
|
||||
options.RequestTimeout = TimeSpan.FromSeconds(30);
|
||||
var cacheRoot = Path.Combine(Path.GetTempPath(), "stellaops-tests", _fixture.Database.DatabaseNamespace.DatabaseName, "ru-bdu");
|
||||
Directory.CreateDirectory(cacheRoot);
|
||||
options.CacheDirectory = cacheRoot;
|
||||
});
|
||||
|
||||
services.Configure<HttpClientFactoryOptions>(RuBduOptions.HttpClientName, options =>
|
||||
{
|
||||
options.HttpMessageHandlerBuilderActions.Add(builder => builder.PrimaryHandler = harness.Handler);
|
||||
});
|
||||
});
|
||||
|
||||
_harness = harness;
|
||||
return harness;
|
||||
}
|
||||
|
||||
private static HttpResponseMessage BuildArchiveResponse()
|
||||
{
|
||||
var archiveBytes = CreateArchiveBytes();
|
||||
var response = new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{
|
||||
Content = new ByteArrayContent(archiveBytes),
|
||||
};
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
|
||||
response.Content.Headers.LastModified = new DateTimeOffset(2025, 10, 14, 9, 30, 0, TimeSpan.Zero);
|
||||
response.Content.Headers.ContentLength = archiveBytes.Length;
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<string> BuildDocumentsSnapshotAsync(IServiceProvider provider, IReadOnlyCollection<Guid> documentIds)
|
||||
{
|
||||
var documentStore = provider.GetRequiredService<IDocumentStore>();
|
||||
var records = new List<object>(documentIds.Count);
|
||||
|
||||
foreach (var documentId in documentIds)
|
||||
{
|
||||
var record = await documentStore.FindAsync(documentId, CancellationToken.None);
|
||||
if (record is null)
|
||||
{
|
||||
var existing = await _fixture.Database
|
||||
.GetCollection<BsonDocument>("documents")
|
||||
.Find(Builders<BsonDocument>.Filter.Empty)
|
||||
.Project(Builders<BsonDocument>.Projection.Include("Uri"))
|
||||
.ToListAsync(CancellationToken.None);
|
||||
var uris = existing
|
||||
.Select(document => document.GetValue("Uri", BsonValue.Create(string.Empty)).AsString)
|
||||
.ToArray();
|
||||
throw new XunitException($"Document id not found: {documentId}. Known URIs: {string.Join(", ", uris)}");
|
||||
}
|
||||
|
||||
records.Add(new
|
||||
{
|
||||
record.Uri,
|
||||
record.Status,
|
||||
record.Sha256,
|
||||
Metadata = record.Metadata is null
|
||||
? null
|
||||
: record.Metadata
|
||||
.OrderBy(static pair => pair.Key, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(static pair => pair.Key, static pair => pair.Value, StringComparer.OrdinalIgnoreCase)
|
||||
});
|
||||
}
|
||||
|
||||
var ordered = records
|
||||
.OrderBy(static entry => entry?.GetType().GetProperty("Uri")?.GetValue(entry)?.ToString(), StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
|
||||
return SnapshotSerializer.ToSnapshot(ordered);
|
||||
}
|
||||
|
||||
private async Task<string> BuildDtoSnapshotAsync(IServiceProvider provider)
|
||||
{
|
||||
var dtoStore = provider.GetRequiredService<IDtoStore>();
|
||||
var documentStore = provider.GetRequiredService<IDocumentStore>();
|
||||
var records = await dtoStore.GetBySourceAsync(RuBduConnectorPlugin.SourceName, 25, CancellationToken.None);
|
||||
|
||||
var entries = new List<object>(records.Count);
|
||||
foreach (var record in records.OrderBy(static r => r.DocumentId))
|
||||
{
|
||||
var document = await documentStore.FindAsync(record.DocumentId, CancellationToken.None);
|
||||
Assert.NotNull(document);
|
||||
|
||||
var payload = BsonTypeMapper.MapToDotNetValue(record.Payload);
|
||||
entries.Add(new
|
||||
{
|
||||
DocumentUri = document!.Uri,
|
||||
record.SchemaVersion,
|
||||
Payload = payload,
|
||||
});
|
||||
}
|
||||
|
||||
return SnapshotSerializer.ToSnapshot(entries.OrderBy(static entry => entry.GetType().GetProperty("DocumentUri")!.GetValue(entry)?.ToString(), StringComparer.Ordinal).ToArray());
|
||||
}
|
||||
|
||||
private async Task<string> BuildAdvisoriesSnapshotAsync(IServiceProvider provider)
|
||||
{
|
||||
var advisoryStore = provider.GetRequiredService<IAdvisoryStore>();
|
||||
var advisories = await advisoryStore.GetRecentAsync(25, CancellationToken.None);
|
||||
var ordered = advisories
|
||||
.OrderBy(static advisory => advisory.AdvisoryKey, StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
return SnapshotSerializer.ToSnapshot(ordered);
|
||||
}
|
||||
|
||||
private async Task<string> BuildStateSnapshotAsync(IServiceProvider provider)
|
||||
{
|
||||
var stateRepository = provider.GetRequiredService<ISourceStateRepository>();
|
||||
var state = await stateRepository.TryGetAsync(RuBduConnectorPlugin.SourceName, CancellationToken.None);
|
||||
Assert.NotNull(state);
|
||||
|
||||
var cursor = state!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromBson(state.Cursor);
|
||||
var snapshot = new
|
||||
{
|
||||
PendingDocuments = cursor.PendingDocuments.Select(static guid => guid.ToString()).OrderBy(static id => id, StringComparer.Ordinal).ToArray(),
|
||||
PendingMappings = cursor.PendingMappings.Select(static guid => guid.ToString()).OrderBy(static id => id, StringComparer.Ordinal).ToArray(),
|
||||
LastSuccessfulFetch = cursor.LastSuccessfulFetch?.ToUniversalTime().ToString("O"),
|
||||
};
|
||||
|
||||
return SnapshotSerializer.ToSnapshot(snapshot);
|
||||
}
|
||||
|
||||
private static string BuildRequestsSnapshot(IReadOnlyCollection<CannedHttpMessageHandler.CannedRequestRecord> requests)
|
||||
{
|
||||
var ordered = requests
|
||||
.Select(record => new
|
||||
{
|
||||
Method = record.Method.Method,
|
||||
Uri = record.Uri.ToString(),
|
||||
Headers = record.Headers
|
||||
.OrderBy(static kvp => kvp.Key, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(static kvp => kvp.Key, static kvp => kvp.Value, StringComparer.OrdinalIgnoreCase),
|
||||
})
|
||||
.OrderBy(static entry => entry.Uri, StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
|
||||
return SnapshotSerializer.ToSnapshot(ordered);
|
||||
}
|
||||
|
||||
private static string ReadFixtureText(string filename)
|
||||
{
|
||||
var path = GetSourceFixturePath(filename);
|
||||
return File.ReadAllText(path, Encoding.UTF8);
|
||||
}
|
||||
|
||||
private static byte[] CreateArchiveBytes()
|
||||
{
|
||||
var xml = ReadFixtureText("export-sample.xml");
|
||||
using var buffer = new MemoryStream();
|
||||
using (var archive = new ZipArchive(buffer, ZipArchiveMode.Create, leaveOpen: true))
|
||||
{
|
||||
var entry = archive.CreateEntry("export/export.xml", CompressionLevel.NoCompression);
|
||||
entry.LastWriteTime = new DateTimeOffset(2025, 10, 14, 9, 0, 0, TimeSpan.Zero);
|
||||
using var entryStream = entry.Open();
|
||||
using var writer = new StreamWriter(entryStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
|
||||
writer.Write(xml);
|
||||
}
|
||||
|
||||
return buffer.ToArray();
|
||||
}
|
||||
|
||||
private static bool ShouldUpdateFixtures()
|
||||
=> !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(UpdateFixturesVariable));
|
||||
|
||||
private static void WriteOrAssertSnapshot(string content, string filename)
|
||||
{
|
||||
var path = GetSourceFixturePath(filename);
|
||||
if (ShouldUpdateFixtures())
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
|
||||
File.WriteAllText(path, NormalizeLineEndings(content), Encoding.UTF8);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(File.Exists(path), $"Snapshot '{filename}' is missing. Run {UpdateFixturesVariable}=1 dotnet test to regenerate fixtures.");
|
||||
var expected = File.ReadAllText(path, Encoding.UTF8);
|
||||
Assert.Equal(NormalizeLineEndings(expected), NormalizeLineEndings(content));
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetSourceFixturePath(string relativeName)
|
||||
=> Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "Fixtures", relativeName));
|
||||
|
||||
private static string NormalizeLineEndings(string value)
|
||||
{
|
||||
var normalized = value.Replace("\r\n", "\n", StringComparison.Ordinal);
|
||||
return normalized.Length > 0 && normalized[0] == '\ufeff'
|
||||
? normalized[1..]
|
||||
: normalized;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,5 +10,6 @@
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Models/StellaOps.Concelier.Models.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Normalization/StellaOps.Concelier.Normalization.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Connector.Ru.Bdu/StellaOps.Concelier.Connector.Ru.Bdu.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography.DependencyInjection/StellaOps.Cryptography.DependencyInjection.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,495 +1,501 @@
|
||||
[
|
||||
{
|
||||
"advisoryKey": "BDU:2025-01001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "SampleVendor SampleGateway",
|
||||
"platform": "Energy, ICS",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": "2.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": false,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": ">= 2.0",
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": "2.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false,
|
||||
"style": "greaterThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": null
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-range",
|
||||
"value": "SampleVendor SampleGateway >= 2.0 All platforms",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": ">= 2.0",
|
||||
"rangeKind": "semver"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "gte",
|
||||
"min": "2.0",
|
||||
"minInclusive": true,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": null,
|
||||
"notes": "SampleVendor SampleGateway >= 2.0 All platforms"
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-status",
|
||||
"value": "patch_available",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "fixed"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package",
|
||||
"value": "SampleVendor SampleGateway >= 2.0 All platforms",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "SampleVendor SampleSCADA",
|
||||
"platform": "Energy, ICS",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": "4.2",
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": false,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": "<= 4.2",
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": null,
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": "4.2",
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "lessThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": null
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-range",
|
||||
"value": "SampleVendor SampleSCADA <= 4.2",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": "<= 4.2",
|
||||
"rangeKind": "semver"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "lte",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": "4.2",
|
||||
"maxInclusive": true,
|
||||
"value": null,
|
||||
"notes": "SampleVendor SampleSCADA <= 4.2"
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-status",
|
||||
"value": "patch_available",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "fixed"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package",
|
||||
"value": "SampleVendor SampleSCADA <= 4.2",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"BDU:2025-01001",
|
||||
"CVE-2025-0101"
|
||||
],
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 8.5,
|
||||
"baseSeverity": "high",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H",
|
||||
"version": "3.1"
|
||||
},
|
||||
{
|
||||
"baseScore": 6.4,
|
||||
"baseSeverity": "medium",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H",
|
||||
"version": "4.0"
|
||||
}
|
||||
],
|
||||
"exploitKnown": true,
|
||||
"language": "ru",
|
||||
"modified": "2025-09-22T00:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "advisory",
|
||||
"value": "BDU:2025-01001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-09-20T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://bdu.fstec.ru/vul/2025-01001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "bdu",
|
||||
"summary": null,
|
||||
"url": "https://bdu.fstec.ru/vul/2025-01001"
|
||||
},
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://cert.gov.ru/materialy/uyazvimosti/2025-01001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-nkcki",
|
||||
"summary": null,
|
||||
"url": "https://cert.gov.ru/materialy/uyazvimosti/2025-01001"
|
||||
},
|
||||
{
|
||||
"kind": "cwe",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://cwe.mitre.org/data/definitions/321.html",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "cwe",
|
||||
"summary": "Use of Hard-coded Cryptographic Key",
|
||||
"url": "https://cwe.mitre.org/data/definitions/321.html"
|
||||
},
|
||||
{
|
||||
"kind": "external",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example/advisories/sample-scada",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://vendor.example/advisories/sample-scada"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "Authenticated RCE in Sample SCADA",
|
||||
"title": "Authenticated RCE in Sample SCADA"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "BDU:2024-00011",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "cpe",
|
||||
"identifier": "LegacyPanel",
|
||||
"platform": "Software",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": "2.5",
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": false,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": "<= 2.5",
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": null,
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": "2.5",
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "lessThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": null
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-range",
|
||||
"value": "LegacyPanel 1.0 - 2.5",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": "<= 2.5",
|
||||
"rangeKind": "semver"
|
||||
},
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": "1.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": false,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": ">= 1.0",
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": "1.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false,
|
||||
"style": "greaterThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": null
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-range",
|
||||
"value": "LegacyPanel 1.0 - 2.5",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": ">= 1.0",
|
||||
"rangeKind": "semver"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "gte",
|
||||
"min": "1.0",
|
||||
"minInclusive": true,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": null,
|
||||
"notes": "LegacyPanel 1.0 - 2.5"
|
||||
},
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "lte",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": "2.5",
|
||||
"maxInclusive": true,
|
||||
"value": null,
|
||||
"notes": "LegacyPanel 1.0 - 2.5"
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-status",
|
||||
"value": "affected",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "affected"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package",
|
||||
"value": "LegacyPanel 1.0 - 2.5",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"BDU:2024-00011"
|
||||
],
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 8.8,
|
||||
"baseSeverity": "high",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
|
||||
"version": "3.1"
|
||||
}
|
||||
],
|
||||
"exploitKnown": true,
|
||||
"language": "ru",
|
||||
"modified": "2024-08-02T00:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "advisory",
|
||||
"value": "BDU:2024-00011",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2024-08-01T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://bdu.fstec.ru/vul/2024-00011",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "bdu",
|
||||
"summary": null,
|
||||
"url": "https://bdu.fstec.ru/vul/2024-00011"
|
||||
},
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://cert.gov.ru/materialy/uyazvimosti/2024-00011",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-nkcki",
|
||||
"summary": null,
|
||||
"url": "https://cert.gov.ru/materialy/uyazvimosti/2024-00011"
|
||||
}
|
||||
],
|
||||
"severity": "high",
|
||||
"summary": "Legacy panel overflow",
|
||||
"title": "Legacy panel overflow"
|
||||
}
|
||||
[
|
||||
{
|
||||
"advisoryKey": "BDU:2025-01001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "SampleVendor SampleGateway",
|
||||
"platform": "Energy, ICS",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": "2.0.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": false,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": ">= 2.0.0",
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": "2.0.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false,
|
||||
"style": "greaterThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": null
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-range",
|
||||
"value": "SampleVendor SampleGateway >= 2.0 All platforms",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": ">= 2.0.0",
|
||||
"rangeKind": "semver"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "gte",
|
||||
"min": "2.0.0",
|
||||
"minInclusive": true,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": null,
|
||||
"notes": "SampleVendor SampleGateway >= 2.0 All platforms"
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-status",
|
||||
"value": "patch_available",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "fixed"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package",
|
||||
"value": "SampleVendor SampleGateway >= 2.0 All platforms",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ics-vendor",
|
||||
"identifier": "SampleVendor SampleSCADA",
|
||||
"platform": "Energy, ICS",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": "4.2.0",
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": false,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": "<= 4.2.0",
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": null,
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": "4.2.0",
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "lessThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": null
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-range",
|
||||
"value": "SampleVendor SampleSCADA <= 4.2",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": "<= 4.2.0",
|
||||
"rangeKind": "semver"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "lte",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": "4.2.0",
|
||||
"maxInclusive": true,
|
||||
"value": null,
|
||||
"notes": "SampleVendor SampleSCADA <= 4.2"
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-status",
|
||||
"value": "patch_available",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "fixed"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package",
|
||||
"value": "SampleVendor SampleSCADA <= 4.2",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"BDU:2025-01001",
|
||||
"CVE-2025-0101"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 8.5,
|
||||
"baseSeverity": "high",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H",
|
||||
"version": "3.1"
|
||||
},
|
||||
{
|
||||
"baseScore": 6.4,
|
||||
"baseSeverity": "medium",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H",
|
||||
"version": "4.0"
|
||||
}
|
||||
],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": true,
|
||||
"language": "ru",
|
||||
"modified": "2025-09-22T00:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "advisory",
|
||||
"value": "BDU:2025-01001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2025-09-20T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://bdu.fstec.ru/vul/2025-01001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "bdu",
|
||||
"summary": null,
|
||||
"url": "https://bdu.fstec.ru/vul/2025-01001"
|
||||
},
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://cert.gov.ru/materialy/uyazvimosti/2025-01001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-nkcki",
|
||||
"summary": null,
|
||||
"url": "https://cert.gov.ru/materialy/uyazvimosti/2025-01001"
|
||||
},
|
||||
{
|
||||
"kind": "cwe",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://cwe.mitre.org/data/definitions/321.html",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "cwe",
|
||||
"summary": "Use of Hard-coded Cryptographic Key",
|
||||
"url": "https://cwe.mitre.org/data/definitions/321.html"
|
||||
},
|
||||
{
|
||||
"kind": "external",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://vendor.example/advisories/sample-scada",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": null,
|
||||
"summary": null,
|
||||
"url": "https://vendor.example/advisories/sample-scada"
|
||||
}
|
||||
],
|
||||
"severity": "critical",
|
||||
"summary": "Authenticated RCE in Sample SCADA",
|
||||
"title": "Authenticated RCE in Sample SCADA"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "BDU:2024-00011",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "cpe",
|
||||
"identifier": "LegacyPanel",
|
||||
"platform": "Software",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": null,
|
||||
"lastAffectedVersion": "2.5.0",
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": false,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": "<= 2.5.0",
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": null,
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": "2.5.0",
|
||||
"lastAffectedInclusive": true,
|
||||
"style": "lessThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": null
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-range",
|
||||
"value": "LegacyPanel 1.0 - 2.5",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": "<= 2.5.0",
|
||||
"rangeKind": "semver"
|
||||
},
|
||||
{
|
||||
"fixedVersion": null,
|
||||
"introducedVersion": "1.0.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": false,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": ">= 1.0.0",
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": "1.0.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false,
|
||||
"style": "greaterThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": null
|
||||
},
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-range",
|
||||
"value": "LegacyPanel 1.0 - 2.5",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].versionranges[]"
|
||||
]
|
||||
},
|
||||
"rangeExpression": ">= 1.0.0",
|
||||
"rangeKind": "semver"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "gte",
|
||||
"min": "1.0.0",
|
||||
"minInclusive": true,
|
||||
"max": null,
|
||||
"maxInclusive": null,
|
||||
"value": null,
|
||||
"notes": "LegacyPanel 1.0 - 2.5"
|
||||
},
|
||||
{
|
||||
"scheme": "semver",
|
||||
"type": "lte",
|
||||
"min": null,
|
||||
"minInclusive": null,
|
||||
"max": "2.5.0",
|
||||
"maxInclusive": true,
|
||||
"value": null,
|
||||
"notes": "LegacyPanel 1.0 - 2.5"
|
||||
}
|
||||
],
|
||||
"statuses": [
|
||||
{
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package-status",
|
||||
"value": "affected",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[].statuses[]"
|
||||
]
|
||||
},
|
||||
"status": "affected"
|
||||
}
|
||||
],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "package",
|
||||
"value": "LegacyPanel 1.0 - 2.5",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"affectedpackages[]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"BDU:2024-00011"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [
|
||||
{
|
||||
"baseScore": 8.8,
|
||||
"baseSeverity": "high",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "cvss",
|
||||
"value": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"cvssmetrics[]"
|
||||
]
|
||||
},
|
||||
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
|
||||
"version": "3.1"
|
||||
}
|
||||
],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": true,
|
||||
"language": "ru",
|
||||
"modified": "2024-08-02T00:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "ru-nkcki",
|
||||
"kind": "advisory",
|
||||
"value": "BDU:2024-00011",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"advisory"
|
||||
]
|
||||
}
|
||||
],
|
||||
"published": "2024-08-01T00:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://bdu.fstec.ru/vul/2024-00011",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "bdu",
|
||||
"summary": null,
|
||||
"url": "https://bdu.fstec.ru/vul/2024-00011"
|
||||
},
|
||||
{
|
||||
"kind": "details",
|
||||
"provenance": {
|
||||
"source": "ru-nkcki",
|
||||
"kind": "reference",
|
||||
"value": "https://cert.gov.ru/materialy/uyazvimosti/2024-00011",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2025-10-12T00:01:00+00:00",
|
||||
"fieldMask": [
|
||||
"references[]"
|
||||
]
|
||||
},
|
||||
"sourceTag": "ru-nkcki",
|
||||
"summary": null,
|
||||
"url": "https://cert.gov.ru/materialy/uyazvimosti/2024-00011"
|
||||
}
|
||||
],
|
||||
"severity": "high",
|
||||
"summary": "Legacy panel overflow",
|
||||
"title": "Legacy panel overflow"
|
||||
}
|
||||
]
|
||||
@@ -19,12 +19,13 @@ using StellaOps.Concelier.Connector.Common.Http;
|
||||
using StellaOps.Concelier.Connector.Common.Testing;
|
||||
using StellaOps.Concelier.Connector.Ru.Nkcki;
|
||||
using StellaOps.Concelier.Connector.Ru.Nkcki.Configuration;
|
||||
using StellaOps.Concelier.Storage.Mongo;
|
||||
using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Documents;
|
||||
using StellaOps.Concelier.Testing;
|
||||
using StellaOps.Concelier.Models;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Concelier.Storage.Mongo;
|
||||
using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Documents;
|
||||
using StellaOps.Concelier.Testing;
|
||||
using StellaOps.Concelier.Models;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Cryptography.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ru.Nkcki.Tests;
|
||||
@@ -123,14 +124,15 @@ public sealed class RuNkckiConnectorTests : IAsyncLifetime
|
||||
services.AddLogging(builder => builder.AddProvider(NullLoggerProvider.Instance));
|
||||
services.AddSingleton<TimeProvider>(_timeProvider);
|
||||
|
||||
services.AddMongoStorage(options =>
|
||||
{
|
||||
options.ConnectionString = _fixture.Runner.ConnectionString;
|
||||
options.DatabaseName = _fixture.Database.DatabaseNamespace.DatabaseName;
|
||||
options.CommandTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
services.AddSourceCommon();
|
||||
services.AddMongoStorage(options =>
|
||||
{
|
||||
options.ConnectionString = _fixture.Runner.ConnectionString;
|
||||
options.DatabaseName = _fixture.Database.DatabaseNamespace.DatabaseName;
|
||||
options.CommandTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
services.AddStellaOpsCrypto();
|
||||
services.AddSourceCommon();
|
||||
services.AddRuNkckiConnector(options =>
|
||||
{
|
||||
options.BaseAddress = new Uri("https://cert.gov.ru/");
|
||||
|
||||
@@ -10,5 +10,6 @@
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Models/StellaOps.Concelier.Models.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Normalization/StellaOps.Concelier.Normalization.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/StellaOps.Concelier.Connector.Ru.Nkcki.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography.DependencyInjection/StellaOps.Cryptography.DependencyInjection.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Connector.StellaOpsMirror/StellaOps.Concelier.Connector.StellaOpsMirror.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography/StellaOps.Cryptography.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography.DependencyInjection/StellaOps.Cryptography.DependencyInjection.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Fixtures\**\*.json" CopyToOutputDirectory="Always" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -23,7 +23,8 @@ using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Documents;
|
||||
using StellaOps.Concelier.Storage.Mongo.Dtos;
|
||||
using StellaOps.Concelier.Testing;
|
||||
using StellaOps.Cryptography;
|
||||
using StellaOps.Cryptography;
|
||||
using StellaOps.Cryptography.DependencyInjection;
|
||||
using StellaOps.Concelier.Models;
|
||||
using Xunit;
|
||||
|
||||
@@ -287,9 +288,7 @@ public sealed class StellaOpsMirrorConnectorTests : IAsyncLifetime
|
||||
options.CommandTimeout = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
services.AddSingleton<DefaultCryptoProvider>();
|
||||
services.AddSingleton<ICryptoProvider>(sp => sp.GetRequiredService<DefaultCryptoProvider>());
|
||||
services.AddSingleton<ICryptoProviderRegistry>(sp => new CryptoProviderRegistry(sp.GetServices<ICryptoProvider>()));
|
||||
services.AddStellaOpsCrypto();
|
||||
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using MongoDB.Bson;
|
||||
using StellaOps.Concelier.Models;
|
||||
@@ -20,23 +21,24 @@ public sealed class CiscoMapperTests
|
||||
var published = new DateTimeOffset(2025, 10, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
var updated = published.AddDays(1);
|
||||
|
||||
var dto = new CiscoAdvisoryDto(
|
||||
AdvisoryId: "CISCO-SA-TEST",
|
||||
Title: "Test Advisory",
|
||||
Summary: "Sample summary",
|
||||
Severity: "High",
|
||||
var dto = new CiscoAdvisoryDto(
|
||||
AdvisoryId: "CISCO-SA-TEST",
|
||||
Title: "Test Advisory",
|
||||
Summary: "Sample summary",
|
||||
Severity: "High",
|
||||
Published: published,
|
||||
Updated: updated,
|
||||
PublicationUrl: "https://example.com/advisory",
|
||||
CsafUrl: "https://sec.cloudapps.cisco.com/csaf/test.json",
|
||||
CvrfUrl: "https://example.com/cvrf.xml",
|
||||
CvssBaseScore: 9.8,
|
||||
Cves: new List<string> { "CVE-2024-0001" },
|
||||
BugIds: new List<string> { "BUG123" },
|
||||
Products: new List<CiscoAffectedProductDto>
|
||||
{
|
||||
new("Cisco Widget", "PID-1", "1.2.3", new [] { AffectedPackageStatusCatalog.KnownAffected })
|
||||
});
|
||||
CvssBaseScore: 9.8,
|
||||
Cves: new List<string> { "CVE-2024-0001" },
|
||||
BugIds: new List<string> { "BUG123" },
|
||||
Products: new List<CiscoAffectedProductDto>
|
||||
{
|
||||
new("Cisco Widget", "PID-1", "1.2.3", new [] { AffectedPackageStatusCatalog.KnownAffected }),
|
||||
new("Cisco Router", "PID-2", ">=1.0.0 <1.4.0", new [] { AffectedPackageStatusCatalog.KnownAffected })
|
||||
});
|
||||
|
||||
var document = new DocumentRecord(
|
||||
Id: Guid.NewGuid(),
|
||||
@@ -62,18 +64,38 @@ public sealed class CiscoMapperTests
|
||||
advisory.Aliases.Should().Contain(new[] { "CISCO-SA-TEST", "CVE-2024-0001", "BUG123" });
|
||||
advisory.References.Should().Contain(reference => reference.Url == "https://example.com/advisory");
|
||||
advisory.References.Should().Contain(reference => reference.Url == "https://sec.cloudapps.cisco.com/csaf/test.json");
|
||||
advisory.AffectedPackages.Should().HaveCount(1);
|
||||
|
||||
var package = advisory.AffectedPackages[0];
|
||||
package.Type.Should().Be(AffectedPackageTypes.Vendor);
|
||||
package.Identifier.Should().Be("Cisco Widget");
|
||||
package.Statuses.Should().ContainSingle(status => status.Status == AffectedPackageStatusCatalog.KnownAffected);
|
||||
package.VersionRanges.Should().ContainSingle();
|
||||
var range = package.VersionRanges[0];
|
||||
range.RangeKind.Should().Be("semver");
|
||||
range.Provenance.Source.Should().Be(VndrCiscoConnectorPlugin.SourceName);
|
||||
range.Primitives.Should().NotBeNull();
|
||||
range.Primitives!.SemVer.Should().NotBeNull();
|
||||
range.Primitives.SemVer!.ExactValue.Should().Be("1.2.3");
|
||||
}
|
||||
}
|
||||
advisory.AffectedPackages.Should().HaveCount(2);
|
||||
|
||||
var package = advisory.AffectedPackages.Single(p => p.Identifier == "Cisco Widget");
|
||||
package.Type.Should().Be(AffectedPackageTypes.Vendor);
|
||||
package.Identifier.Should().Be("Cisco Widget");
|
||||
package.Statuses.Should().ContainSingle(status => status.Status == AffectedPackageStatusCatalog.KnownAffected);
|
||||
package.VersionRanges.Should().ContainSingle();
|
||||
var range = package.VersionRanges[0];
|
||||
range.RangeKind.Should().Be("semver");
|
||||
range.Provenance.Source.Should().Be(VndrCiscoConnectorPlugin.SourceName);
|
||||
range.Primitives.Should().NotBeNull();
|
||||
range.Primitives!.SemVer.Should().NotBeNull();
|
||||
range.Primitives.SemVer!.ExactValue.Should().Be("1.2.3");
|
||||
|
||||
package.NormalizedVersions.Should().ContainSingle();
|
||||
var normalized = package.NormalizedVersions[0];
|
||||
normalized.Scheme.Should().Be(NormalizedVersionSchemes.SemVer);
|
||||
normalized.Type.Should().Be(NormalizedVersionRuleTypes.Exact);
|
||||
normalized.Value.Should().Be("1.2.3");
|
||||
normalized.Notes.Should().Be("cisco:pid-1");
|
||||
|
||||
var rangePackage = advisory.AffectedPackages.Single(p => p.Identifier == "Cisco Router");
|
||||
rangePackage.VersionRanges.Should().ContainSingle();
|
||||
var rangePackageRange = rangePackage.VersionRanges[0];
|
||||
rangePackageRange.Primitives!.SemVer.Should().NotBeNull();
|
||||
rangePackageRange.Primitives.SemVer!.Introduced.Should().Be("1.0.0");
|
||||
rangePackageRange.Primitives.SemVer.Fixed.Should().Be("1.4.0");
|
||||
rangePackage.NormalizedVersions.Should().ContainSingle(rule =>
|
||||
rule.Min == "1.0.0" &&
|
||||
rule.Max == "1.4.0" &&
|
||||
rule.MinInclusive == true &&
|
||||
rule.MaxInclusive == false &&
|
||||
rule.Notes == "cisco:pid-2");
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,275 +1,306 @@
|
||||
[
|
||||
{
|
||||
"advisoryKey": "VMSA-2024-0001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"identifier": "VMware ESXi 7.0",
|
||||
"platform": null,
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "affected",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "VMware ESXi 7.0"
|
||||
}
|
||||
],
|
||||
"statuses": [],
|
||||
"type": "vendor",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "7.0u3f",
|
||||
"introducedVersion": "7.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": "7.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vmware.product": "VMware ESXi 7.0",
|
||||
"vmware.version.raw": "7.0",
|
||||
"vmware.fixedVersion.raw": "7.0u3f"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "range",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "VMware ESXi 7.0"
|
||||
},
|
||||
"rangeExpression": "7.0",
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "VMware vCenter Server 8.0",
|
||||
"platform": null,
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "affected",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "VMware vCenter Server 8.0"
|
||||
}
|
||||
],
|
||||
"statuses": [],
|
||||
"type": "vendor",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "8.0a",
|
||||
"introducedVersion": "8.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": "8.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vmware.product": "VMware vCenter Server 8.0",
|
||||
"vmware.version.raw": "8.0",
|
||||
"vmware.fixedVersion.raw": "8.0a"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "range",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "VMware vCenter Server 8.0"
|
||||
},
|
||||
"rangeExpression": "8.0",
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CVE-2024-1000",
|
||||
"CVE-2024-1001",
|
||||
"VMSA-2024-0001"
|
||||
],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-04-01T10:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "https://vmware.example/api/vmsa/VMSA-2024-0001.json"
|
||||
},
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "mapping",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "VMSA-2024-0001"
|
||||
}
|
||||
],
|
||||
"published": "2024-04-01T10:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "kb",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "https://kb.vmware.example/90234"
|
||||
},
|
||||
"sourceTag": "kb",
|
||||
"summary": null,
|
||||
"url": "https://kb.vmware.example/90234"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "https://www.vmware.com/security/advisories/VMSA-2024-0001.html"
|
||||
},
|
||||
"sourceTag": "advisory",
|
||||
"summary": null,
|
||||
"url": "https://www.vmware.com/security/advisories/VMSA-2024-0001.html"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Security updates for VMware ESXi 7.0 and vCenter Server 8.0 resolve multiple vulnerabilities.",
|
||||
"title": "VMware ESXi and vCenter Server updates address vulnerabilities"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "VMSA-2024-0002",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"identifier": "VMware Cloud Foundation 5.x",
|
||||
"platform": null,
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "affected",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "VMware Cloud Foundation 5.x"
|
||||
}
|
||||
],
|
||||
"statuses": [],
|
||||
"type": "vendor",
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "5.1.1",
|
||||
"introducedVersion": "5.1",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": null,
|
||||
"fixed": "5.1.1",
|
||||
"fixedInclusive": false,
|
||||
"introduced": "5.1",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vmware.product": "VMware Cloud Foundation 5.x",
|
||||
"vmware.version.raw": "5.1",
|
||||
"vmware.fixedVersion.raw": "5.1.1"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "range",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "VMware Cloud Foundation 5.x"
|
||||
},
|
||||
"rangeExpression": "5.1",
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CVE-2024-2000",
|
||||
"VMSA-2024-0002"
|
||||
],
|
||||
"cvssMetrics": [],
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-04-02T09:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "document",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "https://vmware.example/api/vmsa/VMSA-2024-0002.json"
|
||||
},
|
||||
{
|
||||
"fieldMask": [],
|
||||
"kind": "mapping",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "VMSA-2024-0002"
|
||||
}
|
||||
],
|
||||
"published": "2024-04-02T09:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "kb",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "https://kb.vmware.example/91234"
|
||||
},
|
||||
"sourceTag": "kb",
|
||||
"summary": null,
|
||||
"url": "https://kb.vmware.example/91234"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"fieldMask": [],
|
||||
"kind": "reference",
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"source": "vmware",
|
||||
"value": "https://www.vmware.com/security/advisories/VMSA-2024-0002.html"
|
||||
},
|
||||
"sourceTag": "advisory",
|
||||
"summary": null,
|
||||
"url": "https://www.vmware.com/security/advisories/VMSA-2024-0002.html"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "An update is available for VMware Cloud Foundation components to address a remote code execution vulnerability.",
|
||||
"title": "VMware Cloud Foundation remote code execution vulnerability"
|
||||
}
|
||||
[
|
||||
{
|
||||
"advisoryKey": "VMSA-2024-0001",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "VMware ESXi 7.0",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "7.0u3f",
|
||||
"introducedVersion": "7.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": null,
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": "7.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false,
|
||||
"style": "greaterThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vmware.product": "VMware ESXi 7.0",
|
||||
"vmware.version.raw": "7.0",
|
||||
"vmware.fixedVersion.raw": "7.0u3f"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "vmware",
|
||||
"kind": "range",
|
||||
"value": "VMware ESXi 7.0",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": "7.0",
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "vmware",
|
||||
"kind": "affected",
|
||||
"value": "VMware ESXi 7.0",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "VMware vCenter Server 8.0",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "8.0a",
|
||||
"introducedVersion": "8.0",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": null,
|
||||
"exactValue": null,
|
||||
"fixed": null,
|
||||
"fixedInclusive": false,
|
||||
"introduced": "8.0",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false,
|
||||
"style": "greaterThanOrEqual"
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vmware.product": "VMware vCenter Server 8.0",
|
||||
"vmware.version.raw": "8.0",
|
||||
"vmware.fixedVersion.raw": "8.0a"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "vmware",
|
||||
"kind": "range",
|
||||
"value": "VMware vCenter Server 8.0",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": "8.0",
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "vmware",
|
||||
"kind": "affected",
|
||||
"value": "VMware vCenter Server 8.0",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CVE-2024-1000",
|
||||
"CVE-2024-1001",
|
||||
"VMSA-2024-0001"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-04-01T10:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "vmware",
|
||||
"kind": "document",
|
||||
"value": "https://vmware.example/api/vmsa/VMSA-2024-0001.json",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
{
|
||||
"source": "vmware",
|
||||
"kind": "mapping",
|
||||
"value": "VMSA-2024-0001",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-04-01T10:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "kb",
|
||||
"provenance": {
|
||||
"source": "vmware",
|
||||
"kind": "reference",
|
||||
"value": "https://kb.vmware.example/90234",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "kb",
|
||||
"summary": null,
|
||||
"url": "https://kb.vmware.example/90234"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "vmware",
|
||||
"kind": "reference",
|
||||
"value": "https://www.vmware.com/security/advisories/VMSA-2024-0001.html",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "advisory",
|
||||
"summary": null,
|
||||
"url": "https://www.vmware.com/security/advisories/VMSA-2024-0001.html"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "Security updates for VMware ESXi 7.0 and vCenter Server 8.0 resolve multiple vulnerabilities.",
|
||||
"title": "VMware ESXi and vCenter Server updates address vulnerabilities"
|
||||
},
|
||||
{
|
||||
"advisoryKey": "VMSA-2024-0002",
|
||||
"affectedPackages": [
|
||||
{
|
||||
"type": "vendor",
|
||||
"identifier": "VMware Cloud Foundation 5.x",
|
||||
"platform": null,
|
||||
"versionRanges": [
|
||||
{
|
||||
"fixedVersion": "5.1.1",
|
||||
"introducedVersion": "5.1",
|
||||
"lastAffectedVersion": null,
|
||||
"primitives": {
|
||||
"evr": null,
|
||||
"hasVendorExtensions": true,
|
||||
"nevra": null,
|
||||
"semVer": {
|
||||
"constraintExpression": null,
|
||||
"exactValue": null,
|
||||
"fixed": "5.1.1",
|
||||
"fixedInclusive": false,
|
||||
"introduced": "5.1",
|
||||
"introducedInclusive": true,
|
||||
"lastAffected": null,
|
||||
"lastAffectedInclusive": false,
|
||||
"style": "range"
|
||||
},
|
||||
"vendorExtensions": {
|
||||
"vmware.product": "VMware Cloud Foundation 5.x",
|
||||
"vmware.version.raw": "5.1",
|
||||
"vmware.fixedVersion.raw": "5.1.1"
|
||||
}
|
||||
},
|
||||
"provenance": {
|
||||
"source": "vmware",
|
||||
"kind": "range",
|
||||
"value": "VMware Cloud Foundation 5.x",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"rangeExpression": "5.1",
|
||||
"rangeKind": "vendor"
|
||||
}
|
||||
],
|
||||
"normalizedVersions": [],
|
||||
"statuses": [],
|
||||
"provenance": [
|
||||
{
|
||||
"source": "vmware",
|
||||
"kind": "affected",
|
||||
"value": "VMware Cloud Foundation 5.x",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
"CVE-2024-2000",
|
||||
"VMSA-2024-0002"
|
||||
],
|
||||
"canonicalMetricId": null,
|
||||
"credits": [],
|
||||
"cvssMetrics": [],
|
||||
"cwes": [],
|
||||
"description": null,
|
||||
"exploitKnown": false,
|
||||
"language": "en",
|
||||
"modified": "2024-04-02T09:00:00+00:00",
|
||||
"provenance": [
|
||||
{
|
||||
"source": "vmware",
|
||||
"kind": "document",
|
||||
"value": "https://vmware.example/api/vmsa/VMSA-2024-0002.json",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
{
|
||||
"source": "vmware",
|
||||
"kind": "mapping",
|
||||
"value": "VMSA-2024-0002",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
}
|
||||
],
|
||||
"published": "2024-04-02T09:00:00+00:00",
|
||||
"references": [
|
||||
{
|
||||
"kind": "kb",
|
||||
"provenance": {
|
||||
"source": "vmware",
|
||||
"kind": "reference",
|
||||
"value": "https://kb.vmware.example/91234",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "kb",
|
||||
"summary": null,
|
||||
"url": "https://kb.vmware.example/91234"
|
||||
},
|
||||
{
|
||||
"kind": "advisory",
|
||||
"provenance": {
|
||||
"source": "vmware",
|
||||
"kind": "reference",
|
||||
"value": "https://www.vmware.com/security/advisories/VMSA-2024-0002.html",
|
||||
"decisionReason": null,
|
||||
"recordedAt": "2024-04-05T00:00:00+00:00",
|
||||
"fieldMask": []
|
||||
},
|
||||
"sourceTag": "advisory",
|
||||
"summary": null,
|
||||
"url": "https://www.vmware.com/security/advisories/VMSA-2024-0002.html"
|
||||
}
|
||||
],
|
||||
"severity": null,
|
||||
"summary": "An update is available for VMware Cloud Foundation components to address a remote code execution vulnerability.",
|
||||
"title": "VMware Cloud Foundation remote code execution vulnerability"
|
||||
}
|
||||
]
|
||||
@@ -1,17 +1,20 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json;
|
||||
using StellaOps.Aoc;
|
||||
using StellaOps.Concelier.Core.Aoc;
|
||||
using StellaOps.Concelier.RawModels;
|
||||
|
||||
namespace StellaOps.Concelier.Core.Tests.Aoc;
|
||||
|
||||
public sealed class AdvisoryRawWriteGuardTests
|
||||
{
|
||||
private static AdvisoryRawDocument CreateDocument(
|
||||
string tenant = "tenant-a",
|
||||
bool signaturePresent = false,
|
||||
bool includeSignaturePayload = true)
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Aoc;
|
||||
using StellaOps.Concelier.Core.Aoc;
|
||||
using StellaOps.Concelier.RawModels;
|
||||
|
||||
namespace StellaOps.Concelier.Core.Tests.Aoc;
|
||||
|
||||
public sealed class AdvisoryRawWriteGuardTests
|
||||
{
|
||||
private static readonly AocGuardOptions GuardOptions = AocGuardOptions.Default;
|
||||
|
||||
private static AdvisoryRawDocument CreateDocument(
|
||||
string tenant = "tenant-a",
|
||||
bool signaturePresent = false,
|
||||
bool includeSignaturePayload = true)
|
||||
{
|
||||
using var rawDocument = JsonDocument.Parse("""{"id":"demo"}""");
|
||||
var signature = signaturePresent
|
||||
@@ -22,11 +25,11 @@ public sealed class AdvisoryRawWriteGuardTests
|
||||
Signature: includeSignaturePayload ? "base64signature" : null)
|
||||
: new RawSignatureMetadata(false);
|
||||
|
||||
return new AdvisoryRawDocument(
|
||||
Tenant: tenant,
|
||||
Source: new RawSourceMetadata("vendor-x", "connector-y", "1.0.0"),
|
||||
Upstream: new RawUpstreamMetadata(
|
||||
UpstreamId: "GHSA-xxxx",
|
||||
return new AdvisoryRawDocument(
|
||||
Tenant: tenant,
|
||||
Source: new RawSourceMetadata("vendor-x", "connector-y", "1.0.0"),
|
||||
Upstream: new RawUpstreamMetadata(
|
||||
UpstreamId: "GHSA-xxxx",
|
||||
DocumentVersion: "1",
|
||||
RetrievedAt: DateTimeOffset.UtcNow,
|
||||
ContentHash: "sha256:abc",
|
||||
@@ -36,47 +39,51 @@ public sealed class AdvisoryRawWriteGuardTests
|
||||
Format: "OSV",
|
||||
SpecVersion: "1.0",
|
||||
Raw: rawDocument.RootElement.Clone()),
|
||||
Identifiers: new RawIdentifiers(
|
||||
Aliases: ImmutableArray.Create("GHSA-xxxx"),
|
||||
PrimaryId: "GHSA-xxxx"),
|
||||
Linkset: new RawLinkset
|
||||
{
|
||||
Aliases = ImmutableArray<string>.Empty,
|
||||
PackageUrls = ImmutableArray<string>.Empty,
|
||||
Cpes = ImmutableArray<string>.Empty,
|
||||
References = ImmutableArray<RawReference>.Empty,
|
||||
ReconciledFrom = ImmutableArray<string>.Empty,
|
||||
Notes = ImmutableDictionary<string, string>.Empty
|
||||
});
|
||||
}
|
||||
Identifiers: new RawIdentifiers(
|
||||
Aliases: ImmutableArray.Create("GHSA-xxxx"),
|
||||
PrimaryId: "GHSA-xxxx"),
|
||||
Linkset: new RawLinkset
|
||||
{
|
||||
Aliases = ImmutableArray<string>.Empty,
|
||||
PackageUrls = ImmutableArray<string>.Empty,
|
||||
Cpes = ImmutableArray<string>.Empty,
|
||||
References = ImmutableArray<RawReference>.Empty,
|
||||
ReconciledFrom = ImmutableArray<string>.Empty,
|
||||
Notes = ImmutableDictionary<string, string>.Empty
|
||||
},
|
||||
Links: ImmutableArray<RawLink>.Empty);
|
||||
}
|
||||
|
||||
private static AdvisoryRawWriteGuard CreateGuard()
|
||||
=> new(new AocWriteGuard(), Options.Create(GuardOptions));
|
||||
|
||||
[Fact]
|
||||
public void EnsureValid_AllowsMinimalDocument()
|
||||
{
|
||||
var guard = CreateGuard();
|
||||
var document = CreateDocument();
|
||||
|
||||
guard.EnsureValid(document);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureValid_AllowsMinimalDocument()
|
||||
{
|
||||
var guard = new AdvisoryRawWriteGuard(new AocWriteGuard());
|
||||
var document = CreateDocument();
|
||||
|
||||
guard.EnsureValid(document);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureValid_ThrowsWhenTenantMissing()
|
||||
{
|
||||
var guard = new AdvisoryRawWriteGuard(new AocWriteGuard());
|
||||
var document = CreateDocument(tenant: string.Empty);
|
||||
|
||||
var exception = Assert.Throws<ConcelierAocGuardException>(() => guard.EnsureValid(document));
|
||||
[Fact]
|
||||
public void EnsureValid_ThrowsWhenTenantMissing()
|
||||
{
|
||||
var guard = CreateGuard();
|
||||
var document = CreateDocument(tenant: string.Empty);
|
||||
|
||||
var exception = Assert.Throws<ConcelierAocGuardException>(() => guard.EnsureValid(document));
|
||||
Assert.Equal("ERR_AOC_004", exception.PrimaryErrorCode);
|
||||
Assert.Contains(exception.Violations, violation => violation.ErrorCode == "ERR_AOC_004" && violation.Path == "/tenant");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureValid_ThrowsWhenSignaturePayloadMissing()
|
||||
{
|
||||
var guard = new AdvisoryRawWriteGuard(new AocWriteGuard());
|
||||
var document = CreateDocument(signaturePresent: true, includeSignaturePayload: false);
|
||||
|
||||
var exception = Assert.Throws<ConcelierAocGuardException>(() => guard.EnsureValid(document));
|
||||
[Fact]
|
||||
public void EnsureValid_ThrowsWhenSignaturePayloadMissing()
|
||||
{
|
||||
var guard = CreateGuard();
|
||||
var document = CreateDocument(signaturePresent: true, includeSignaturePayload: false);
|
||||
|
||||
var exception = Assert.Throws<ConcelierAocGuardException>(() => guard.EnsureValid(document));
|
||||
Assert.Equal("ERR_AOC_005", exception.PrimaryErrorCode);
|
||||
Assert.Contains(exception.Violations, violation => violation.ErrorCode == "ERR_AOC_005");
|
||||
}
|
||||
|
||||
@@ -53,11 +53,11 @@ public sealed class AdvisoryEventLogTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AppendAsync_PersistsConflictsWithCanonicalizedJson()
|
||||
{
|
||||
var repository = new FakeRepository();
|
||||
var timeProvider = new FixedTimeProvider(DateTimeOffset.Parse("2025-10-19T12:00:00Z"));
|
||||
var log = new AdvisoryEventLog(repository, timeProvider);
|
||||
public async Task AppendAsync_PersistsConflictsWithCanonicalizedJson()
|
||||
{
|
||||
var repository = new FakeRepository();
|
||||
var timeProvider = new FixedTimeProvider(DateTimeOffset.Parse("2025-10-19T12:00:00Z"));
|
||||
var log = new AdvisoryEventLog(repository, timeProvider);
|
||||
|
||||
using var conflictJson = JsonDocument.Parse("{\"reason\":\"tie\",\"details\":{\"b\":2,\"a\":1}}");
|
||||
var conflictInput = new AdvisoryConflictInput(
|
||||
@@ -73,13 +73,52 @@ public sealed class AdvisoryEventLogTests
|
||||
Assert.Equal("cve-2025-0001", entry.VulnerabilityKey);
|
||||
Assert.Equal("{\"details\":{\"a\":1,\"b\":2},\"reason\":\"tie\"}", entry.CanonicalJson);
|
||||
Assert.NotEqual(ImmutableArray<byte>.Empty, entry.ConflictHash);
|
||||
Assert.Equal(DateTimeOffset.Parse("2025-10-04T00:00:00Z"), entry.AsOf);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReplayAsync_ReturnsSortedSnapshots()
|
||||
{
|
||||
var repository = new FakeRepository();
|
||||
Assert.Equal(DateTimeOffset.Parse("2025-10-04T00:00:00Z"), entry.AsOf);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AppendAsync_SortsConflictStatementIds()
|
||||
{
|
||||
var repository = new FakeRepository();
|
||||
var timeProvider = new FixedTimeProvider(DateTimeOffset.Parse("2025-10-20T12:00:00Z"));
|
||||
var log = new AdvisoryEventLog(repository, timeProvider);
|
||||
|
||||
var unordered = new[]
|
||||
{
|
||||
Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"),
|
||||
Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"),
|
||||
Guid.Empty,
|
||||
Guid.Parse("cccccccc-cccc-cccc-cccc-cccccccccccc"),
|
||||
Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
|
||||
};
|
||||
|
||||
using var conflictJson = JsonDocument.Parse("{\"reason\":\"severity-mismatch\"}");
|
||||
var conflictInput = new AdvisoryConflictInput(
|
||||
VulnerabilityKey: "CVE-2025-3000",
|
||||
Details: conflictJson,
|
||||
AsOf: DateTimeOffset.Parse("2025-10-20T00:00:00Z"),
|
||||
StatementIds: unordered);
|
||||
|
||||
await log.AppendAsync(
|
||||
new AdvisoryEventAppendRequest(Array.Empty<AdvisoryStatementInput>(), new[] { conflictInput }),
|
||||
CancellationToken.None);
|
||||
|
||||
var entry = Assert.Single(repository.InsertedConflicts);
|
||||
Assert.Equal(
|
||||
new[]
|
||||
{
|
||||
Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"),
|
||||
Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"),
|
||||
Guid.Parse("cccccccc-cccc-cccc-cccc-cccccccccccc")
|
||||
},
|
||||
entry.StatementIds);
|
||||
Assert.Equal("{\"reason\":\"severity-mismatch\"}", entry.CanonicalJson);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReplayAsync_ReturnsSortedSnapshots()
|
||||
{
|
||||
var repository = new FakeRepository();
|
||||
var timeProvider = new FixedTimeProvider(DateTimeOffset.Parse("2025-10-05T00:00:00Z"));
|
||||
var log = new AdvisoryEventLog(repository, timeProvider);
|
||||
|
||||
|
||||
@@ -122,19 +122,19 @@ public sealed class AdvisoryObservationFactoryTests
|
||||
var factory = new AdvisoryObservationFactory();
|
||||
var notes = ImmutableDictionary.CreateRange(new Dictionary<string, string>
|
||||
{
|
||||
["range-introduced"] = "1.0.0",
|
||||
["range-fixed"] = "1.0.5"
|
||||
});
|
||||
|
||||
var rawDocument = BuildRawDocument(
|
||||
identifiers: new RawIdentifiers(ImmutableArray<string>.Empty, "primary"),
|
||||
linkset: new RawLinkset
|
||||
{
|
||||
Notes = notes,
|
||||
ReconciledFrom = ImmutableArray.Create("connector-a", "connector-b")
|
||||
},
|
||||
supersedes: "tenant-a:vendor-x:previous:sha256:123");
|
||||
|
||||
["range-introduced"] = "1.0.0",
|
||||
["range-fixed"] = "1.0.5"
|
||||
});
|
||||
|
||||
var rawDocument = BuildRawDocument(
|
||||
identifiers: new RawIdentifiers(ImmutableArray<string>.Empty, "primary"),
|
||||
linkset: new RawLinkset
|
||||
{
|
||||
Notes = notes,
|
||||
ReconciledFrom = ImmutableArray.Create("connector-a", "connector-b")
|
||||
},
|
||||
supersedes: "tenant-a:vendor-x:previous:sha256:123");
|
||||
|
||||
var observation = factory.Create(rawDocument);
|
||||
|
||||
Assert.Equal("1.0.0", observation.Attributes["linkset.note.range-introduced"]);
|
||||
@@ -145,6 +145,65 @@ public sealed class AdvisoryObservationFactoryTests
|
||||
Assert.Equal(new[] { "connector-a", "connector-b" }, observation.RawLinkset.ReconciledFrom);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_PreservesRawReferencesForConflictAudits()
|
||||
{
|
||||
var factory = new AdvisoryObservationFactory();
|
||||
var references = ImmutableArray.Create(
|
||||
new RawReference(" ADVISORY ", " https://example.test/advisory ", "vendor-feed"),
|
||||
new RawReference("fix", "https://example.test/fix ", "vendor-feed"));
|
||||
var notes = ImmutableDictionary.CreateRange(new Dictionary<string, string>
|
||||
{
|
||||
["conflict.primary"] = "critical",
|
||||
["conflict.suppressed"] = "medium"
|
||||
});
|
||||
|
||||
var rawDocument = BuildRawDocument(
|
||||
identifiers: new RawIdentifiers(
|
||||
Aliases: ImmutableArray.Create("CVE-2025-2000"),
|
||||
PrimaryId: "VENDOR-2000"),
|
||||
linkset: new RawLinkset
|
||||
{
|
||||
References = references,
|
||||
Notes = notes,
|
||||
ReconciledFrom = ImmutableArray.Create("/content/raw/severity", "/content/raw/status")
|
||||
});
|
||||
|
||||
var observation = factory.Create(rawDocument, SampleTimestamp);
|
||||
|
||||
Assert.Collection(
|
||||
observation.Linkset.References,
|
||||
first =>
|
||||
{
|
||||
Assert.Equal("ADVISORY", first.Type);
|
||||
Assert.Equal("https://example.test/advisory", first.Url);
|
||||
},
|
||||
second =>
|
||||
{
|
||||
Assert.Equal("fix", second.Type);
|
||||
Assert.Equal("https://example.test/fix", second.Url);
|
||||
});
|
||||
|
||||
Assert.Collection(
|
||||
observation.RawLinkset.References,
|
||||
first =>
|
||||
{
|
||||
Assert.Equal(" ADVISORY ", first.Type);
|
||||
Assert.Equal(" https://example.test/advisory ", first.Url);
|
||||
Assert.Equal("vendor-feed", first.Source);
|
||||
},
|
||||
second =>
|
||||
{
|
||||
Assert.Equal("fix", second.Type);
|
||||
Assert.Equal("https://example.test/fix ", second.Url);
|
||||
Assert.Equal("vendor-feed", second.Source);
|
||||
});
|
||||
|
||||
Assert.Equal("critical", observation.Attributes["linkset.note.conflict.primary"]);
|
||||
Assert.Equal("medium", observation.Attributes["linkset.note.conflict.suppressed"]);
|
||||
Assert.Equal("/content/raw/severity;/content/raw/status", observation.Attributes["linkset.reconciled_from"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_IsDeterministicAcrossRuns()
|
||||
{
|
||||
|
||||
@@ -1,30 +1,34 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Aoc;
|
||||
using StellaOps.Concelier.Core.Aoc;
|
||||
using StellaOps.Concelier.Core.Linksets;
|
||||
using StellaOps.Concelier.Core.Raw;
|
||||
using StellaOps.Concelier.RawModels;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Core.Tests.Raw;
|
||||
|
||||
public sealed class AdvisoryRawServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task IngestAsync_RemovesClientSupersedesBeforeUpsert()
|
||||
{
|
||||
var repository = new RecordingRepository();
|
||||
var service = CreateService(repository);
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics.Metrics;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Aoc;
|
||||
using StellaOps.Concelier.Core.Aoc;
|
||||
using StellaOps.Concelier.Core.Linksets;
|
||||
using StellaOps.Concelier.Core.Raw;
|
||||
using StellaOps.Concelier.RawModels;
|
||||
using StellaOps.Ingestion.Telemetry;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Core.Tests.Raw;
|
||||
|
||||
public sealed class AdvisoryRawServiceTests
|
||||
{
|
||||
private const string GhsaAlias = "GHSA-AAAA-BBBB-CCCC";
|
||||
|
||||
[Fact]
|
||||
public async Task IngestAsync_RemovesClientSupersedesBeforeUpsert()
|
||||
{
|
||||
var repository = new RecordingRepository();
|
||||
var service = CreateService(repository);
|
||||
|
||||
var document = CreateDocument() with { Supersedes = " previous-id " };
|
||||
var storedDocument = document.WithSupersedes("advisory_raw:vendor-x:ghsa-xxxx:sha256-2");
|
||||
var storedDocument = document.WithSupersedes("advisory_raw:vendor-x:ghsa-aaaa-bbbb-cccc:sha256-2");
|
||||
var expectedResult = new AdvisoryRawUpsertResult(true, CreateRecord(storedDocument));
|
||||
repository.NextResult = expectedResult;
|
||||
|
||||
@@ -33,12 +37,14 @@ public sealed class AdvisoryRawServiceTests
|
||||
Assert.NotNull(repository.CapturedDocument);
|
||||
Assert.Null(repository.CapturedDocument!.Supersedes);
|
||||
Assert.Equal(expectedResult.Record.Document.Supersedes, result.Record.Document.Supersedes);
|
||||
Assert.Equal("GHSA-XXXX", repository.CapturedDocument.AdvisoryKey);
|
||||
Assert.Contains(repository.CapturedDocument.Links, link => link.Scheme == "GHSA" && link.Value == "GHSA-XXXX");
|
||||
Assert.Contains(repository.CapturedDocument.Links, link => link.Scheme == "PRIMARY" && link.Value == "GHSA-XXXX");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
Assert.Equal("GHSA-AAAA-BBBB-CCCC", repository.CapturedDocument.AdvisoryKey, ignoreCase: true);
|
||||
Assert.Contains(repository.CapturedDocument.Links, link =>
|
||||
string.Equals(link.Value, "GHSA-AAAA-BBBB-CCCC", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(repository.CapturedDocument.Links, link =>
|
||||
link.Scheme == "PRIMARY" && string.Equals(link.Value, "GHSA-AAAA-BBBB-CCCC", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IngestAsync_PropagatesRepositoryDuplicateResult()
|
||||
{
|
||||
var repository = new RecordingRepository();
|
||||
@@ -54,16 +60,66 @@ public sealed class AdvisoryRawServiceTests
|
||||
Assert.Same(expectedResult.Record, result.Record);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IngestAsync_EmitsWriteMetric()
|
||||
{
|
||||
var repository = new RecordingRepository();
|
||||
repository.NextResult = new AdvisoryRawUpsertResult(true, CreateRecord(CreateDocument()));
|
||||
var service = CreateService(repository);
|
||||
|
||||
var measurements = await CollectCounterMeasurementsAsync(
|
||||
"ingestion_write_total",
|
||||
() => service.IngestAsync(CreateDocument(), CancellationToken.None));
|
||||
|
||||
Assert.Contains(
|
||||
measurements,
|
||||
tags => string.Equals(GetTagValue(tags, "tenant") as string, "tenant-a", StringComparison.OrdinalIgnoreCase)
|
||||
&& string.Equals(GetTagValue(tags, "result") as string, IngestionTelemetry.ResultOk, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IngestAsync_EmitsViolationMetricWhenGuardFails()
|
||||
{
|
||||
var repository = new RecordingRepository();
|
||||
var service = CreateService(repository, new ThrowingWriteGuard());
|
||||
|
||||
var violationMeasurements = await CollectCounterMeasurementsAsync(
|
||||
"aoc_violation_total",
|
||||
async () =>
|
||||
{
|
||||
await Assert.ThrowsAsync<ConcelierAocGuardException>(
|
||||
() => service.IngestAsync(CreateDocument(), CancellationToken.None));
|
||||
});
|
||||
|
||||
Assert.Contains(
|
||||
violationMeasurements,
|
||||
tags => string.Equals(GetTagValue(tags, "tenant") as string, "tenant-a", StringComparison.OrdinalIgnoreCase)
|
||||
&& string.Equals(GetTagValue(tags, "code") as string, "ERR_AOC_001", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
var writeMeasurements = await CollectCounterMeasurementsAsync(
|
||||
"ingestion_write_total",
|
||||
async () =>
|
||||
{
|
||||
await Assert.ThrowsAsync<ConcelierAocGuardException>(
|
||||
() => service.IngestAsync(CreateDocument(), CancellationToken.None));
|
||||
});
|
||||
|
||||
Assert.Contains(
|
||||
writeMeasurements,
|
||||
tags => string.Equals(GetTagValue(tags, "tenant") as string, "tenant-a", StringComparison.OrdinalIgnoreCase)
|
||||
&& string.Equals(GetTagValue(tags, "result") as string, IngestionTelemetry.ResultReject, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IngestAsync_PreservesAliasOrderAndDuplicates()
|
||||
{
|
||||
var repository = new RecordingRepository();
|
||||
var service = CreateService(repository);
|
||||
|
||||
var aliasSeries = ImmutableArray.Create("CVE-2025-0001", "CVE-2025-0001", "GHSA-xxxx", "cve-2025-0001");
|
||||
var aliasSeries = ImmutableArray.Create("CVE-2025-0001", "CVE-2025-0001", GhsaAlias, "cve-2025-0001");
|
||||
var document = CreateDocument() with
|
||||
{
|
||||
Identifiers = new RawIdentifiers(aliasSeries, "GHSA-xxxx"),
|
||||
Identifiers = new RawIdentifiers(aliasSeries, GhsaAlias),
|
||||
};
|
||||
|
||||
repository.NextResult = new AdvisoryRawUpsertResult(true, CreateRecord(document));
|
||||
@@ -74,7 +130,8 @@ public sealed class AdvisoryRawServiceTests
|
||||
Assert.True(aliasSeries.SequenceEqual(repository.CapturedDocument!.Identifiers.Aliases));
|
||||
Assert.Equal("CVE-2025-0001", repository.CapturedDocument.AdvisoryKey);
|
||||
Assert.Contains(repository.CapturedDocument.Links, link => link.Scheme == "CVE" && link.Value == "CVE-2025-0001");
|
||||
Assert.Contains(repository.CapturedDocument.Links, link => link.Scheme == "GHSA" && link.Value == "GHSA-XXXX");
|
||||
Assert.Contains(repository.CapturedDocument.Links, link =>
|
||||
string.Equals(link.Value, "GHSA-AAAA-BBBB-CCCC", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -88,38 +145,42 @@ public sealed class AdvisoryRawServiceTests
|
||||
|
||||
var results = await service.FindByAdvisoryKeyAsync(
|
||||
"Tenant-Example",
|
||||
"ghsa-xxxx",
|
||||
"ghsa-aaaa-bbbb-cccc",
|
||||
new[] { "Vendor-X", " " },
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.Single(results);
|
||||
Assert.Equal("tenant-example", repository.CapturedTenant);
|
||||
Assert.Contains("GHSA-XXXX", repository.CapturedAdvisoryKeySearchValues!, StringComparer.Ordinal);
|
||||
Assert.Contains("ghsa-xxxx", repository.CapturedAdvisoryKeySearchValues!, StringComparer.Ordinal);
|
||||
Assert.Contains("GHSA-AAAA-BBBB-CCCC", repository.CapturedAdvisoryKeySearchValues!, StringComparer.OrdinalIgnoreCase);
|
||||
Assert.Contains("ghsa-aaaa-bbbb-cccc", repository.CapturedAdvisoryKeySearchValues!, StringComparer.Ordinal);
|
||||
Assert.Contains("vendor-x", repository.CapturedAdvisoryKeyVendors!, StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
private static AdvisoryRawService CreateService(RecordingRepository repository)
|
||||
{
|
||||
var writeGuard = new AdvisoryRawWriteGuard(new AocWriteGuard());
|
||||
var linksetMapper = new PassthroughLinksetMapper();
|
||||
return new AdvisoryRawService(
|
||||
repository,
|
||||
writeGuard,
|
||||
new AocWriteGuard(),
|
||||
linksetMapper,
|
||||
TimeProvider.System,
|
||||
NullLogger<AdvisoryRawService>.Instance);
|
||||
}
|
||||
|
||||
private static AdvisoryRawDocument CreateDocument()
|
||||
{
|
||||
using var raw = JsonDocument.Parse("""{"id":"demo"}""");
|
||||
private static AdvisoryRawService CreateService(
|
||||
RecordingRepository repository,
|
||||
IAdvisoryRawWriteGuard? writeGuard = null,
|
||||
IAocGuard? aocGuard = null)
|
||||
{
|
||||
var guard = aocGuard ?? new AocWriteGuard();
|
||||
var resolvedWriteGuard = writeGuard ?? new NoOpWriteGuard();
|
||||
var linksetMapper = new PassthroughLinksetMapper();
|
||||
return new AdvisoryRawService(
|
||||
repository,
|
||||
resolvedWriteGuard,
|
||||
guard,
|
||||
linksetMapper,
|
||||
TimeProvider.System,
|
||||
NullLogger<AdvisoryRawService>.Instance);
|
||||
}
|
||||
|
||||
private static AdvisoryRawDocument CreateDocument()
|
||||
{
|
||||
using var raw = JsonDocument.Parse("""{"id":"demo"}""");
|
||||
return new AdvisoryRawDocument(
|
||||
Tenant: "Tenant-A",
|
||||
Source: new RawSourceMetadata("Vendor-X", "connector-y", "1.0.0"),
|
||||
Upstream: new RawUpstreamMetadata(
|
||||
UpstreamId: "GHSA-xxxx",
|
||||
UpstreamId: GhsaAlias,
|
||||
DocumentVersion: "1",
|
||||
RetrievedAt: DateTimeOffset.UtcNow,
|
||||
ContentHash: "sha256:abc",
|
||||
@@ -134,8 +195,8 @@ public sealed class AdvisoryRawServiceTests
|
||||
SpecVersion: "1.0",
|
||||
Raw: raw.RootElement.Clone()),
|
||||
Identifiers: new RawIdentifiers(
|
||||
Aliases: ImmutableArray.Create("GHSA-xxxx"),
|
||||
PrimaryId: "GHSA-xxxx"),
|
||||
Aliases: ImmutableArray.Create(GhsaAlias),
|
||||
PrimaryId: GhsaAlias),
|
||||
Linkset: new RawLinkset
|
||||
{
|
||||
Aliases = ImmutableArray<string>.Empty,
|
||||
@@ -148,7 +209,7 @@ public sealed class AdvisoryRawServiceTests
|
||||
AdvisoryKey: string.Empty,
|
||||
Links: ImmutableArray<RawLink>.Empty);
|
||||
}
|
||||
|
||||
|
||||
private static AdvisoryRawRecord CreateRecord(AdvisoryRawDocument document)
|
||||
{
|
||||
var canonical = AdvisoryCanonicalizer.Canonicalize(document.Identifiers, document.Source, document.Upstream);
|
||||
@@ -159,13 +220,13 @@ public sealed class AdvisoryRawServiceTests
|
||||
};
|
||||
|
||||
return new AdvisoryRawRecord(
|
||||
Id: "advisory_raw:vendor-x:ghsa-xxxx:sha256-1",
|
||||
Id: "advisory_raw:vendor-x:ghsa-aaaa-bbbb-cccc:sha256-1",
|
||||
Document: resolvedDocument,
|
||||
IngestedAt: DateTimeOffset.UtcNow,
|
||||
CreatedAt: document.Upstream.RetrievedAt);
|
||||
}
|
||||
|
||||
private sealed class RecordingRepository : IAdvisoryRawRepository
|
||||
|
||||
private sealed class RecordingRepository : IAdvisoryRawRepository
|
||||
{
|
||||
public AdvisoryRawDocument? CapturedDocument { get; private set; }
|
||||
|
||||
@@ -184,15 +245,15 @@ public sealed class AdvisoryRawServiceTests
|
||||
if (NextResult is null)
|
||||
{
|
||||
throw new InvalidOperationException("NextResult must be set before calling UpsertAsync.");
|
||||
}
|
||||
|
||||
CapturedDocument = document;
|
||||
return Task.FromResult(NextResult);
|
||||
}
|
||||
|
||||
public Task<AdvisoryRawRecord?> FindByIdAsync(string tenant, string id, CancellationToken cancellationToken)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
}
|
||||
|
||||
CapturedDocument = document;
|
||||
return Task.FromResult(NextResult);
|
||||
}
|
||||
|
||||
public Task<AdvisoryRawRecord?> FindByIdAsync(string tenant, string id, CancellationToken cancellationToken)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public Task<AdvisoryRawQueryResult> QueryAsync(AdvisoryRawQueryOptions options, CancellationToken cancellationToken)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
@@ -213,12 +274,73 @@ public sealed class AdvisoryRawServiceTests
|
||||
DateTimeOffset since,
|
||||
DateTimeOffset until,
|
||||
IReadOnlyCollection<string> sourceVendors,
|
||||
CancellationToken cancellationToken)
|
||||
=> throw new NotSupportedException();
|
||||
}
|
||||
|
||||
private sealed class PassthroughLinksetMapper : IAdvisoryLinksetMapper
|
||||
{
|
||||
public RawLinkset Map(AdvisoryRawDocument document) => document.Linkset;
|
||||
}
|
||||
}
|
||||
CancellationToken cancellationToken)
|
||||
=> throw new NotSupportedException();
|
||||
}
|
||||
|
||||
private static async Task<List<KeyValuePair<string, object?>[]>> CollectCounterMeasurementsAsync(
|
||||
string instrumentName,
|
||||
Func<Task> action)
|
||||
{
|
||||
var measurements = new List<KeyValuePair<string, object?>[]>();
|
||||
using var listener = new MeterListener();
|
||||
listener.InstrumentPublished += (instrument, meterListener) =>
|
||||
{
|
||||
if (instrument.Meter.Name == IngestionTelemetry.MeterName && instrument.Name == instrumentName)
|
||||
{
|
||||
meterListener.EnableMeasurementEvents(instrument);
|
||||
}
|
||||
};
|
||||
|
||||
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
|
||||
{
|
||||
if (instrument.Name == instrumentName)
|
||||
{
|
||||
measurements.Add(tags.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
listener.Start();
|
||||
await action().ConfigureAwait(false);
|
||||
return measurements;
|
||||
}
|
||||
|
||||
private static object? GetTagValue(IEnumerable<KeyValuePair<string, object?>> tags, string key)
|
||||
{
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (string.Equals(tag.Key, key, StringComparison.Ordinal))
|
||||
{
|
||||
return tag.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private sealed class ThrowingWriteGuard : IAdvisoryRawWriteGuard
|
||||
{
|
||||
public void EnsureValid(AdvisoryRawDocument document)
|
||||
{
|
||||
var violation = AocViolation.Create(
|
||||
AocViolationCode.ForbiddenField,
|
||||
"/content/raw",
|
||||
"Forbidden derived data detected");
|
||||
var result = AocGuardResult.FromViolations(new[] { violation });
|
||||
throw new ConcelierAocGuardException(result);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class NoOpWriteGuard : IAdvisoryRawWriteGuard
|
||||
{
|
||||
public void EnsureValid(AdvisoryRawDocument document)
|
||||
{
|
||||
// Intentionally left blank for tests.
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class PassthroughLinksetMapper : IAdvisoryLinksetMapper
|
||||
{
|
||||
public RawLinkset Map(AdvisoryRawDocument document) => document.Linkset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Core/StellaOps.Concelier.Core.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.RawModels/StellaOps.Concelier.RawModels.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.Ingestion.Telemetry/StellaOps.Ingestion.Telemetry.csproj" />
|
||||
<ProjectReference Include="../../../Aoc/__Libraries/StellaOps.Aoc/StellaOps.Aoc.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Concelier.Exporter.Json;
|
||||
using StellaOps.Concelier.Models;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Concelier.Exporter.Json;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Cryptography;
|
||||
|
||||
namespace StellaOps.Concelier.Exporter.Json.Tests;
|
||||
|
||||
@@ -82,26 +83,52 @@ public sealed class JsonExportSnapshotBuilderTests : IDisposable
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteAsync_NormalizesInputOrdering()
|
||||
{
|
||||
var options = new JsonExportOptions { OutputRoot = _root };
|
||||
var builder = new JsonExportSnapshotBuilder(options, new VulnListJsonExportPathResolver());
|
||||
var exportedAt = DateTimeOffset.Parse("2024-06-01T00:00:00Z", CultureInfo.InvariantCulture);
|
||||
public async Task WriteAsync_NormalizesInputOrdering()
|
||||
{
|
||||
var options = new JsonExportOptions { OutputRoot = _root };
|
||||
var builder = new JsonExportSnapshotBuilder(options, new VulnListJsonExportPathResolver());
|
||||
var exportedAt = DateTimeOffset.Parse("2024-06-01T00:00:00Z", CultureInfo.InvariantCulture);
|
||||
|
||||
var advisoryA = CreateAdvisory("CVE-2024-1000", new[] { "CVE-2024-1000" }, "Alpha", "high");
|
||||
var advisoryB = CreateAdvisory("VENDOR-0001", new[] { "VENDOR-0001" }, "Vendor Advisory", "medium");
|
||||
|
||||
var result = await builder.WriteAsync(new[] { advisoryB, advisoryA }, exportedAt, cancellationToken: CancellationToken.None);
|
||||
|
||||
var expectedOrder = result.FilePaths.OrderBy(path => path, StringComparer.Ordinal).ToArray();
|
||||
Assert.Equal(expectedOrder, result.FilePaths.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteAsync_EnumeratesStreamOnlyOnce()
|
||||
{
|
||||
var options = new JsonExportOptions { OutputRoot = _root };
|
||||
var builder = new JsonExportSnapshotBuilder(options, new VulnListJsonExportPathResolver());
|
||||
var expectedOrder = result.FilePaths.OrderBy(path => path, StringComparer.Ordinal).ToArray();
|
||||
Assert.Equal(expectedOrder, result.FilePaths.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteAsync_DifferentInputOrderProducesSameDigest()
|
||||
{
|
||||
var options = new JsonExportOptions { OutputRoot = _root };
|
||||
var builder = new JsonExportSnapshotBuilder(options, new VulnListJsonExportPathResolver());
|
||||
var exportedAt = DateTimeOffset.Parse("2024-06-15T00:00:00Z", CultureInfo.InvariantCulture);
|
||||
|
||||
var advisoryA = CreateAdvisory("CVE-2024-1100", new[] { "CVE-2024-1100" }, "Alpha", "critical");
|
||||
var advisoryB = CreateAdvisory("VENDOR-2024-42", new[] { "VENDOR-2024-42" }, "Vendor", "medium");
|
||||
|
||||
var first = await builder.WriteAsync(
|
||||
new[] { advisoryA, advisoryB },
|
||||
exportedAt,
|
||||
exportName: "order-a",
|
||||
cancellationToken: CancellationToken.None);
|
||||
var second = await builder.WriteAsync(
|
||||
new[] { advisoryB, advisoryA },
|
||||
exportedAt,
|
||||
exportName: "order-b",
|
||||
cancellationToken: CancellationToken.None);
|
||||
|
||||
Assert.Equal(
|
||||
Convert.ToHexString(ComputeDigest(first)),
|
||||
Convert.ToHexString(ComputeDigest(second)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteAsync_EnumeratesStreamOnlyOnce()
|
||||
{
|
||||
var options = new JsonExportOptions { OutputRoot = _root };
|
||||
var builder = new JsonExportSnapshotBuilder(options, new VulnListJsonExportPathResolver());
|
||||
var exportedAt = DateTimeOffset.Parse("2024-08-01T00:00:00Z", CultureInfo.InvariantCulture);
|
||||
|
||||
var advisories = new[]
|
||||
@@ -150,19 +177,20 @@ public sealed class JsonExportSnapshotBuilderTests : IDisposable
|
||||
});
|
||||
}
|
||||
|
||||
private static byte[] ComputeDigest(JsonExportResult result)
|
||||
{
|
||||
using var sha256 = SHA256.Create();
|
||||
foreach (var relative in result.FilePaths.OrderBy(x => x, StringComparer.Ordinal))
|
||||
{
|
||||
var fullPath = ResolvePath(result.ExportDirectory, relative);
|
||||
var bytes = File.ReadAllBytes(fullPath);
|
||||
sha256.TransformBlock(bytes, 0, bytes.Length, null, 0);
|
||||
}
|
||||
|
||||
sha256.TransformFinalBlock(Array.Empty<byte>(), 0, 0);
|
||||
return sha256.Hash ?? Array.Empty<byte>();
|
||||
}
|
||||
private static byte[] ComputeDigest(JsonExportResult result)
|
||||
{
|
||||
var hash = CryptoHashFactory.CreateDefault();
|
||||
var buffer = new ArrayBufferWriter<byte>();
|
||||
|
||||
foreach (var relative in result.FilePaths.OrderBy(x => x, StringComparer.Ordinal))
|
||||
{
|
||||
var fullPath = ResolvePath(result.ExportDirectory, relative);
|
||||
var bytes = File.ReadAllBytes(fullPath);
|
||||
buffer.Write(bytes);
|
||||
}
|
||||
|
||||
return hash.ComputeHash(buffer.WrittenSpan, HashAlgorithms.Sha256);
|
||||
}
|
||||
|
||||
private static string ResolvePath(string root, string relative)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,8 @@ using StellaOps.Concelier.Exporter.Json;
|
||||
using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Exporting;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Cryptography;
|
||||
using StellaOps.Cryptography.DependencyInjection;
|
||||
|
||||
namespace StellaOps.Concelier.Exporter.Json.Tests;
|
||||
|
||||
@@ -26,7 +28,10 @@ public sealed class JsonExporterDependencyInjectionRoutineTests
|
||||
services.AddSingleton<IAdvisoryStore, StubAdvisoryStore>();
|
||||
services.AddSingleton<IExportStateStore, StubExportStateStore>();
|
||||
services.AddSingleton<IAdvisoryEventLog, StubAdvisoryEventLog>();
|
||||
services.AddOptions();
|
||||
services.AddOptions<JobSchedulerOptions>();
|
||||
services.Configure<CryptoHashOptions>(_ => { });
|
||||
services.AddStellaOpsCrypto();
|
||||
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>())
|
||||
|
||||
@@ -10,16 +10,17 @@ using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Concelier.Core.Events;
|
||||
using StellaOps.Concelier.Exporter.Json;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Exporting;
|
||||
using StellaOps.Cryptography;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Concelier.Core.Events;
|
||||
using StellaOps.Concelier.Exporter.Json;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Concelier.Storage.Mongo.Advisories;
|
||||
using StellaOps.Concelier.Storage.Mongo.Exporting;
|
||||
using StellaOps.Cryptography;
|
||||
using StellaOps.Cryptography.DependencyInjection;
|
||||
|
||||
namespace StellaOps.Concelier.Exporter.Json.Tests;
|
||||
|
||||
@@ -70,7 +71,7 @@ public sealed class JsonFeedExporterTests : IDisposable
|
||||
NullLogger<JsonFeedExporter>.Instance,
|
||||
timeProvider);
|
||||
|
||||
using var provider = new ServiceCollection().BuildServiceProvider();
|
||||
using var provider = CreateCryptoProvider();
|
||||
await exporter.ExportAsync(provider, CancellationToken.None);
|
||||
|
||||
var record = await stateStore.FindAsync(JsonFeedExporter.ExporterId, CancellationToken.None);
|
||||
@@ -164,7 +165,7 @@ public sealed class JsonFeedExporterTests : IDisposable
|
||||
NullLogger<JsonFeedExporter>.Instance,
|
||||
timeProvider);
|
||||
|
||||
using var provider = new ServiceCollection().BuildServiceProvider();
|
||||
using var provider = CreateCryptoProvider();
|
||||
await exporter.ExportAsync(provider, CancellationToken.None);
|
||||
|
||||
var exportId = exportedAt.ToString(optionsValue.DirectoryNameFormat, CultureInfo.InvariantCulture);
|
||||
@@ -322,16 +323,7 @@ public sealed class JsonFeedExporterTests : IDisposable
|
||||
NullLogger<JsonFeedExporter>.Instance,
|
||||
timeProvider);
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<DefaultCryptoProvider>();
|
||||
services.AddSingleton<ICryptoProvider>(sp => sp.GetRequiredService<DefaultCryptoProvider>());
|
||||
services.AddSingleton<ICryptoProviderRegistry>(sp =>
|
||||
{
|
||||
var provider = sp.GetRequiredService<DefaultCryptoProvider>();
|
||||
return new CryptoProviderRegistry(new[] { provider });
|
||||
});
|
||||
|
||||
using var provider = services.BuildServiceProvider();
|
||||
using var provider = CreateCryptoProvider();
|
||||
await exporter.ExportAsync(provider, CancellationToken.None);
|
||||
|
||||
var exportId = exportedAt.ToString(optionsValue.DirectoryNameFormat, CultureInfo.InvariantCulture);
|
||||
@@ -449,7 +441,7 @@ public sealed class JsonFeedExporterTests : IDisposable
|
||||
return $"-----BEGIN {label}-----\n{base64}\n-----END {label}-----\n";
|
||||
}
|
||||
|
||||
private static byte[] BuildSigningInput(string protectedHeader, byte[] payload)
|
||||
private static byte[] BuildSigningInput(string protectedHeader, byte[] payload)
|
||||
{
|
||||
var headerBytes = Encoding.ASCII.GetBytes(protectedHeader);
|
||||
var buffer = new byte[headerBytes.Length + 1 + payload.Length];
|
||||
@@ -459,9 +451,9 @@ public sealed class JsonFeedExporterTests : IDisposable
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static byte[] Base64UrlDecode(string value)
|
||||
{
|
||||
var builder = new StringBuilder(value.Length + 3);
|
||||
private static byte[] Base64UrlDecode(string value)
|
||||
{
|
||||
var builder = new StringBuilder(value.Length + 3);
|
||||
foreach (var ch in value)
|
||||
{
|
||||
builder.Append(ch switch
|
||||
@@ -475,10 +467,19 @@ public sealed class JsonFeedExporterTests : IDisposable
|
||||
while (builder.Length % 4 != 0)
|
||||
{
|
||||
builder.Append('=');
|
||||
}
|
||||
|
||||
return Convert.FromBase64String(builder.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return Convert.FromBase64String(builder.ToString());
|
||||
}
|
||||
|
||||
private static ServiceProvider CreateCryptoProvider()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddOptions();
|
||||
services.Configure<CryptoHashOptions>(_ => { });
|
||||
services.AddStellaOpsCrypto();
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private sealed class StubAdvisoryStore : IAdvisoryStore
|
||||
{
|
||||
@@ -594,4 +595,4 @@ public sealed class JsonFeedExporterTests : IDisposable
|
||||
|
||||
public void Advance(TimeSpan delta) => _now = _now.Add(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,5 +10,6 @@
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Exporter.Json/StellaOps.Concelier.Exporter.Json.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Models/StellaOps.Concelier.Models.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Concelier.Storage.Mongo/StellaOps.Concelier.Storage.Mongo.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography.DependencyInjection/StellaOps.Cryptography.DependencyInjection.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -67,6 +67,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
{
|
||||
_runner = MongoDbRunner.Start(singleNodeReplSet: true);
|
||||
_factory = new ConcelierApplicationFactory(_runner.ConnectionString);
|
||||
WarmupFactory(_factory);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -670,7 +671,10 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
using var client = _factory.CreateClient();
|
||||
client.DefaultRequestHeaders.Add("X-Stella-Tenant", "tenant-violation");
|
||||
|
||||
var invalidRequest = BuildAdvisoryIngestRequest(contentHash: string.Empty, upstreamId: "GHSA-INVALID-1");
|
||||
var invalidRequest = BuildAdvisoryIngestRequest(
|
||||
contentHash: string.Empty,
|
||||
upstreamId: "GHSA-INVALID-1",
|
||||
enforceContentHash: false);
|
||||
var response = await client.PostAsJsonAsync("/ingest/advisory", invalidRequest);
|
||||
|
||||
Assert.Equal(HttpStatusCode.UnprocessableEntity, response.StatusCode);
|
||||
@@ -1361,10 +1365,22 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
var snapshot = documents?.ToArray() ?? Array.Empty<AdvisoryObservationDocument>();
|
||||
if (snapshot.Length == 0)
|
||||
{
|
||||
await collection.InsertManyAsync(snapshot);
|
||||
return;
|
||||
}
|
||||
|
||||
await collection.InsertManyAsync(snapshot);
|
||||
|
||||
var rawDocuments = snapshot
|
||||
.Select(doc => CreateAdvisoryRawDocument(
|
||||
doc.Tenant,
|
||||
doc.Source.Vendor,
|
||||
doc.Id,
|
||||
doc.Upstream.ContentHash,
|
||||
doc.Content.Raw.DeepClone().AsBsonDocument))
|
||||
.ToArray();
|
||||
|
||||
await SeedAdvisoryRawDocumentsAsync(rawDocuments);
|
||||
}
|
||||
|
||||
private static AdvisoryObservationDocument[] BuildSampleObservationDocuments()
|
||||
@@ -1501,6 +1517,11 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
return value ?? string.Empty;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return value.Trim();
|
||||
}
|
||||
|
||||
using var sha256 = SHA256.Create();
|
||||
var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(raw.GetRawText()));
|
||||
return $"sha256:{Convert.ToHexString(bytes).ToLowerInvariant()}";
|
||||
@@ -1973,10 +1994,18 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
}
|
||||
}
|
||||
|
||||
private static AdvisoryIngestRequest BuildAdvisoryIngestRequest(string? contentHash, string upstreamId)
|
||||
private static void WarmupFactory(WebApplicationFactory<Program> factory)
|
||||
{
|
||||
var normalizedContentHash = contentHash ?? ComputeDeterministicContentHash(upstreamId);
|
||||
var raw = CreateJsonElement($@"{{""id"":""{upstreamId}"",""modified"":""{DateTime.UtcNow:O}""}}");
|
||||
using var client = factory.CreateClient();
|
||||
}
|
||||
|
||||
private static AdvisoryIngestRequest BuildAdvisoryIngestRequest(
|
||||
string? contentHash,
|
||||
string upstreamId,
|
||||
bool enforceContentHash = true)
|
||||
{
|
||||
var raw = CreateJsonElement($@"{{""id"":""{upstreamId}"",""modified"":""{DefaultIngestTimestamp:O}""}}");
|
||||
var normalizedContentHash = NormalizeContentHash(contentHash, raw, enforceContentHash);
|
||||
var references = new[]
|
||||
{
|
||||
new AdvisoryLinksetReferenceRequest("advisory", $"https://example.test/advisories/{upstreamId}", null)
|
||||
|
||||
Reference in New Issue
Block a user