From e345d93a66acf0f301fd2a72f135ac3b6d848e94 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Wed, 30 Oct 2024 08:40:25 -0400 Subject: [PATCH 1/9] feat: RHEL CSAF provider Add a new provider, rhel_csaf, that downloads rhel vulnerability data from the CSAF VEX JSON that RedHat publishes. Move the existing rhel provider to rhel_legacy. Add a top-level rhel provider that can be configured to delegate to rhel_legacy or rhel_csaf. Add some dataclasses to deserialize CSAF JSON into. Signed-off-by: Will Murphy --- poetry.lock | 240 +++--- pyproject.toml | 6 +- src/vunnel/providers/__init__.py | 2 + src/vunnel/providers/rhel/__init__.py | 77 +- src/vunnel/providers/rhel_csaf/__init__.py | 50 ++ src/vunnel/providers/rhel_csaf/parser.py | 146 ++++ src/vunnel/providers/rhel_csaf/transformer.py | 245 ++++++ src/vunnel/providers/rhel_legacy/__init__.py | 66 ++ .../{rhel => rhel_legacy}/oval_parser.py | 0 .../providers/{rhel => rhel_legacy}/parser.py | 0 src/vunnel/utils/csaf_types.py | 415 ++++++++++ tests/quality/Makefile | 3 + tests/quality/config.yaml | 4 +- tests/quality/vulnerability-match-labels | 2 +- tests/unit/cli/test_cli.py | 1 + .../providers/rhel/test_rhel_base_provider.py | 19 + .../providers/{rhel => rhel_csaf}/__init__.py | 0 .../test-fixtures/cve-2019-16161.json | 638 +++++++++++++++ .../test-fixtures/cve-2019-18276.json | 751 ++++++++++++++++++ .../result-for-cve-2019-16161.json | 89 +++ .../result-for-cve-2019-18276.json | 160 ++++ .../result-for-cve-2021-46661.json | 237 ++++++ .../providers/rhel_csaf/test_transformer.py | 75 ++ tests/unit/providers/rhel_legacy/__init__.py | 0 .../input/cve/full/CVE-2017-3509 | 0 .../input/cve/full/CVE-2017-3511 | 0 .../input/cve/full/CVE-2017-3526 | 0 .../input/cve/full/CVE-2017-3533 | 0 .../input/cve/full/CVE-2017-3539 | 0 .../input/cve/full/CVE-2017-3544 | 0 .../input/cve/full/CVE-2019-25059 | 0 .../input/cve/full/CVE-2020-16587 | 0 .../input/cve/full/CVE-2020-16588 | 0 .../input/cve/full/CVE-2021-20298 | 0 .../input/cve/full/CVE-2021-20299 | 0 .../input/cve/full/CVE-2022-1921 | 0 .../input/cve/full/CVE-2022-1922 | 0 .../input/cve/full/CVE-2022-1923 | 0 .../input/cve/full/CVE-2022-1924 | 0 .../input/cve/full/CVE-2022-1925 | 0 .../input/cve/full/CVE-2022-2309 | 0 .../input/cve/full/CVE-2023-4863 | 0 .../input/cve/full/CVE-2023-5129 | 0 .../input/cve/full/CVE-2023-5217 | 0 .../test-fixtures/input/cve/min/CVE-2017-3509 | 0 .../test-fixtures/input/cve/min/CVE-2017-3511 | 0 .../test-fixtures/input/cve/min/CVE-2017-3526 | 0 .../test-fixtures/input/cve/min/CVE-2017-3533 | 0 .../test-fixtures/input/cve/min/CVE-2017-3539 | 0 .../test-fixtures/input/cve/min/CVE-2017-3544 | 0 .../input/cve/min/CVE-2019-25059 | 0 .../input/cve/min/CVE-2020-16587 | 0 .../input/cve/min/CVE-2020-16588 | 0 .../input/cve/min/CVE-2021-20298 | 0 .../input/cve/min/CVE-2021-20299 | 0 .../test-fixtures/input/cve/min/CVE-2022-1921 | 0 .../test-fixtures/input/cve/min/CVE-2022-1922 | 0 .../test-fixtures/input/cve/min/CVE-2022-1923 | 0 .../test-fixtures/input/cve/min/CVE-2022-1924 | 0 .../test-fixtures/input/cve/min/CVE-2022-1925 | 0 .../test-fixtures/input/cve/min/CVE-2022-2309 | 0 .../test-fixtures/input/cve/min/CVE-2023-4863 | 0 .../test-fixtures/input/cve/min/CVE-2023-5129 | 0 .../test-fixtures/input/cve/min/CVE-2023-5217 | 0 .../input/rhsa/com.redhat.rhsa-all.xml | 0 .../rhsa/com.redhat.rhsa-all.xml.sha256sum | 0 .../snapshots/rhel:5/cve-2017-3509.json | 0 .../snapshots/rhel:5/cve-2017-3511.json | 0 .../snapshots/rhel:5/cve-2017-3526.json | 0 .../snapshots/rhel:5/cve-2017-3533.json | 0 .../snapshots/rhel:5/cve-2017-3539.json | 0 .../snapshots/rhel:5/cve-2017-3544.json | 0 .../snapshots/rhel:6/cve-2017-3509.json | 0 .../snapshots/rhel:6/cve-2017-3511.json | 0 .../snapshots/rhel:6/cve-2017-3526.json | 0 .../snapshots/rhel:6/cve-2017-3533.json | 0 .../snapshots/rhel:6/cve-2017-3539.json | 0 .../snapshots/rhel:6/cve-2017-3544.json | 0 .../snapshots/rhel:6/cve-2020-16587.json | 0 .../snapshots/rhel:6/cve-2020-16588.json | 0 .../snapshots/rhel:6/cve-2021-20298.json | 0 .../snapshots/rhel:6/cve-2021-20299.json | 0 .../snapshots/rhel:6/cve-2022-1921.json | 0 .../snapshots/rhel:6/cve-2022-1922.json | 0 .../snapshots/rhel:6/cve-2022-1923.json | 0 .../snapshots/rhel:6/cve-2022-1924.json | 0 .../snapshots/rhel:6/cve-2022-1925.json | 0 .../snapshots/rhel:6/cve-2023-4863.json | 0 .../snapshots/rhel:6/cve-2023-5129.json | 0 .../snapshots/rhel:6/cve-2023-5217.json | 0 .../snapshots/rhel:7/cve-2017-3509.json | 0 .../snapshots/rhel:7/cve-2017-3511.json | 0 .../snapshots/rhel:7/cve-2017-3526.json | 0 .../snapshots/rhel:7/cve-2017-3533.json | 0 .../snapshots/rhel:7/cve-2017-3539.json | 0 .../snapshots/rhel:7/cve-2017-3544.json | 0 .../snapshots/rhel:7/cve-2020-16587.json | 0 .../snapshots/rhel:7/cve-2020-16588.json | 0 .../snapshots/rhel:7/cve-2021-20298.json | 0 .../snapshots/rhel:7/cve-2021-20299.json | 0 .../snapshots/rhel:7/cve-2022-1921.json | 0 .../snapshots/rhel:7/cve-2022-1922.json | 0 .../snapshots/rhel:7/cve-2022-1923.json | 0 .../snapshots/rhel:7/cve-2022-1924.json | 0 .../snapshots/rhel:7/cve-2022-1925.json | 0 .../snapshots/rhel:7/cve-2023-4863.json | 0 .../snapshots/rhel:7/cve-2023-5129.json | 0 .../snapshots/rhel:7/cve-2023-5217.json | 0 .../snapshots/rhel:8/cve-2019-25059.json | 0 .../snapshots/rhel:8/cve-2020-16587.json | 0 .../snapshots/rhel:8/cve-2021-20298.json | 0 .../snapshots/rhel:8/cve-2021-20299.json | 0 .../snapshots/rhel:8/cve-2022-1921.json | 0 .../snapshots/rhel:8/cve-2022-1922.json | 0 .../snapshots/rhel:8/cve-2022-1923.json | 0 .../snapshots/rhel:8/cve-2022-1924.json | 0 .../snapshots/rhel:8/cve-2022-1925.json | 0 .../snapshots/rhel:8/cve-2023-4863.json | 0 .../snapshots/rhel:8/cve-2023-5129.json | 0 .../snapshots/rhel:8/cve-2023-5217.json | 0 .../snapshots/rhel:9/cve-2019-25059.json | 0 .../snapshots/rhel:9/cve-2022-1921.json | 0 .../snapshots/rhel:9/cve-2022-1922.json | 0 .../snapshots/rhel:9/cve-2022-1923.json | 0 .../snapshots/rhel:9/cve-2022-1924.json | 0 .../snapshots/rhel:9/cve-2022-1925.json | 0 .../snapshots/rhel:9/cve-2022-2309.json | 0 .../snapshots/rhel:9/cve-2023-4863.json | 0 .../snapshots/rhel:9/cve-2023-5129.json | 0 .../snapshots/rhel:9/cve-2023-5217.json | 0 .../{rhel => rhel_legacy}/test_rhel.py | 4 +- 131 files changed, 3091 insertions(+), 139 deletions(-) create mode 100644 src/vunnel/providers/rhel_csaf/__init__.py create mode 100644 src/vunnel/providers/rhel_csaf/parser.py create mode 100644 src/vunnel/providers/rhel_csaf/transformer.py create mode 100644 src/vunnel/providers/rhel_legacy/__init__.py rename src/vunnel/providers/{rhel => rhel_legacy}/oval_parser.py (100%) rename src/vunnel/providers/{rhel => rhel_legacy}/parser.py (100%) create mode 100644 src/vunnel/utils/csaf_types.py create mode 100644 tests/unit/providers/rhel/test_rhel_base_provider.py rename tests/unit/providers/{rhel => rhel_csaf}/__init__.py (100%) create mode 100644 tests/unit/providers/rhel_csaf/test-fixtures/cve-2019-16161.json create mode 100644 tests/unit/providers/rhel_csaf/test-fixtures/cve-2019-18276.json create mode 100644 tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2019-16161.json create mode 100644 tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2019-18276.json create mode 100644 tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2021-46661.json create mode 100644 tests/unit/providers/rhel_csaf/test_transformer.py create mode 100644 tests/unit/providers/rhel_legacy/__init__.py rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2017-3509 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2017-3511 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2017-3526 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2017-3533 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2017-3539 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2017-3544 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2019-25059 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2020-16587 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2020-16588 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2021-20298 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2021-20299 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2022-1921 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2022-1922 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2022-1923 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2022-1924 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2022-1925 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2022-2309 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2023-4863 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2023-5129 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/full/CVE-2023-5217 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2017-3509 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2017-3511 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2017-3526 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2017-3533 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2017-3539 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2017-3544 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2019-25059 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2020-16587 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2020-16588 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2021-20298 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2021-20299 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2022-1921 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2022-1922 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2022-1923 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2022-1924 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2022-1925 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2022-2309 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2023-4863 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2023-5129 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/cve/min/CVE-2023-5217 (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml.sha256sum (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:5/cve-2017-3509.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:5/cve-2017-3511.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:5/cve-2017-3526.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:5/cve-2017-3533.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:5/cve-2017-3539.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:5/cve-2017-3544.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2017-3509.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2017-3511.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2017-3526.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2017-3533.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2017-3539.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2017-3544.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2020-16587.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2020-16588.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2021-20298.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2021-20299.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2022-1921.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2022-1922.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2022-1923.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2022-1924.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2022-1925.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2023-4863.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2023-5129.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:6/cve-2023-5217.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2017-3509.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2017-3511.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2017-3526.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2017-3533.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2017-3539.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2017-3544.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2020-16587.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2020-16588.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2021-20298.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2021-20299.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2022-1921.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2022-1922.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2022-1923.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2022-1924.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2022-1925.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2023-4863.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2023-5129.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:7/cve-2023-5217.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2019-25059.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2020-16587.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2021-20298.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2021-20299.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2022-1921.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2022-1922.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2022-1923.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2022-1924.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2022-1925.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2023-4863.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2023-5129.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:8/cve-2023-5217.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2019-25059.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2022-1921.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2022-1922.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2022-1923.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2022-1924.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2022-1925.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2022-2309.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2023-4863.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2023-5129.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test-fixtures/snapshots/rhel:9/cve-2023-5217.json (100%) rename tests/unit/providers/{rhel => rhel_legacy}/test_rhel.py (99%) diff --git a/poetry.lock b/poetry.lock index 997567bb..4ccf31cf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "attrs" @@ -455,6 +455,24 @@ files = [ marshmallow = ">=3.18.0,<4.0.0" typing-inspect = ">=0.4.0,<1" +[[package]] +name = "deepdiff" +version = "8.1.1" +description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." +optional = false +python-versions = ">=3.8" +files = [ + {file = "deepdiff-8.1.1-py3-none-any.whl", hash = "sha256:b0231fa3afb0f7184e82535f2b4a36636442ed21e94a0cf3aaa7982157e7ebca"}, + {file = "deepdiff-8.1.1.tar.gz", hash = "sha256:dd7bc7d5c8b51b5b90f01b0e2fe23c801fd8b4c6a7ee7e31c5a3c3663fcc7ceb"}, +] + +[package.dependencies] +orderly-set = ">=5.2.3,<6" + +[package.extras] +cli = ["click (==8.1.7)", "pyyaml (==6.0.2)"] +optimize = ["orjson"] + [[package]] name = "defusedxml" version = "0.7.1" @@ -1143,90 +1161,118 @@ files = [ {file = "omitempty-0.1.1.tar.gz", hash = "sha256:761fea43d0edb7a31e3322158f73c97d77e939e57c1e62754be23e081ab853d8"}, ] +[[package]] +name = "orderly-set" +version = "5.2.3" +description = "Orderly set" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orderly_set-5.2.3-py3-none-any.whl", hash = "sha256:d357cedcf67f4ebff0d4cbd5b0997e98eeb65dd24fdf5c990a501ae9e82c7d34"}, + {file = "orderly_set-5.2.3.tar.gz", hash = "sha256:571ed97c5a5fca7ddeb6b2d26c19aca896b0ed91f334d9c109edd2f265fb3017"}, +] + [[package]] name = "orjson" -version = "3.10.14" +version = "3.10.13" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.10.14-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:849ea7845a55f09965826e816cdc7689d6cf74fe9223d79d758c714af955bcb6"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5947b139dfa33f72eecc63f17e45230a97e741942955a6c9e650069305eb73d"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cde6d76910d3179dae70f164466692f4ea36da124d6fb1a61399ca589e81d69a"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6dfbaeb7afa77ca608a50e2770a0461177b63a99520d4928e27591b142c74b1"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa45e489ef80f28ff0e5ba0a72812b8cfc7c1ef8b46a694723807d1b07c89ebb"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5007abfdbb1d866e2aa8990bd1c465f0f6da71d19e695fc278282be12cffa5"}, - {file = "orjson-3.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1b49e2af011c84c3f2d541bb5cd1e3c7c2df672223e7e3ea608f09cf295e5f8a"}, - {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:164ac155109226b3a2606ee6dda899ccfbe6e7e18b5bdc3fbc00f79cc074157d"}, - {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6b1225024cf0ef5d15934b5ffe9baf860fe8bc68a796513f5ea4f5056de30bca"}, - {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d6546e8073dc382e60fcae4a001a5a1bc46da5eab4a4878acc2d12072d6166d5"}, - {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9f1d2942605c894162252d6259b0121bf1cb493071a1ea8cb35d79cb3e6ac5bc"}, - {file = "orjson-3.10.14-cp310-cp310-win32.whl", hash = "sha256:397083806abd51cf2b3bbbf6c347575374d160331a2d33c5823e22249ad3118b"}, - {file = "orjson-3.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:fa18f949d3183a8d468367056be989666ac2bef3a72eece0bade9cdb733b3c28"}, - {file = "orjson-3.10.14-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f506fd666dd1ecd15a832bebc66c4df45c1902fd47526292836c339f7ba665a9"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efe5fd254cfb0eeee13b8ef7ecb20f5d5a56ddda8a587f3852ab2cedfefdb5f6"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ddc8c866d7467f5ee2991397d2ea94bcf60d0048bdd8ca555740b56f9042725"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af8e42ae4363773658b8d578d56dedffb4f05ceeb4d1d4dd3fb504950b45526"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84dd83110503bc10e94322bf3ffab8bc49150176b49b4984dc1cce4c0a993bf9"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36f5bfc0399cd4811bf10ec7a759c7ab0cd18080956af8ee138097d5b5296a95"}, - {file = "orjson-3.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868943660fb2a1e6b6b965b74430c16a79320b665b28dd4511d15ad5038d37d5"}, - {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33449c67195969b1a677533dee9d76e006001213a24501333624623e13c7cc8e"}, - {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e4c9f60f9fb0b5be66e416dcd8c9d94c3eabff3801d875bdb1f8ffc12cf86905"}, - {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0de4d6315cfdbd9ec803b945c23b3a68207fd47cbe43626036d97e8e9561a436"}, - {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83adda3db595cb1a7e2237029b3249c85afbe5c747d26b41b802e7482cb3933e"}, - {file = "orjson-3.10.14-cp311-cp311-win32.whl", hash = "sha256:998019ef74a4997a9d741b1473533cdb8faa31373afc9849b35129b4b8ec048d"}, - {file = "orjson-3.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:9d034abdd36f0f0f2240f91492684e5043d46f290525d1117712d5b8137784eb"}, - {file = "orjson-3.10.14-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2ad4b7e367efba6dc3f119c9a0fcd41908b7ec0399a696f3cdea7ec477441b09"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f496286fc85e93ce0f71cc84fc1c42de2decf1bf494094e188e27a53694777a7"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7f189bbfcded40e41a6969c1068ba305850ba016665be71a217918931416fbf"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cc8204f0b75606869c707da331058ddf085de29558b516fc43c73ee5ee2aadb"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:deaa2899dff7f03ab667e2ec25842d233e2a6a9e333efa484dfe666403f3501c"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1c3ea52642c9714dc6e56de8a451a066f6d2707d273e07fe8a9cc1ba073813d"}, - {file = "orjson-3.10.14-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d3f9ed72e7458ded9a1fb1b4d4ed4c4fdbaf82030ce3f9274b4dc1bff7ace2b"}, - {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:07520685d408a2aba514c17ccc16199ff2934f9f9e28501e676c557f454a37fe"}, - {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:76344269b550ea01488d19a2a369ab572c1ac4449a72e9f6ac0d70eb1cbfb953"}, - {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e2979d0f2959990620f7e62da6cd954e4620ee815539bc57a8ae46e2dacf90e3"}, - {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03f61ca3674555adcb1aa717b9fc87ae936aa7a63f6aba90a474a88701278780"}, - {file = "orjson-3.10.14-cp312-cp312-win32.whl", hash = "sha256:d5075c54edf1d6ad81d4c6523ce54a748ba1208b542e54b97d8a882ecd810fd1"}, - {file = "orjson-3.10.14-cp312-cp312-win_amd64.whl", hash = "sha256:175cafd322e458603e8ce73510a068d16b6e6f389c13f69bf16de0e843d7d406"}, - {file = "orjson-3.10.14-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:0905ca08a10f7e0e0c97d11359609300eb1437490a7f32bbaa349de757e2e0c7"}, - {file = "orjson-3.10.14-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92d13292249f9f2a3e418cbc307a9fbbef043c65f4bd8ba1eb620bc2aaba3d15"}, - {file = "orjson-3.10.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90937664e776ad316d64251e2fa2ad69265e4443067668e4727074fe39676414"}, - {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9ed3d26c4cb4f6babaf791aa46a029265850e80ec2a566581f5c2ee1a14df4f1"}, - {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:56ee546c2bbe9599aba78169f99d1dc33301853e897dbaf642d654248280dc6e"}, - {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:901e826cb2f1bdc1fcef3ef59adf0c451e8f7c0b5deb26c1a933fb66fb505eae"}, - {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26336c0d4b2d44636e1e1e6ed1002f03c6aae4a8a9329561c8883f135e9ff010"}, - {file = "orjson-3.10.14-cp313-cp313-win32.whl", hash = "sha256:e2bc525e335a8545c4e48f84dd0328bc46158c9aaeb8a1c2276546e94540ea3d"}, - {file = "orjson-3.10.14-cp313-cp313-win_amd64.whl", hash = "sha256:eca04dfd792cedad53dc9a917da1a522486255360cb4e77619343a20d9f35364"}, - {file = "orjson-3.10.14-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a0fba3b8a587a54c18585f077dcab6dd251c170d85cfa4d063d5746cd595a0f"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:175abf3d20e737fec47261d278f95031736a49d7832a09ab684026528c4d96db"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29ca1a93e035d570e8b791b6c0feddd403c6a5388bfe870bf2aa6bba1b9d9b8e"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f77202c80e8ab5a1d1e9faf642343bee5aaf332061e1ada4e9147dbd9eb00c46"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e2ec73b7099b6a29b40a62e08a23b936423bd35529f8f55c42e27acccde7954"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2d1679df9f9cd9504f8dff24555c1eaabba8aad7f5914f28dab99e3c2552c9d"}, - {file = "orjson-3.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691ab9a13834310a263664313e4f747ceb93662d14a8bdf20eb97d27ed488f16"}, - {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:b11ed82054fce82fb74cea33247d825d05ad6a4015ecfc02af5fbce442fbf361"}, - {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:e70a1d62b8288677d48f3bea66c21586a5f999c64ecd3878edb7393e8d1b548d"}, - {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:16642f10c1ca5611251bd835de9914a4b03095e28a34c8ba6a5500b5074338bd"}, - {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3871bad546aa66c155e3f36f99c459780c2a392d502a64e23fb96d9abf338511"}, - {file = "orjson-3.10.14-cp38-cp38-win32.whl", hash = "sha256:0293a88815e9bb5c90af4045f81ed364d982f955d12052d989d844d6c4e50945"}, - {file = "orjson-3.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:6169d3868b190d6b21adc8e61f64e3db30f50559dfbdef34a1cd6c738d409dfc"}, - {file = "orjson-3.10.14-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:06d4ec218b1ec1467d8d64da4e123b4794c781b536203c309ca0f52819a16c03"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962c2ec0dcaf22b76dee9831fdf0c4a33d4bf9a257a2bc5d4adc00d5c8ad9034"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:21d3be4132f71ef1360385770474f29ea1538a242eef72ac4934fe142800e37f"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c28ed60597c149a9e3f5ad6dd9cebaee6fb2f0e3f2d159a4a2b9b862d4748860"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e947f70167fe18469f2023644e91ab3d24f9aed69a5e1c78e2c81b9cea553fb"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64410696c97a35af2432dea7bdc4ce32416458159430ef1b4beb79fd30093ad6"}, - {file = "orjson-3.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8050a5d81c022561ee29cd2739de5b4445f3c72f39423fde80a63299c1892c52"}, - {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b49a28e30d3eca86db3fe6f9b7f4152fcacbb4a467953cd1b42b94b479b77956"}, - {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ca041ad20291a65d853a9523744eebc3f5a4b2f7634e99f8fe88320695ddf766"}, - {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d313a2998b74bb26e9e371851a173a9b9474764916f1fc7971095699b3c6e964"}, - {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7796692136a67b3e301ef9052bde6fe8e7bd5200da766811a3a608ffa62aaff0"}, - {file = "orjson-3.10.14-cp39-cp39-win32.whl", hash = "sha256:eee4bc767f348fba485ed9dc576ca58b0a9eac237f0e160f7a59bce628ed06b3"}, - {file = "orjson-3.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:96a1c0ee30fb113b3ae3c748fd75ca74a157ff4c58476c47db4d61518962a011"}, - {file = "orjson-3.10.14.tar.gz", hash = "sha256:cf31f6f071a6b8e7aa1ead1fa27b935b48d00fbfa6a28ce856cfff2d5dd68eed"}, + {file = "orjson-3.10.13-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1232c5e873a4d1638ef957c5564b4b0d6f2a6ab9e207a9b3de9de05a09d1d920"}, + {file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d26a0eca3035619fa366cbaf49af704c7cb1d4a0e6c79eced9f6a3f2437964b6"}, + {file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d4b6acd7c9c829895e50d385a357d4b8c3fafc19c5989da2bae11783b0fd4977"}, + {file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1884e53c6818686891cc6fc5a3a2540f2f35e8c76eac8dc3b40480fb59660b00"}, + {file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a428afb5720f12892f64920acd2eeb4d996595bf168a26dd9190115dbf1130d"}, + {file = "orjson-3.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba5b13b8739ce5b630c65cb1c85aedbd257bcc2b9c256b06ab2605209af75a2e"}, + {file = "orjson-3.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cab83e67f6aabda1b45882254b2598b48b80ecc112968fc6483fa6dae609e9f0"}, + {file = "orjson-3.10.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:62c3cc00c7e776c71c6b7b9c48c5d2701d4c04e7d1d7cdee3572998ee6dc57cc"}, + {file = "orjson-3.10.13-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:dc03db4922e75bbc870b03fc49734cefbd50fe975e0878327d200022210b82d8"}, + {file = "orjson-3.10.13-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:22f1c9a30b43d14a041a6ea190d9eca8a6b80c4beb0e8b67602c82d30d6eec3e"}, + {file = "orjson-3.10.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b42f56821c29e697c68d7d421410d7c1d8f064ae288b525af6a50cf99a4b1200"}, + {file = "orjson-3.10.13-cp310-cp310-win32.whl", hash = "sha256:0dbf3b97e52e093d7c3e93eb5eb5b31dc7535b33c2ad56872c83f0160f943487"}, + {file = "orjson-3.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:46c249b4e934453be4ff2e518cd1adcd90467da7391c7a79eaf2fbb79c51e8c7"}, + {file = "orjson-3.10.13-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a36c0d48d2f084c800763473020a12976996f1109e2fcb66cfea442fdf88047f"}, + {file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0065896f85d9497990731dfd4a9991a45b0a524baec42ef0a63c34630ee26fd6"}, + {file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92b4ec30d6025a9dcdfe0df77063cbce238c08d0404471ed7a79f309364a3d19"}, + {file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a94542d12271c30044dadad1125ee060e7a2048b6c7034e432e116077e1d13d2"}, + {file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3723e137772639af8adb68230f2aa4bcb27c48b3335b1b1e2d49328fed5e244c"}, + {file = "orjson-3.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f00c7fb18843bad2ac42dc1ce6dd214a083c53f1e324a0fd1c8137c6436269b"}, + {file = "orjson-3.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0e2759d3172300b2f892dee85500b22fca5ac49e0c42cfff101aaf9c12ac9617"}, + {file = "orjson-3.10.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee948c6c01f6b337589c88f8e0bb11e78d32a15848b8b53d3f3b6fea48842c12"}, + {file = "orjson-3.10.13-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:aa6fe68f0981fba0d4bf9cdc666d297a7cdba0f1b380dcd075a9a3dd5649a69e"}, + {file = "orjson-3.10.13-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dbcd7aad6bcff258f6896abfbc177d54d9b18149c4c561114f47ebfe74ae6bfd"}, + {file = "orjson-3.10.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2149e2fcd084c3fd584881c7f9d7f9e5ad1e2e006609d8b80649655e0d52cd02"}, + {file = "orjson-3.10.13-cp311-cp311-win32.whl", hash = "sha256:89367767ed27b33c25c026696507c76e3d01958406f51d3a2239fe9e91959df2"}, + {file = "orjson-3.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:dca1d20f1af0daff511f6e26a27354a424f0b5cf00e04280279316df0f604a6f"}, + {file = "orjson-3.10.13-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a3614b00621c77f3f6487792238f9ed1dd8a42f2ec0e6540ee34c2d4e6db813a"}, + {file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c976bad3996aa027cd3aef78aa57873f3c959b6c38719de9724b71bdc7bd14b"}, + {file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f74d878d1efb97a930b8a9f9898890067707d683eb5c7e20730030ecb3fb930"}, + {file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33ef84f7e9513fb13b3999c2a64b9ca9c8143f3da9722fbf9c9ce51ce0d8076e"}, + {file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd2bcde107221bb9c2fa0c4aaba735a537225104173d7e19cf73f70b3126c993"}, + {file = "orjson-3.10.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:064b9dbb0217fd64a8d016a8929f2fae6f3312d55ab3036b00b1d17399ab2f3e"}, + {file = "orjson-3.10.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0044b0b8c85a565e7c3ce0a72acc5d35cda60793edf871ed94711e712cb637d"}, + {file = "orjson-3.10.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7184f608ad563032e398f311910bc536e62b9fbdca2041be889afcbc39500de8"}, + {file = "orjson-3.10.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d36f689e7e1b9b6fb39dbdebc16a6f07cbe994d3644fb1c22953020fc575935f"}, + {file = "orjson-3.10.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:54433e421618cd5873e51c0e9d0b9fb35f7bf76eb31c8eab20b3595bb713cd3d"}, + {file = "orjson-3.10.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e1ba0c5857dd743438acecc1cd0e1adf83f0a81fee558e32b2b36f89e40cee8b"}, + {file = "orjson-3.10.13-cp312-cp312-win32.whl", hash = "sha256:a42b9fe4b0114b51eb5cdf9887d8c94447bc59df6dbb9c5884434eab947888d8"}, + {file = "orjson-3.10.13-cp312-cp312-win_amd64.whl", hash = "sha256:3a7df63076435f39ec024bdfeb4c9767ebe7b49abc4949068d61cf4857fa6d6c"}, + {file = "orjson-3.10.13-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2cdaf8b028a976ebab837a2c27b82810f7fc76ed9fb243755ba650cc83d07730"}, + {file = "orjson-3.10.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48a946796e390cbb803e069472de37f192b7a80f4ac82e16d6eb9909d9e39d56"}, + {file = "orjson-3.10.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d64f1db5ecbc21eb83097e5236d6ab7e86092c1cd4c216c02533332951afc"}, + {file = "orjson-3.10.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:711878da48f89df194edd2ba603ad42e7afed74abcd2bac164685e7ec15f96de"}, + {file = "orjson-3.10.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:cf16f06cb77ce8baf844bc222dbcb03838f61d0abda2c3341400c2b7604e436e"}, + {file = "orjson-3.10.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8257c3fb8dd7b0b446b5e87bf85a28e4071ac50f8c04b6ce2d38cb4abd7dff57"}, + {file = "orjson-3.10.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9c3a87abe6f849a4a7ac8a8a1dede6320a4303d5304006b90da7a3cd2b70d2c"}, + {file = "orjson-3.10.13-cp313-cp313-win32.whl", hash = "sha256:527afb6ddb0fa3fe02f5d9fba4920d9d95da58917826a9be93e0242da8abe94a"}, + {file = "orjson-3.10.13-cp313-cp313-win_amd64.whl", hash = "sha256:b5f7c298d4b935b222f52d6c7f2ba5eafb59d690d9a3840b7b5c5cda97f6ec5c"}, + {file = "orjson-3.10.13-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e49333d1038bc03a25fdfe11c86360df9b890354bfe04215f1f54d030f33c342"}, + {file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:003721c72930dbb973f25c5d8e68d0f023d6ed138b14830cc94e57c6805a2eab"}, + {file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63664bf12addb318dc8f032160e0f5dc17eb8471c93601e8f5e0d07f95003784"}, + {file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6066729cf9552d70de297b56556d14b4f49c8f638803ee3c90fd212fa43cc6af"}, + {file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8a1152e2761025c5d13b5e1908d4b1c57f3797ba662e485ae6f26e4e0c466388"}, + {file = "orjson-3.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69b21d91c5c5ef8a201036d207b1adf3aa596b930b6ca3c71484dd11386cf6c3"}, + {file = "orjson-3.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b12a63f48bb53dba8453d36ca2661f2330126d54e26c1661e550b32864b28ce3"}, + {file = "orjson-3.10.13-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a5a7624ab4d121c7e035708c8dd1f99c15ff155b69a1c0affc4d9d8b551281ba"}, + {file = "orjson-3.10.13-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:0fee076134398d4e6cb827002468679ad402b22269510cf228301b787fdff5ae"}, + {file = "orjson-3.10.13-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ae537fcf330b3947e82c6ae4271e092e6cf16b9bc2cef68b14ffd0df1fa8832a"}, + {file = "orjson-3.10.13-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f81b26c03f5fb5f0d0ee48d83cea4d7bc5e67e420d209cc1a990f5d1c62f9be0"}, + {file = "orjson-3.10.13-cp38-cp38-win32.whl", hash = "sha256:0bc858086088b39dc622bc8219e73d3f246fb2bce70a6104abd04b3a080a66a8"}, + {file = "orjson-3.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:3ca6f17467ebbd763f8862f1d89384a5051b461bb0e41074f583a0ebd7120e8e"}, + {file = "orjson-3.10.13-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4a11532cbfc2f5752c37e84863ef8435b68b0e6d459b329933294f65fa4bda1a"}, + {file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c96d2fb80467d1d0dfc4d037b4e1c0f84f1fe6229aa7fea3f070083acef7f3d7"}, + {file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dda4ba4d3e6f6c53b6b9c35266788053b61656a716a7fef5c884629c2a52e7aa"}, + {file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4f998bbf300690be881772ee9c5281eb9c0044e295bcd4722504f5b5c6092ff"}, + {file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1cc42ed75b585c0c4dc5eb53a90a34ccb493c09a10750d1a1f9b9eff2bd12"}, + {file = "orjson-3.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03b0f29d485411e3c13d79604b740b14e4e5fb58811743f6f4f9693ee6480a8f"}, + {file = "orjson-3.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:233aae4474078d82f425134bb6a10fb2b3fc5a1a1b3420c6463ddd1b6a97eda8"}, + {file = "orjson-3.10.13-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e384e330a67cf52b3597ee2646de63407da6f8fc9e9beec3eaaaef5514c7a1c9"}, + {file = "orjson-3.10.13-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4222881d0aab76224d7b003a8e5fdae4082e32c86768e0e8652de8afd6c4e2c1"}, + {file = "orjson-3.10.13-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e400436950ba42110a20c50c80dff4946c8e3ec09abc1c9cf5473467e83fd1c5"}, + {file = "orjson-3.10.13-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f47c9e7d224b86ffb086059cdcf634f4b3f32480f9838864aa09022fe2617ce2"}, + {file = "orjson-3.10.13-cp39-cp39-win32.whl", hash = "sha256:a9ecea472f3eb653e1c0a3d68085f031f18fc501ea392b98dcca3e87c24f9ebe"}, + {file = "orjson-3.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:5385935a73adce85cc7faac9d396683fd813566d3857fa95a0b521ef84a5b588"}, + {file = "orjson-3.10.13.tar.gz", hash = "sha256:eb9bfb14ab8f68d9d9492d4817ae497788a15fd7da72e14dfabc289c3bb088ec"}, +] + +[[package]] +name = "packageurl-python" +version = "0.16.0" +description = "A purl aka. Package URL parser and builder" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packageurl_python-0.16.0-py3-none-any.whl", hash = "sha256:5c3872638b177b0f1cf01c3673017b7b27ebee485693ae12a8bed70fa7fa7c35"}, + {file = "packageurl_python-0.16.0.tar.gz", hash = "sha256:69e3bf8a3932fe9c2400f56aaeb9f86911ecee2f9398dbe1b58ec34340be365d"}, ] +[package.extras] +build = ["setuptools", "wheel"] +lint = ["black", "isort", "mypy"] +sqlalchemy = ["sqlalchemy (>=2.0.0)"] +test = ["pytest"] + [[package]] name = "packaging" version = "24.1" @@ -1786,29 +1832,29 @@ files = [ [[package]] name = "ruff" -version = "0.8.6" +version = "0.8.4" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:defed167955d42c68b407e8f2e6f56ba52520e790aba4ca707a9c88619e580e3"}, - {file = "ruff-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:54799ca3d67ae5e0b7a7ac234baa657a9c1784b48ec954a094da7c206e0365b1"}, - {file = "ruff-0.8.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e88b8f6d901477c41559ba540beeb5a671e14cd29ebd5683903572f4b40a9807"}, - {file = "ruff-0.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0509e8da430228236a18a677fcdb0c1f102dd26d5520f71f79b094963322ed25"}, - {file = "ruff-0.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91a7ddb221779871cf226100e677b5ea38c2d54e9e2c8ed847450ebbdf99b32d"}, - {file = "ruff-0.8.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:248b1fb3f739d01d528cc50b35ee9c4812aa58cc5935998e776bf8ed5b251e75"}, - {file = "ruff-0.8.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:bc3c083c50390cf69e7e1b5a5a7303898966be973664ec0c4a4acea82c1d4315"}, - {file = "ruff-0.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52d587092ab8df308635762386f45f4638badb0866355b2b86760f6d3c076188"}, - {file = "ruff-0.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61323159cf21bc3897674e5adb27cd9e7700bab6b84de40d7be28c3d46dc67cf"}, - {file = "ruff-0.8.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ae4478b1471fc0c44ed52a6fb787e641a2ac58b1c1f91763bafbc2faddc5117"}, - {file = "ruff-0.8.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0c000a471d519b3e6cfc9c6680025d923b4ca140ce3e4612d1a2ef58e11f11fe"}, - {file = "ruff-0.8.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9257aa841e9e8d9b727423086f0fa9a86b6b420fbf4bf9e1465d1250ce8e4d8d"}, - {file = "ruff-0.8.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:45a56f61b24682f6f6709636949ae8cc82ae229d8d773b4c76c09ec83964a95a"}, - {file = "ruff-0.8.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:496dd38a53aa173481a7d8866bcd6451bd934d06976a2505028a50583e001b76"}, - {file = "ruff-0.8.6-py3-none-win32.whl", hash = "sha256:e169ea1b9eae61c99b257dc83b9ee6c76f89042752cb2d83486a7d6e48e8f764"}, - {file = "ruff-0.8.6-py3-none-win_amd64.whl", hash = "sha256:f1d70bef3d16fdc897ee290d7d20da3cbe4e26349f62e8a0274e7a3f4ce7a905"}, - {file = "ruff-0.8.6-py3-none-win_arm64.whl", hash = "sha256:7d7fc2377a04b6e04ffe588caad613d0c460eb2ecba4c0ccbbfe2bc973cbc162"}, - {file = "ruff-0.8.6.tar.gz", hash = "sha256:dcad24b81b62650b0eb8814f576fc65cfee8674772a6e24c9b747911801eeaa5"}, + {file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"}, + {file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"}, + {file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"}, + {file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"}, + {file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"}, + {file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"}, + {file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"}, ] [[package]] @@ -2433,4 +2479,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.0" python-versions = ">=3.11,<=3.13" -content-hash = "693d94dff64b7f5f7bd582ed18b8b8e86957ffa53a093421632fbaa459717c3e" +content-hash = "ee94b29d4c08570431fdbda54177b52347ae3d7f250af0c9f936456eef9199e1" diff --git a/pyproject.toml b/pyproject.toml index 252b4750..f5370225 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,8 @@ pytest-snapshot = "^0.9.0" mashumaro = "^3.10" iso8601 = "^2.1.0" zstandard = ">=0.22,<0.24" +packageurl-python = "^0.16.0" +deepdiff = "^8.0.1" [tool.poetry.group.dev.dependencies] pytest = ">=7.2.2,<9.0.0" @@ -110,8 +112,8 @@ exclude = '''(?x)( | ^src/vunnel/providers/mariner/model/ # generated code | ^src/vunnel/providers/nvd/parser\.py$ # ported from enterprise, never had type hints | ^src/vunnel/providers/oracle/parser\.py$ # ported from enterprise, never had type hints - | ^src/vunnel/providers/rhel/parser\.py$ # ported from enterprise, never had type hints - | ^src/vunnel/providers/rhel/oval_parser\.py$ # ported from enterprise, never had type hints + | ^src/vunnel/providers/rhel_legacy/parser\.py$ # ported from enterprise, never had type hints + | ^src/vunnel/providers/rhel_legacy/oval_parser\.py$ # ported from enterprise, never had type hints | ^src/vunnel/providers/sles/parser\.py$ # ported from enterprise, never had type hints | ^src/vunnel/providers/ubuntu/git\.py$ # ported from enterprise, never had type hints | ^src/vunnel/providers/ubuntu/parser\.py$ # ported from enterprise, never had type hints diff --git a/src/vunnel/providers/__init__.py b/src/vunnel/providers/__init__.py index 92e7bcd6..3a1a309c 100644 --- a/src/vunnel/providers/__init__.py +++ b/src/vunnel/providers/__init__.py @@ -14,6 +14,7 @@ nvd, oracle, rhel, + rhel_csaf, sles, ubuntu, wolfi, @@ -31,6 +32,7 @@ nvd.Provider.name(): nvd.Provider, oracle.Provider.name(): oracle.Provider, rhel.Provider.name(): rhel.Provider, + rhel_csaf.Provider.name(): rhel_csaf.Provider, sles.Provider.name(): sles.Provider, ubuntu.Provider.name(): ubuntu.Provider, wolfi.Provider.name(): wolfi.Provider, diff --git a/src/vunnel/providers/rhel/__init__.py b/src/vunnel/providers/rhel/__init__.py index 860b4d35..b886401c 100644 --- a/src/vunnel/providers/rhel/__init__.py +++ b/src/vunnel/providers/rhel/__init__.py @@ -1,15 +1,14 @@ -from __future__ import annotations - -import os +import datetime from dataclasses import dataclass, field -from typing import TYPE_CHECKING - -from vunnel import provider, result, schema -from .parser import Parser +from vunnel import provider, result +from vunnel.providers.rhel_csaf import Config as CSAFConfig +from vunnel.providers.rhel_csaf import Provider as RHEL_CSAFProvider +from vunnel.providers.rhel_legacy import Config as LegacyConfig +from vunnel.providers.rhel_legacy import Provider as LegacyRHELProvider -if TYPE_CHECKING: - import datetime +CSAF_PROVIDER = "csaf" +LEGACY_PROVIDER = "legacy" @dataclass @@ -24,43 +23,49 @@ class Config: parallelism: int = 4 full_sync_interval: int = 2 skip_namespaces: list[str] = field(default_factory=lambda: ["rhel:3", "rhel:4"]) + provider_type: str = CSAF_PROVIDER # "legacy" or "csaf" + def to_specific_config(self) -> LegacyConfig | CSAFConfig: + if self.provider_type == LEGACY_PROVIDER: + return LegacyConfig( + runtime=self.runtime, + request_timeout=self.request_timeout, + parallelism=self.parallelism, + full_sync_interval=self.full_sync_interval, + skip_namespaces=self.skip_namespaces, + ) + if self.provider_type == CSAF_PROVIDER: + # other fields don't make sense for CSAF Provider + return CSAFConfig( + runtime=self.runtime, + skip_namespaces=self.skip_namespaces, + ) + raise ValueError(f"invalid config type {self.provider_type}, expected '{LEGACY_PROVIDER}' or '{CSAF_PROVIDER}'") -class Provider(provider.Provider): - - __schema__ = schema.OSSchema() - __distribution_version__ = int(__schema__.major_version) +class Provider(provider.Provider): def __init__(self, root: str, config: Config | None = None): if not config: config = Config() super().__init__(root, runtime_cfg=config.runtime) + self.logger.info(f"config: {config}") + self._provider_instance: RHEL_CSAFProvider | LegacyRHELProvider | None = None + specific_config = config.to_specific_config() + if isinstance(specific_config, CSAFConfig): + self.logger.info(f"Using provider: {config.provider_type}") + self._provider_instance = RHEL_CSAFProvider(root, specific_config) + elif isinstance(specific_config, LegacyConfig): + self.logger.info(f"Using provider: {config.provider_type}") + self._provider_instance = LegacyRHELProvider(root, specific_config) + else: + raise ValueError(f"unknown provider type {config.provider_type}, expected {LEGACY_PROVIDER} or {CSAF_PROVIDER}") self.config = config - self.logger.debug(f"config: {config}") - - self.parser = Parser( - workspace=self.workspace, - download_timeout=self.config.request_timeout, - max_workers=self.config.parallelism, - full_sync_interval=self.config.full_sync_interval, - skip_namespaces=self.config.skip_namespaces, - logger=self.logger, - ) - @classmethod def name(cls) -> str: return "rhel" - def update(self, last_updated: datetime.datetime | None) -> tuple[list[str], int]: - with self.results_writer() as writer: - for namespace, vuln_id, record in self.parser.get(skip_if_exists=self.config.runtime.skip_if_exists): - namespace = namespace.lower() - vuln_id = vuln_id.lower() - writer.write( - identifier=os.path.join(namespace, vuln_id), - schema=self.__schema__, - payload=record, - ) - - return self.parser.urls, len(writer) + def update(self, last_updated: datetime.datetime | None = None) -> tuple[list[str], int]: + if not self._provider_instance: + raise ValueError("attempt to call update on delegating provider with no underlying provider") + return self._provider_instance.update(last_updated) diff --git a/src/vunnel/providers/rhel_csaf/__init__.py b/src/vunnel/providers/rhel_csaf/__init__.py new file mode 100644 index 00000000..bd54224a --- /dev/null +++ b/src/vunnel/providers/rhel_csaf/__init__.py @@ -0,0 +1,50 @@ +import datetime +import os +from dataclasses import dataclass, field + +from vunnel import provider, result, schema + +from .parser import Parser + + +@dataclass +class Config: + runtime: provider.RuntimeConfig = field( + default_factory=lambda: provider.RuntimeConfig( + result_store=result.StoreStrategy.SQLITE, + existing_results=result.ResultStatePolicy.DELETE_BEFORE_WRITE, + ), + ) + skip_namespaces: list[str] = field(default_factory=lambda: ["rhel:3", "rhel:4"]) + + +class Provider(provider.Provider): + + __schema__ = schema.OSSchema() + __distribution_version__ = int(__schema__.major_version) + + def __init__(self, root: str, config: Config | None = None): + if not config: + config = Config() + super().__init__(root, runtime_cfg=config.runtime) + self.config = config + + self.logger.debug(f"config: {config}") + self.parser = Parser(workspace=self.workspace, logger=self.logger) + + @classmethod + def name(cls) -> str: + return "rhel" + + def update(self, last_updated: datetime.datetime | None) -> tuple[list[str], int]: + with self.results_writer() as writer: + for namespace, vuln_id, record in self.parser.get(skip_if_exists=self.config.runtime.skip_if_exists): + namespace = namespace.lower() + vuln_id = vuln_id.lower() + writer.write( + identifier=os.path.join(namespace, vuln_id), + schema=self.__schema__, + payload=record, + ) + + return self.parser.urls, len(writer) diff --git a/src/vunnel/providers/rhel_csaf/parser.py b/src/vunnel/providers/rhel_csaf/parser.py new file mode 100644 index 00000000..9c38bd70 --- /dev/null +++ b/src/vunnel/providers/rhel_csaf/parser.py @@ -0,0 +1,146 @@ +import concurrent.futures +import contextlib +import csv +import logging +import os +from collections.abc import Generator +from datetime import datetime, timezone +from typing import Any + +from vunnel.providers.rhel_csaf.transformer import vulnerabilities_by_namespace +from vunnel.utils import http +from vunnel.utils.archive import extract +from vunnel.utils.csaf_types import from_path +from vunnel.utils.vulnerability import Vulnerability +from vunnel.workspace import Workspace + +VEX_LATEST_URL = "https://security.access.redhat.com/data/csaf/v2/vex/archive_latest.txt" +VEX_CHANGES_URL = "https://security.access.redhat.com/data/csaf/v2/vex/changes.csv" +VEX_DELETIONS_URL = "https://security.access.redhat.com/data/csaf/v2/vex/deletions.csv" +ADVISORIES_LATEST_URL = "https://security.access.redhat.com/data/csaf/v2/advisories/archive_latest.txt" + + +class Parser: + def __init__( + self, + workspace: Workspace, + download_timeout: int | None = None, + skip_namespaces: list[str] | None = None, + logger: logging.Logger | None = None, + ): + self.workspace = workspace + self.download_timeout = download_timeout if isinstance(download_timeout, int) else 125 + self.skip_namespaces = skip_namespaces if isinstance(skip_namespaces, list) else ["rhel:3", "rhel:4"] + self.rhsa_dict = None + self.urls: list[str] = [] + self.vex_archive_date: datetime | None = None + + self.download_path = os.path.join(self.workspace.input_path, "vex_archive.tar.zst") + self.advisory_download_path = os.path.join(self.workspace.input_path, "advisory_archive.tar.zst") + self.csaf_path = os.path.join(self.workspace.input_path, "csaf") + os.makedirs(self.csaf_path, exist_ok=True) + self.advisories_path = os.path.join(self.workspace.input_path, "advisories") + + if not logger: + logger = logging.getLogger(self.__class__.__name__) + self.logger = logger + self.logger.debug("starting of RHEL CSAF parser") + + def get_archive_date(self, archive_filename: str) -> datetime: + date_part = archive_filename.removeprefix("csaf_vex_").removesuffix(".tar.zst") + return datetime.strptime(date_part, "%Y-%m-%d").replace(tzinfo=timezone.utc) # noqa: UP017 + + def download_stream(self, url: str, dest: str) -> None: + with http.get(url, logger=self.logger, stream=True) as resp, open(dest, "wb") as fh: + for chunk in resp.iter_content(chunk_size=65536): # 64k chunks + if chunk: + fh.write(chunk) + + def download_vex_archive(self) -> None: + latest_resp = http.get(url=VEX_LATEST_URL, logger=self.logger) + archive_filename = latest_resp.content.decode() + self.vex_archive_date = self.get_archive_date(archive_filename) + archive_url = VEX_LATEST_URL.replace("archive_latest.txt", archive_filename) + self.urls = [archive_url] + self.download_stream(archive_url, self.download_path) + changes_path = os.path.join(self.csaf_path, "changes.csv") + self.download_stream(VEX_CHANGES_URL, changes_path) + deletions_path = os.path.join(self.csaf_path, "deletions.csv") + self.download_stream(VEX_DELETIONS_URL, deletions_path) + + def extract_all(self) -> None: + os.makedirs(self.csaf_path, exist_ok=True) + extract(self.download_path, self.csaf_path) + + def process_changes_and_deletions(self) -> None: + """process the changes and deletions. deletions.csv is the list of CSAF JSON + files that have been deleted. Download it and loop over it, deleting all + referenced files. changes.csv is a date-sorted list of when each CSAF JSON + file changed. Download it, and loop over the rows, until we get back to the + date of the archive, keeping a list of unique files, to get the set of files + that have changed since the archive was published. Re-download all of them, over-writing + whatever data was in the archive.""" + changes_path = os.path.join(self.csaf_path, "changes.csv") + deletions_path = os.path.join(self.csaf_path, "deletions.csv") + with open(deletions_path, newline="") as fh: + reader = csv.reader(fh) + for row in reader: + deleted_fragment = row[0] + # suppress FileNotFound because deleting the same file twice + # should no-op rather than raise an error + with contextlib.suppress(FileNotFoundError): + os.remove(os.path.join(self.csaf_path, deleted_fragment)) + seen_files = set() + with open(changes_path, newline="") as fh: + reader = csv.reader(fh) + for row in reader: + # row is like "2021/cve-2021-47265.json","2024-11-08T18:28:22+00:00" + changed_file = row[0] + date_str = row[1] + change_date = datetime.fromisoformat(date_str) + if self.vex_archive_date and change_date < self.vex_archive_date: + break + if changed_file in seen_files: + continue + seen_files.add(changed_file) + with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor: + futures = { + executor.submit( + self.download_stream, + url=VEX_LATEST_URL.replace("archive_latest.txt", changed_file), + dest=os.path.join(self.csaf_path, changed_file), + ): changed_file + for changed_file in seen_files + } + concurrent.futures.wait(futures.keys()) + for future, changed_file in futures.items(): + if future.exception() is not None: + self.logger.warning(f"Failed to download {changed_file}: {future.exception()}") + + def fetch(self) -> None: + self.download_vex_archive() + self.extract_all() + self.process_changes_and_deletions() + + def _csaf_vex_files(self) -> Generator[str]: + for root, _, files in os.walk(self.csaf_path): + for file in files: + if file.endswith(".json"): + yield os.path.join(root, file) + + def process(self) -> Generator[tuple[str, str, Vulnerability]]: + for file_path in self._csaf_vex_files(): + try: + self.logger.debug(f"processing {file_path}") + c = from_path(file_path) + ns_to_vulns = vulnerabilities_by_namespace(c, set(self.skip_namespaces)) + for ns, vuln in ns_to_vulns.items(): + yield ns, vuln.Name, vuln + + except Exception as e: + self.logger.warning(f"failed to process {file_path}: {e}") + + def get(self, skip_if_exists: bool = False) -> Generator[tuple[str, str, dict[str, Any]]]: + self.fetch() + for namespace, vuln_id, record in self.process(): + yield namespace, vuln_id, record.to_payload() diff --git a/src/vunnel/providers/rhel_csaf/transformer.py b/src/vunnel/providers/rhel_csaf/transformer.py new file mode 100644 index 00000000..af846790 --- /dev/null +++ b/src/vunnel/providers/rhel_csaf/transformer.py @@ -0,0 +1,245 @@ +import re + +from packageurl import PackageURL + +from vunnel.utils.csaf_types import CSAFDoc, Score +from vunnel.utils.vulnerability import CVSS, AdvisorySummary, FixedIn, VendorAdvisory, Vulnerability + +RHEL_CPE_REGEXES = [ + r"^cpe:/[ao]:redhat:enterprise_linux:(\d+)(::(client|server|workstation|appstream|baseos|realtime|crb|supplementary))*$", # appstream has :a: + r"^cpe:/a:redhat:rhel_extras_rt:(\d+)", + r"^cpe:/a:redhat:rhel_extras_rt:(\d+)", + r"^cpe:/a:redhat:rhel_virtualization:(\d+)(::(client|server))?", +] + +SEVERITY_DICT = { + "low": "Low", + "moderate": "Medium", + "important": "High", + "critical": "Critical", +} + + +class NamespaceMatcher: + def __init__(self, csaf: CSAFDoc): + prefixes_to_namespaces = {} + for b in csaf.product_tree.branches[0].product_name_branches(): + prefix = b.product_id() + cpe = b.cpe() + if not (cpe and prefix): + continue + for r in RHEL_CPE_REGEXES: + match = re.search(r, cpe) + if match: + version = match.group(1) + ns = f"rhel:{version}" + prefixes_to_namespaces[prefix] = ns + self.prefixes_to_namespaces = prefixes_to_namespaces + + def namespace_from_product_id(self, pid: str) -> str | None: + for prefix, ns in self.prefixes_to_namespaces.items(): + if pid.startswith(prefix): + return ns + return None + + +class NameFilter: + def __init__(self, csaf: CSAFDoc): + affected_top_level_products = [] + for b in csaf.product_tree.branches[0].branches: + if b.category == "product_version" and b.product and b.product.product_id: + affected_top_level_products.append(b.product.product_id) + + versionless_source_rpms = [] + rpm_module_names = [] + for b in csaf.product_tree.branches[0].product_version_branches(): + maybe_purl = b.purl() + if maybe_purl: + purl = PackageURL.from_string(maybe_purl) + if purl and purl.qualifiers and isinstance(purl.qualifiers, dict): # noqa: SIM102 + if purl.qualifiers.get("arch") in ["src", "noarch"] and not purl.version: + versionless_source_rpms.append(purl.name) + + if purl.type == "rpmmod" and purl.name: + rpm_module_names.append(purl.name) + self.included = set(affected_top_level_products + versionless_source_rpms + rpm_module_names) + + def include(self, product_name: str) -> bool: + return product_name in self.included + + +def base_vulnerability(csaf: CSAFDoc, namespace_name: str) -> Vulnerability: + if len(csaf.vulnerabilities) != 1: + raise ValueError("unexpected document type; RHEL VEX CSAF documents should have exactly 1 vulnerability per document") + cve_id = csaf.vulnerabilities[0].cve + severity = SEVERITY_DICT.get(csaf.document.aggregate_severity.text.lower(), "Unknown") + description = next((n.text for n in csaf.vulnerabilities[0].notes if n.category == "description"), "") + link = next((r.url for r in csaf.vulnerabilities[0].references or [] if r.category == "self"), "") + return Vulnerability( + Name=cve_id, + NamespaceName=namespace_name, + Description=description, + Severity=severity, + Link=link, + CVSS=[], + FixedIn=[], + ) + + +def parse_cvss(scores: list[Score], status: str, full_product_id: str) -> CVSS | None: + for s in scores: + if full_product_id in s.products and s.cvss_v3: + return s.to_vunnel_cvss(status) + return None + + +def vulnerabilities_by_namespace( # noqa: C901, PLR0912, PLR0915 + csaf: CSAFDoc, + skip_namespaces: set[str] | None = None, +) -> dict[str, Vulnerability]: + """ + namespace -> vulnerabilities -> fixed-ins + { + "rhel:8": [ + { + "Name": "CVE-12345", + "FixedIn": [], + } + ] + } + """ + if len(csaf.vulnerabilities) != 1: + # This parser was probably called on a CSAFDoc that's not a RHEL CSAF VEX doc, for example on an RHSA CSAFDoc. + # It doesn't know how to parse those. + raise ValueError("unexpected document type; RHEL VEX CSAF documents should have exactly 1 vulnerability per document") + + vuln = csaf.vulnerabilities[0] + if not vuln.product_status: + return {} + + if not csaf.product_tree.branches: + return {} + + ns_matcher = NamespaceMatcher(csaf=csaf) + ns_to_vulnerability = {} + module_pid_to_purl = {} + # Keep a map of product IDs that represent modules to the PURLs + # so that we can accurately get module version info later. + for b in csaf.product_tree.branches[0].product_version_branches(): + if b.product and b.product.product_identification_helper and b.product.product_identification_helper.purl: + purl_str = b.product.product_identification_helper.purl + purl = PackageURL.from_string(purl_str) + if purl.type == "rpmmod": + module_pid_to_purl[b.product.product_id] = purl + + name_filter = NameFilter(csaf=csaf) + seen_already = set() + + for b in csaf.product_tree.branches[0].product_version_branches(): + if b.product and b.product.product_identification_helper and b.product.product_identification_helper.purl: + purl_str = b.product.product_identification_helper.purl + purl = PackageURL.from_string(purl_str) + if purl.type not in ["rpm", "rpmmod"]: + continue + product_id = b.product.product_id + qualified_product_ids = [ + r.full_product_name.product_id for r in csaf.product_tree.relationships if r.product_reference == product_id + ] + + for qpi in qualified_product_ids: + vendor_advisory = VendorAdvisory(NoAdvisory=True, AdvisorySummary=[]) + name = purl.name + + namespace_name = ns_matcher.namespace_from_product_id(qpi) + if not namespace_name: + continue + if skip_namespaces and namespace_name in skip_namespaces: + continue + if namespace_name not in ns_to_vulnerability: + ns_to_vulnerability[namespace_name] = base_vulnerability(csaf, namespace_name) + version_format = "rpm" + version = "None" + module = None + if purl.type == "rpmmod": + if purl.namespace: + if not purl.namespace.startswith("redhat/"): + # We see two kinds of "rpmmod" type PURLs: + # "pkg:rpmmod/redhat/ruby@3.0:8060020220810162001:ad008a3a" + # with namespace "redhat" (no /) and "pkg:rpmmod/redhat/ruby:2.6/ruby" + # with namespace "redhat/ruby:2.6". + # The second kind is really a package namespaced into a module + # e.g ruby as part of ruby:2.6 module, and we should keep those. + # The first kind is a module going to contain many packages, and we'll + # pick those when we do the component packages. + continue + module = purl.namespace.removeprefix("redhat/") + else: # "rpm" + module_pid = None + parent = csaf.product_tree.parent(qpi) + if not parent: + # TODO: log a warning - got a leaf product with no parent distro or module + continue + grand_parent = csaf.product_tree.parent(parent or "NONE") + if grand_parent: + module_pid = parent.removeprefix(grand_parent).removeprefix(":") + if not module_pid: + module_pid = csaf.product_tree.second_parent(qpi) + if module_pid: + module_purl = module_pid_to_purl.get(module_pid) + if module_purl and module_purl.version: + module = f"{module_purl.name}:{module_purl.version.split(':')[0]}" + if qpi in vuln.product_status.fixed: + # a module might be patched all at once, in which case + # there are "fixed" products that were never vulnerable. + # Check whether each fixed product was reported in the top of the + # doc before emitting a FixedIn for it. + # Therefore, only include packages that are part of a module if the + # name filter includes them + if module and not name_filter.include(purl.name): + continue + if purl.version: + version = purl.version + remediations = [r for r in vuln.remediations if qpi in r.product_ids] + if remediations and remediations[0].url: + vendor_advisory = VendorAdvisory( + NoAdvisory=False, + AdvisorySummary=[ + AdvisorySummary(Link=remediations[0].url or "", ID=remediations[0].url.split("/")[-1]), + ], + ) + elif qpi in vuln.product_status.known_affected: + version = "None" + elif qpi in vuln.product_status.known_not_affected: + continue + elif qpi in vuln.product_status.under_investigation: + # TODO: should this be configurable? + continue + + if version != "None" and ":" not in version: + epoch = purl.qualifiers.get("epoch", "0") if purl.qualifiers and isinstance(purl.qualifiers, dict) else "0" + version = f"{epoch}:{version}" + + fi_tuple = (name, namespace_name, version_format, version, module) + if fi_tuple in seen_already: + continue + + seen_already.add(fi_tuple) + + fixed_in = FixedIn( + Name=name, + NamespaceName=namespace_name, + VersionFormat=version_format, + Version=version, + VendorAdvisory=vendor_advisory, + Module=module, + ) + ns_to_vulnerability[namespace_name].FixedIn.append(fixed_in) + # The CSAF spec permits many scores to be defined per document, + # associating each score with a set of product IDs. Vunnel permits + # many scores per vulnerability record, but no way to associate + if not ns_to_vulnerability[namespace_name].CVSS: + maybe_cvss = parse_cvss(csaf.vulnerabilities[0].scores, csaf.document.tracking.status, qpi) + if maybe_cvss: + ns_to_vulnerability[namespace_name].CVSS.append(maybe_cvss) + + return ns_to_vulnerability diff --git a/src/vunnel/providers/rhel_legacy/__init__.py b/src/vunnel/providers/rhel_legacy/__init__.py new file mode 100644 index 00000000..860b4d35 --- /dev/null +++ b/src/vunnel/providers/rhel_legacy/__init__.py @@ -0,0 +1,66 @@ +from __future__ import annotations + +import os +from dataclasses import dataclass, field +from typing import TYPE_CHECKING + +from vunnel import provider, result, schema + +from .parser import Parser + +if TYPE_CHECKING: + import datetime + + +@dataclass +class Config: + runtime: provider.RuntimeConfig = field( + default_factory=lambda: provider.RuntimeConfig( + result_store=result.StoreStrategy.SQLITE, + existing_results=result.ResultStatePolicy.DELETE_BEFORE_WRITE, + ), + ) + request_timeout: int = 125 + parallelism: int = 4 + full_sync_interval: int = 2 + skip_namespaces: list[str] = field(default_factory=lambda: ["rhel:3", "rhel:4"]) + + +class Provider(provider.Provider): + + __schema__ = schema.OSSchema() + __distribution_version__ = int(__schema__.major_version) + + def __init__(self, root: str, config: Config | None = None): + if not config: + config = Config() + super().__init__(root, runtime_cfg=config.runtime) + self.config = config + + self.logger.debug(f"config: {config}") + + self.parser = Parser( + workspace=self.workspace, + download_timeout=self.config.request_timeout, + max_workers=self.config.parallelism, + full_sync_interval=self.config.full_sync_interval, + skip_namespaces=self.config.skip_namespaces, + logger=self.logger, + ) + + @classmethod + def name(cls) -> str: + return "rhel" + + def update(self, last_updated: datetime.datetime | None) -> tuple[list[str], int]: + with self.results_writer() as writer: + for namespace, vuln_id, record in self.parser.get(skip_if_exists=self.config.runtime.skip_if_exists): + namespace = namespace.lower() + vuln_id = vuln_id.lower() + writer.write( + identifier=os.path.join(namespace, vuln_id), + schema=self.__schema__, + payload=record, + ) + + return self.parser.urls, len(writer) diff --git a/src/vunnel/providers/rhel/oval_parser.py b/src/vunnel/providers/rhel_legacy/oval_parser.py similarity index 100% rename from src/vunnel/providers/rhel/oval_parser.py rename to src/vunnel/providers/rhel_legacy/oval_parser.py diff --git a/src/vunnel/providers/rhel/parser.py b/src/vunnel/providers/rhel_legacy/parser.py similarity index 100% rename from src/vunnel/providers/rhel/parser.py rename to src/vunnel/providers/rhel_legacy/parser.py diff --git a/src/vunnel/utils/csaf_types.py b/src/vunnel/utils/csaf_types.py new file mode 100644 index 00000000..9948917d --- /dev/null +++ b/src/vunnel/utils/csaf_types.py @@ -0,0 +1,415 @@ +import re +from dataclasses import dataclass, field +from decimal import Decimal + +import orjson +from cvss import CVSS3 +from cvss.exceptions import CVSS3Error +from mashumaro import field_options +from mashumaro.config import BaseConfig +from mashumaro.mixins.dict import DataClassDictMixin + +from vunnel.utils.vulnerability import CVSS, CVSSBaseMetrics + + +# TODO: is this still doing anything? +# Custom Config to handle camel case for mashumaro +class CamelCaseConfig(BaseConfig): + @staticmethod + def decode_field(name: str) -> str: + # Convert camelCase to snake_case + return re.sub(r"(? CVSS | None: + if self.cvss_v3: + try: + cvss3_obj = CVSS3(self.cvss_v3.vector_string) + return CVSS( + version=self.cvss_v3.version, + vector_string=self.cvss_v3.vector_string, + base_metrics=CVSSBaseMetrics( + base_score=self.cvss_v3.base_score, + exploitability_score=float(cvss3_obj.esc.quantize(Decimal("1.0"))), + impact_score=float(cvss3_obj.isc.quantize(Decimal("1.0"))), + base_severity=cvss3_obj.severities()[0], + ), + status=status, + ) + except CVSS3Error: + return None + # TODO: handle CVSS v2 + return None + + +@dataclass +class Vulnerability(DataClassDictMixin): + title: str + cve: str + cwe: str | None = None + discovery_date: str | None = None + flags: list[Flag] = field(default_factory=list) + ids: list[VulnID] = field(default_factory=list) + notes: list[Note] = field(default_factory=list) + product_status: ProductStatus | None = None + references: list[Reference] | None = None + release_date: str | None = None + remediations: list[Remediation] = field(default_factory=list) + scores: list[Score] = field(default_factory=list) + threats: list[Threat] = field(default_factory=list) + + def all_advisory_urls(self) -> set[str]: + result = set() + for r in self.remediations: + if r.category == "vendor_fix" and r.url: + result.add(r.url) + + return result + + def advisory_url_for_product(self, product_id: str) -> str | None: + for r in self.remediations: + if r.category == "vendor_fix" and product_id in r.product_ids: + return r.url + return None + + +@dataclass +class FullProductName(DataClassDictMixin): + name: str + product_id: str + + +@dataclass +class Relationship(DataClassDictMixin): + category: str + full_product_name: FullProductName + product_reference: str + relates_to_product_reference: str + + +@dataclass +class ProductIdentificationHelper(DataClassDictMixin): + cpe: str | None = None + purl: str | None = None + + +@dataclass +class Product(DataClassDictMixin): + name: str + product_id: str + product_identification_helper: ProductIdentificationHelper | None = None + + +@dataclass +class Branch: + category: str + name: str + branches: list["Branch"] = field(default_factory=list) + product: Product | None = None + + def acculumulate_categories_recursively(self, accumulator: set[str]) -> None: + accumulator.add(self.category) + for b in self.branches: + b.acculumulate_categories_recursively(accumulator) + + def source_rpm_product_ids(self) -> set[str]: + result = set() + if ( + self.product + and self.product.product_identification_helper + and ( + ( + self.product.product_identification_helper.purl + and "arch=src" in self.product.product_identification_helper.purl + ) + or re.search(r"\.el\d+.src$", self.product.product_id) + ) + ): + result.add(self.product.product_id) + + for b in self.branches: + result = result | b.source_rpm_product_ids() + return result + + def purl(self) -> str | None: + if self.product and self.product.product_identification_helper: + return self.product.product_identification_helper.purl + return None + + def cpe(self) -> str | None: + if self.product and self.product.product_identification_helper: + return self.product.product_identification_helper.cpe + return None + + def product_id(self) -> str | None: + if self.product: + return self.product.product_id + return None + + def product_branches(self) -> list["Branch"]: + result = [] + for b in self.branches: + if b.product: + result.append(b) + elif b.branches: + result.extend(b.product_branches()) + return result + + def product_version_branches(self) -> list["Branch"]: + result = [] + if self.category == "product_version": + result.append(self) + for b in self.branches: + result.extend(b.product_version_branches()) + + return result + + def product_name_branches(self) -> list["Branch"]: + result = [] + if self.category == "product_name": + result.append(self) + for b in self.branches: + result.extend(b.product_name_branches()) + + return result + + +@dataclass +class ProductTree(DataClassDictMixin): + relationships: list[Relationship] = field(default_factory=list) + branches: list[Branch] = field(default_factory=list) + product_id_to_parent: dict[str, str] = field(init=False) + + def __post_init__(self) -> None: + self.product_id_to_parent = {} + for r in self.relationships: + self.product_id_to_parent[r.full_product_name.product_id] = r.relates_to_product_reference + + def parent(self, product_id: str) -> str | None: + return self.product_id_to_parent.get(product_id) + + def first_parent(self, product_id: str) -> str: + here: str | None = product_id + last_product_id = product_id + while here: + last_product_id = here + here = self.parent(here) + return last_product_id + + def second_parent(self, product_id: str) -> str | None: + root = self.first_parent(product_id) # Find the root using first_parent + here: str | None = product_id + previous = None + + # Traverse up the tree until we reach the root + while here and here != root: + previous = here # Track the child of the root + here = self.parent(here) # Move up one level + + if previous != product_id: + return previous + return None + + def distinct_branch_categories(self) -> set[str]: + result: set[str] = set() + for b in self.branches: + b.acculumulate_categories_recursively(result) + + return result + + def has_ancestor(self, product_id: str, maybe_ancestor_id: str) -> bool: + parent = self.parent(product_id) + while parent: + if parent == maybe_ancestor_id: + return True + parent = self.parent(parent) + return False + + def product_branches(self) -> list[Branch]: + result = [] + for b in self.branches: + if b.product: + result.append(b) + else: + result.extend(b.product_branches()) + return result + + +@dataclass +class AggregateSeverity(DataClassDictMixin): + namespace: str + text: str + + +@dataclass +class TLP(DataClassDictMixin): + label: str + url: str + + +@dataclass +class Distribution(DataClassDictMixin): + text: str + tlp: TLP + + +@dataclass +class Publisher(DataClassDictMixin): + category: str + contact_details: str + issuing_authority: str + name: str + namespace: str + + +@dataclass +class GeneratorEngine(DataClassDictMixin): + name: str + version: str + + +@dataclass +class Generator(DataClassDictMixin): + date: str + engine: GeneratorEngine + + +@dataclass +class RevisionEntry(DataClassDictMixin): + date: str + number: str # yes, really + summary: str + + +@dataclass +class Tracking(DataClassDictMixin): + current_release_date: str + generator: Generator + id: str + initial_release_date: str + revision_history: list[RevisionEntry] + status: str + version: str + + +@dataclass +class Document(DataClassDictMixin): + aggregate_severity: AggregateSeverity + category: str + csaf_version: str + distribution: Distribution + lang: str + notes: list[Note] + publisher: Publisher + references: list[Reference] + title: str + tracking: Tracking + + +@dataclass +class CSAFDoc(DataClassDictMixin): + document: Document + product_tree: ProductTree + vulnerabilities: list[Vulnerability] + + +def from_path(path: str) -> CSAFDoc: + with open(path) as fh: + data = orjson.loads(fh.read()) + return CSAFDoc.from_dict(data) diff --git a/tests/quality/Makefile b/tests/quality/Makefile index 1dac65da..716bbca9 100644 --- a/tests/quality/Makefile +++ b/tests/quality/Makefile @@ -32,6 +32,9 @@ validate: ## Run all quality checks against already collected data ## Data management targets ################################# +.PHONY: scan +scan: sboms vulns + .PHONY: capture capture: clear-data clear-results configure sboms build-db vulns ## Collect and store all syft and grype results relative to the given provider diff --git a/tests/quality/config.yaml b/tests/quality/config.yaml index 31165ac1..97201f60 100644 --- a/tests/quality/config.yaml +++ b/tests/quality/config.yaml @@ -223,7 +223,9 @@ tests: - docker.io/anchore/test_images:appstreams-rhel-8-1a287dd@sha256:524ff8a75f21fd886ec7ed82387766df386671e8b77e898d05786118d5b7880b - docker.io/anchore/test_images:vulnerabilities-centos@sha256:746d31247006cc06434ce91ccf3523b2c230ff6c378ffed7ca1c60bbb48ea86f validations: - - *default-validations + - <<: *default-validations + max_f1_regression: 0.09 + expected_namespaces: - redhat:distro:redhat:5 diff --git a/tests/quality/vulnerability-match-labels b/tests/quality/vulnerability-match-labels index f213a4cf..8915ebaa 160000 --- a/tests/quality/vulnerability-match-labels +++ b/tests/quality/vulnerability-match-labels @@ -1 +1 @@ -Subproject commit f213a4cf4beb26b90dd4f6e6a9fa81985d6bae78 +Subproject commit 8915ebaa90638c15512afa1299a5cc4015d6a3b5 diff --git a/tests/unit/cli/test_cli.py b/tests/unit/cli/test_cli.py index 8a19e061..0eeceab9 100644 --- a/tests/unit/cli/test_cli.py +++ b/tests/unit/cli/test_cli.py @@ -284,6 +284,7 @@ def test_config(monkeypatch) -> None: rhel: full_sync_interval: 2 parallelism: 4 + provider_type: csaf request_timeout: 125 runtime: existing_input: keep diff --git a/tests/unit/providers/rhel/test_rhel_base_provider.py b/tests/unit/providers/rhel/test_rhel_base_provider.py new file mode 100644 index 00000000..cbdeb2c3 --- /dev/null +++ b/tests/unit/providers/rhel/test_rhel_base_provider.py @@ -0,0 +1,19 @@ +import pytest +from vunnel.providers.rhel import CSAF_PROVIDER, LEGACY_PROVIDER, Config, Provider +from vunnel.providers.rhel_csaf import Provider as CSAFProvider +from vunnel.providers.rhel_legacy import Provider as LegacyProvider + + +@pytest.mark.parametrize( + "config,expected_provider_type", + [ + (Config(), CSAFProvider), + (Config(provider_type="csaf"), CSAFProvider), + (Config(provider_type=CSAF_PROVIDER), CSAFProvider), + (Config(provider_type="legacy"), LegacyProvider), + (Config(provider_type=LEGACY_PROVIDER), LegacyProvider), + ], +) +def test_rhel_base_provider(config: Config, expected_provider_type, tmp_path): + p = Provider(root=tmp_path, config=config) + assert isinstance(p._provider_instance, expected_provider_type) diff --git a/tests/unit/providers/rhel/__init__.py b/tests/unit/providers/rhel_csaf/__init__.py similarity index 100% rename from tests/unit/providers/rhel/__init__.py rename to tests/unit/providers/rhel_csaf/__init__.py diff --git a/tests/unit/providers/rhel_csaf/test-fixtures/cve-2019-16161.json b/tests/unit/providers/rhel_csaf/test-fixtures/cve-2019-16161.json new file mode 100644 index 00000000..fa94e8ee --- /dev/null +++ b/tests/unit/providers/rhel_csaf/test-fixtures/cve-2019-16161.json @@ -0,0 +1,638 @@ +{ + "document": { + "aggregate_severity": { + "namespace": "https://access.redhat.com/security/updates/classification/", + "text": "low" + }, + "category": "csaf_vex", + "csaf_version": "2.0", + "distribution": { + "text": "Copyright © Red Hat, Inc. All rights reserved.", + "tlp": { + "label": "WHITE", + "url": "https://www.first.org/tlp/" + } + }, + "lang": "en", + "notes": [ + { + "category": "legal_disclaimer", + "text": "This content is licensed under the Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/). If you distribute this content, or a modified version of it, you must provide attribution to Red Hat Inc. and provide a link to the original.", + "title": "Terms of Use" + } + ], + "publisher": { + "category": "vendor", + "contact_details": "https://access.redhat.com/security/team/contact/", + "issuing_authority": "Red Hat Product Security is responsible for vulnerability handling across all Red Hat offerings.", + "name": "Red Hat Product Security", + "namespace": "https://www.redhat.com" + }, + "references": [ + { + "category": "self", + "summary": "Canonical URL", + "url": "https://access.redhat.com/security/data/csaf/v2/vex/2019/cve-2019-16161.json" + } + ], + "title": "onigmo: NULL pointer dereference in onig_error_code_to_str because of fetch_token in regparse.c", + "tracking": { + "current_release_date": "2024-08-19T17:53:36+00:00", + "generator": { + "date": "2024-08-19T17:53:36+00:00", + "engine": { + "name": "Red Hat SDEngine", + "version": "3.32.0" + } + }, + "id": "CVE-2019-16161", + "initial_release_date": "2019-07-28T00:00:00+00:00", + "revision_history": [ + { + "date": "2019-07-28T00:00:00+00:00", + "number": "1", + "summary": "Initial version" + }, + { + "date": "2021-10-25T09:55:24+00:00", + "number": "2", + "summary": "Current version" + }, + { + "date": "2024-08-19T17:53:36+00:00", + "number": "3", + "summary": "Last generated version" + } + ], + "status": "final", + "version": "3" + } + }, + "product_tree": { + "branches": [ + { + "branches": [ + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Enterprise Linux 5", + "product": { + "name": "Red Hat Enterprise Linux 5", + "product_id": "red_hat_enterprise_linux_5", + "product_identification_helper": { + "cpe": "cpe:/o:redhat:enterprise_linux:5" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Enterprise Linux 5" + }, + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Enterprise Linux 6", + "product": { + "name": "Red Hat Enterprise Linux 6", + "product_id": "red_hat_enterprise_linux_6", + "product_identification_helper": { + "cpe": "cpe:/o:redhat:enterprise_linux:6" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Enterprise Linux 6" + }, + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Enterprise Linux 7", + "product": { + "name": "Red Hat Enterprise Linux 7", + "product_id": "red_hat_enterprise_linux_7", + "product_identification_helper": { + "cpe": "cpe:/o:redhat:enterprise_linux:7" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Enterprise Linux 7" + }, + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Enterprise Linux 8", + "product": { + "name": "Red Hat Enterprise Linux 8", + "product_id": "red_hat_enterprise_linux_8", + "product_identification_helper": { + "cpe": "cpe:/o:redhat:enterprise_linux:8" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Enterprise Linux 8" + }, + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat OpenShift Container Platform 4", + "product": { + "name": "Red Hat OpenShift Container Platform 4", + "product_id": "red_hat_openshift_container_platform_4", + "product_identification_helper": { + "cpe": "cpe:/a:redhat:openshift:4" + } + } + } + ], + "category": "product_family", + "name": "Red Hat OpenShift Container Platform 4" + }, + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Software Collections", + "product": { + "name": "Red Hat Software Collections", + "product_id": "red_hat_software_collections", + "product_identification_helper": { + "cpe": "cpe:/a:redhat:rhel_software_collections:3" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Software Collections" + }, + { + "category": "product_version", + "name": "php", + "product": { + "name": "php", + "product_id": "php", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/php?arch=src" + } + } + }, + { + "category": "product_version", + "name": "php53", + "product": { + "name": "php53", + "product_id": "php53", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/php53?arch=src" + } + } + }, + { + "category": "product_version", + "name": "oniguruma", + "product": { + "name": "oniguruma", + "product_id": "oniguruma", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/oniguruma?arch=src" + } + } + }, + { + "category": "product_version", + "name": "ruby", + "product": { + "name": "ruby", + "product_id": "ruby", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/ruby?arch=src" + } + } + }, + { + "category": "product_version", + "name": "php:7.2/php", + "product": { + "name": "php:7.2/php", + "product_id": "php:7.2/php", + "product_identification_helper": { + "purl": "pkg:rpmmod/redhat/php:7.2/php" + } + } + }, + { + "category": "product_version", + "name": "php:7.3/php", + "product": { + "name": "php:7.3/php", + "product_id": "php:7.3/php", + "product_identification_helper": { + "purl": "pkg:rpmmod/redhat/php:7.3/php" + } + } + }, + { + "category": "product_version", + "name": "ruby:2.5/ruby", + "product": { + "name": "ruby:2.5/ruby", + "product_id": "ruby:2.5/ruby", + "product_identification_helper": { + "purl": "pkg:rpmmod/redhat/ruby:2.5/ruby" + } + } + }, + { + "category": "product_version", + "name": "ruby:2.6/ruby", + "product": { + "name": "ruby:2.6/ruby", + "product_id": "ruby:2.6/ruby", + "product_identification_helper": { + "purl": "pkg:rpmmod/redhat/ruby:2.6/ruby" + } + } + }, + { + "category": "product_version", + "name": "rh-php72-php", + "product": { + "name": "rh-php72-php", + "product_id": "rh-php72-php", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/rh-php72-php?arch=src" + } + } + }, + { + "category": "product_version", + "name": "rh-php73-php", + "product": { + "name": "rh-php73-php", + "product_id": "rh-php73-php", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/rh-php73-php?arch=src" + } + } + }, + { + "category": "product_version", + "name": "rh-ruby24-ruby", + "product": { + "name": "rh-ruby24-ruby", + "product_id": "rh-ruby24-ruby", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/rh-ruby24-ruby?arch=src" + } + } + }, + { + "category": "product_version", + "name": "rh-ruby25-ruby", + "product": { + "name": "rh-ruby25-ruby", + "product_id": "rh-ruby25-ruby", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/rh-ruby25-ruby?arch=src" + } + } + }, + { + "category": "product_version", + "name": "rh-ruby26-ruby", + "product": { + "name": "rh-ruby26-ruby", + "product_id": "rh-ruby26-ruby", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/rh-ruby26-ruby?arch=src" + } + } + } + ], + "category": "vendor", + "name": "Red Hat" + } + ], + "relationships": [ + { + "category": "default_component_of", + "full_product_name": { + "name": "php as a component of Red Hat Enterprise Linux 5", + "product_id": "red_hat_enterprise_linux_5:php" + }, + "product_reference": "php", + "relates_to_product_reference": "red_hat_enterprise_linux_5" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "php53 as a component of Red Hat Enterprise Linux 5", + "product_id": "red_hat_enterprise_linux_5:php53" + }, + "product_reference": "php53", + "relates_to_product_reference": "red_hat_enterprise_linux_5" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "oniguruma as a component of Red Hat Enterprise Linux 6", + "product_id": "red_hat_enterprise_linux_6:oniguruma" + }, + "product_reference": "oniguruma", + "relates_to_product_reference": "red_hat_enterprise_linux_6" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "php as a component of Red Hat Enterprise Linux 6", + "product_id": "red_hat_enterprise_linux_6:php" + }, + "product_reference": "php", + "relates_to_product_reference": "red_hat_enterprise_linux_6" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "php as a component of Red Hat Enterprise Linux 7", + "product_id": "red_hat_enterprise_linux_7:php" + }, + "product_reference": "php", + "relates_to_product_reference": "red_hat_enterprise_linux_7" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "ruby as a component of Red Hat Enterprise Linux 7", + "product_id": "red_hat_enterprise_linux_7:ruby" + }, + "product_reference": "ruby", + "relates_to_product_reference": "red_hat_enterprise_linux_7" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "oniguruma as a component of Red Hat Enterprise Linux 8", + "product_id": "red_hat_enterprise_linux_8:oniguruma" + }, + "product_reference": "oniguruma", + "relates_to_product_reference": "red_hat_enterprise_linux_8" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "php:7.2/php as a component of Red Hat Enterprise Linux 8", + "product_id": "red_hat_enterprise_linux_8:php:7.2/php" + }, + "product_reference": "php:7.2/php", + "relates_to_product_reference": "red_hat_enterprise_linux_8" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "php:7.3/php as a component of Red Hat Enterprise Linux 8", + "product_id": "red_hat_enterprise_linux_8:php:7.3/php" + }, + "product_reference": "php:7.3/php", + "relates_to_product_reference": "red_hat_enterprise_linux_8" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "ruby:2.5/ruby as a component of Red Hat Enterprise Linux 8", + "product_id": "red_hat_enterprise_linux_8:ruby:2.5/ruby" + }, + "product_reference": "ruby:2.5/ruby", + "relates_to_product_reference": "red_hat_enterprise_linux_8" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "ruby:2.6/ruby as a component of Red Hat Enterprise Linux 8", + "product_id": "red_hat_enterprise_linux_8:ruby:2.6/ruby" + }, + "product_reference": "ruby:2.6/ruby", + "relates_to_product_reference": "red_hat_enterprise_linux_8" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "oniguruma as a component of Red Hat OpenShift Container Platform 4", + "product_id": "red_hat_openshift_container_platform_4:oniguruma" + }, + "product_reference": "oniguruma", + "relates_to_product_reference": "red_hat_openshift_container_platform_4" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "rh-php72-php as a component of Red Hat Software Collections", + "product_id": "red_hat_software_collections:rh-php72-php" + }, + "product_reference": "rh-php72-php", + "relates_to_product_reference": "red_hat_software_collections" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "rh-php73-php as a component of Red Hat Software Collections", + "product_id": "red_hat_software_collections:rh-php73-php" + }, + "product_reference": "rh-php73-php", + "relates_to_product_reference": "red_hat_software_collections" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "rh-ruby24-ruby as a component of Red Hat Software Collections", + "product_id": "red_hat_software_collections:rh-ruby24-ruby" + }, + "product_reference": "rh-ruby24-ruby", + "relates_to_product_reference": "red_hat_software_collections" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "rh-ruby25-ruby as a component of Red Hat Software Collections", + "product_id": "red_hat_software_collections:rh-ruby25-ruby" + }, + "product_reference": "rh-ruby25-ruby", + "relates_to_product_reference": "red_hat_software_collections" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "rh-ruby26-ruby as a component of Red Hat Software Collections", + "product_id": "red_hat_software_collections:rh-ruby26-ruby" + }, + "product_reference": "rh-ruby26-ruby", + "relates_to_product_reference": "red_hat_software_collections" + } + ] + }, + "vulnerabilities": [ + { + "cve": "CVE-2019-16161", + "cwe": { + "id": "CWE-476", + "name": "NULL Pointer Dereference" + }, + "discovery_date": "2019-11-05T00:00:00+00:00", + "flags": [ + { + "label": "vulnerable_code_not_present", + "product_ids": [ + "red_hat_enterprise_linux_5:php", + "red_hat_enterprise_linux_5:php53", + "red_hat_enterprise_linux_6:oniguruma", + "red_hat_enterprise_linux_6:php", + "red_hat_enterprise_linux_7:php", + "red_hat_enterprise_linux_8:oniguruma", + "red_hat_enterprise_linux_8:php:7.2/php", + "red_hat_enterprise_linux_8:php:7.3/php", + "red_hat_openshift_container_platform_4:oniguruma", + "red_hat_software_collections:rh-php72-php", + "red_hat_software_collections:rh-php73-php" + ] + } + ], + "ids": [ + { + "system_name": "Red Hat Bugzilla ID", + "text": "1769042" + } + ], + "notes": [ + { + "category": "description", + "text": "A NULL pointer dereference vulnerability was found in Onigmo in the way it handled certain types of \"subexp\" regular expressions. A remote attacker could exploit this flaw by providing a malformed regular expression that when processed by an application linked to Onigmo, would crash the application, causing a denial of service.", + "title": "Vulnerability description" + }, + { + "category": "summary", + "text": "onigmo: NULL pointer dereference in onig_error_code_to_str because of fetch_token in regparse.c", + "title": "Vulnerability summary" + }, + { + "category": "other", + "text": "This flaw does not affect the versions of oniguruma (embedded in php:7.2/php) as shipped with Red Hat Enterprise Linux 8 as they do not include the vulnerable code, which was introduced in a newer version of the package. The same is true for the versions of oniguruma as shipped with Red Hat Enterprise Linux 6, the versions of oniguruma (embedded in php and php53) as shipped with Red Hat Enterprise Linux 5, 6, and 7, and the versions of oniguruma (embedded in rh-php72-php) as shipped with Red Hat Software Collections 3.\n\nThis flaw does not affect the versions of oniguruma as shipped with Red Hat Enterprise Linux 8 as they already include the patch. The same is true for the versions of oniguruma (embedded in php:7.3/php) as shipped with Red Hat Enterprise Linux 8 and the versions of oniguruma (embedded in rh-php73-php) as shipped with Red Hat Software Collections 3.", + "title": "Statement" + }, + { + "category": "general", + "text": "The CVSS score(s) listed for this vulnerability do not reflect the associated product's status, and are included for informational purposes to better understand the severity of this vulnerability.", + "title": "CVSS score applicability" + } + ], + "product_status": { + "known_affected": [ + "red_hat_enterprise_linux_7:ruby", + "red_hat_enterprise_linux_8:ruby:2.5/ruby", + "red_hat_enterprise_linux_8:ruby:2.6/ruby", + "red_hat_software_collections:rh-ruby24-ruby", + "red_hat_software_collections:rh-ruby25-ruby", + "red_hat_software_collections:rh-ruby26-ruby" + ], + "known_not_affected": [ + "red_hat_enterprise_linux_5:php", + "red_hat_enterprise_linux_5:php53", + "red_hat_enterprise_linux_6:oniguruma", + "red_hat_enterprise_linux_6:php", + "red_hat_enterprise_linux_7:php", + "red_hat_enterprise_linux_8:oniguruma", + "red_hat_enterprise_linux_8:php:7.2/php", + "red_hat_enterprise_linux_8:php:7.3/php", + "red_hat_openshift_container_platform_4:oniguruma", + "red_hat_software_collections:rh-php72-php", + "red_hat_software_collections:rh-php73-php" + ] + }, + "references": [ + { + "category": "self", + "summary": "Canonical URL", + "url": "https://access.redhat.com/security/cve/CVE-2019-16161" + }, + { + "category": "external", + "summary": "RHBZ#1769042", + "url": "https://bugzilla.redhat.com/show_bug.cgi?id=1769042" + }, + { + "category": "external", + "summary": "https://www.cve.org/CVERecord?id=CVE-2019-16161", + "url": "https://www.cve.org/CVERecord?id=CVE-2019-16161" + }, + { + "category": "external", + "summary": "https://nvd.nist.gov/vuln/detail/CVE-2019-16161", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-16161" + } + ], + "release_date": "2019-07-28T00:00:00+00:00", + "remediations": [ + { + "category": "no_fix_planned", + "details": "Will not fix", + "product_ids": [ + "red_hat_enterprise_linux_7:ruby", + "red_hat_enterprise_linux_8:ruby:2.5/ruby", + "red_hat_enterprise_linux_8:ruby:2.6/ruby", + "red_hat_software_collections:rh-ruby24-ruby", + "red_hat_software_collections:rh-ruby25-ruby", + "red_hat_software_collections:rh-ruby26-ruby" + ] + } + ], + "scores": [ + { + "cvss_v3": { + "attackComplexity": "LOW", + "attackVector": "NETWORK", + "availabilityImpact": "HIGH", + "baseScore": 7.5, + "baseSeverity": "HIGH", + "confidentialityImpact": "NONE", + "integrityImpact": "NONE", + "privilegesRequired": "NONE", + "scope": "UNCHANGED", + "userInteraction": "NONE", + "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1" + }, + "products": [ + "red_hat_enterprise_linux_7:ruby", + "red_hat_enterprise_linux_8:ruby:2.5/ruby", + "red_hat_enterprise_linux_8:ruby:2.6/ruby", + "red_hat_software_collections:rh-ruby24-ruby", + "red_hat_software_collections:rh-ruby25-ruby", + "red_hat_software_collections:rh-ruby26-ruby" + ] + } + ], + "threats": [ + { + "category": "impact", + "details": "Low", + "product_ids": [ + "red_hat_enterprise_linux_7:ruby", + "red_hat_enterprise_linux_8:ruby:2.5/ruby", + "red_hat_enterprise_linux_8:ruby:2.6/ruby", + "red_hat_software_collections:rh-ruby24-ruby", + "red_hat_software_collections:rh-ruby25-ruby", + "red_hat_software_collections:rh-ruby26-ruby" + ] + } + ], + "title": "onigmo: NULL pointer dereference in onig_error_code_to_str because of fetch_token in regparse.c" + } + ] +} diff --git a/tests/unit/providers/rhel_csaf/test-fixtures/cve-2019-18276.json b/tests/unit/providers/rhel_csaf/test-fixtures/cve-2019-18276.json new file mode 100644 index 00000000..ce513b53 --- /dev/null +++ b/tests/unit/providers/rhel_csaf/test-fixtures/cve-2019-18276.json @@ -0,0 +1,751 @@ +{ + "document": { + "aggregate_severity": { + "namespace": "https://access.redhat.com/security/updates/classification/", + "text": "low" + }, + "category": "csaf_vex", + "csaf_version": "2.0", + "distribution": { + "text": "Copyright © Red Hat, Inc. All rights reserved.", + "tlp": { + "label": "WHITE", + "url": "https://www.first.org/tlp/" + } + }, + "lang": "en", + "notes": [ + { + "category": "legal_disclaimer", + "text": "This content is licensed under the Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/). If you distribute this content, or a modified version of it, you must provide attribution to Red Hat Inc. and provide a link to the original.", + "title": "Terms of Use" + } + ], + "publisher": { + "category": "vendor", + "contact_details": "https://access.redhat.com/security/team/contact/", + "issuing_authority": "Red Hat Product Security is responsible for vulnerability handling across all Red Hat offerings.", + "name": "Red Hat Product Security", + "namespace": "https://www.redhat.com" + }, + "references": [ + { + "category": "self", + "summary": "Canonical URL", + "url": "https://access.redhat.com/security/data/csaf/v2/vex/2019/cve-2019-18276.json" + } + ], + "title": "bash: when effective UID is not equal to its real UID the saved UID is not dropped", + "tracking": { + "current_release_date": "2024-09-16T05:11:33+00:00", + "generator": { + "date": "2024-09-16T05:11:33+00:00", + "engine": { + "name": "Red Hat SDEngine", + "version": "3.33.3" + } + }, + "id": "CVE-2019-18276", + "initial_release_date": "2019-07-01T00:00:00+00:00", + "revision_history": [ + { + "date": "2019-07-01T00:00:00+00:00", + "number": "1", + "summary": "Initial version" + }, + { + "date": "2024-06-13T22:19:51+00:00", + "number": "2", + "summary": "Current version" + }, + { + "date": "2024-09-16T05:11:33+00:00", + "number": "3", + "summary": "Last generated version" + } + ], + "status": "final", + "version": "3" + } + }, + "product_tree": { + "branches": [ + { + "branches": [ + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Enterprise Linux 5", + "product": { + "name": "Red Hat Enterprise Linux 5", + "product_id": "red_hat_enterprise_linux_5", + "product_identification_helper": { + "cpe": "cpe:/o:redhat:enterprise_linux:5" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Enterprise Linux 5" + }, + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Enterprise Linux 6", + "product": { + "name": "Red Hat Enterprise Linux 6", + "product_id": "red_hat_enterprise_linux_6", + "product_identification_helper": { + "cpe": "cpe:/o:redhat:enterprise_linux:6" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Enterprise Linux 6" + }, + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Enterprise Linux 7", + "product": { + "name": "Red Hat Enterprise Linux 7", + "product_id": "red_hat_enterprise_linux_7", + "product_identification_helper": { + "cpe": "cpe:/o:redhat:enterprise_linux:7" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Enterprise Linux 7" + }, + { + "branches": [ + { + "category": "product_name", + "name": "Red Hat Enterprise Linux BaseOS (v. 8)", + "product": { + "name": "Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA", + "product_identification_helper": { + "cpe": "cpe:/o:redhat:enterprise_linux:8::baseos" + } + } + } + ], + "category": "product_family", + "name": "Red Hat Enterprise Linux" + }, + { + "category": "product_version", + "name": "bash", + "product": { + "name": "bash", + "product_id": "bash", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash?arch=src" + } + } + }, + { + "branches": [ + { + "category": "product_version", + "name": "bash-0:4.4.19-14.el8.s390x", + "product": { + "name": "bash-0:4.4.19-14.el8.s390x", + "product_id": "bash-0:4.4.19-14.el8.s390x", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash@4.4.19-14.el8?arch=s390x" + } + } + }, + { + "category": "product_version", + "name": "bash-doc-0:4.4.19-14.el8.s390x", + "product": { + "name": "bash-doc-0:4.4.19-14.el8.s390x", + "product_id": "bash-doc-0:4.4.19-14.el8.s390x", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-doc@4.4.19-14.el8?arch=s390x" + } + } + }, + { + "category": "product_version", + "name": "bash-debugsource-0:4.4.19-14.el8.s390x", + "product": { + "name": "bash-debugsource-0:4.4.19-14.el8.s390x", + "product_id": "bash-debugsource-0:4.4.19-14.el8.s390x", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-debugsource@4.4.19-14.el8?arch=s390x" + } + } + }, + { + "category": "product_version", + "name": "bash-debuginfo-0:4.4.19-14.el8.s390x", + "product": { + "name": "bash-debuginfo-0:4.4.19-14.el8.s390x", + "product_id": "bash-debuginfo-0:4.4.19-14.el8.s390x", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-debuginfo@4.4.19-14.el8?arch=s390x" + } + } + } + ], + "category": "architecture", + "name": "s390x" + }, + { + "branches": [ + { + "category": "product_version", + "name": "bash-0:4.4.19-14.el8.x86_64", + "product": { + "name": "bash-0:4.4.19-14.el8.x86_64", + "product_id": "bash-0:4.4.19-14.el8.x86_64", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash@4.4.19-14.el8?arch=x86_64" + } + } + }, + { + "category": "product_version", + "name": "bash-doc-0:4.4.19-14.el8.x86_64", + "product": { + "name": "bash-doc-0:4.4.19-14.el8.x86_64", + "product_id": "bash-doc-0:4.4.19-14.el8.x86_64", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-doc@4.4.19-14.el8?arch=x86_64" + } + } + }, + { + "category": "product_version", + "name": "bash-debugsource-0:4.4.19-14.el8.x86_64", + "product": { + "name": "bash-debugsource-0:4.4.19-14.el8.x86_64", + "product_id": "bash-debugsource-0:4.4.19-14.el8.x86_64", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-debugsource@4.4.19-14.el8?arch=x86_64" + } + } + }, + { + "category": "product_version", + "name": "bash-debuginfo-0:4.4.19-14.el8.x86_64", + "product": { + "name": "bash-debuginfo-0:4.4.19-14.el8.x86_64", + "product_id": "bash-debuginfo-0:4.4.19-14.el8.x86_64", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-debuginfo@4.4.19-14.el8?arch=x86_64" + } + } + } + ], + "category": "architecture", + "name": "x86_64" + }, + { + "branches": [ + { + "category": "product_version", + "name": "bash-0:4.4.19-14.el8.ppc64le", + "product": { + "name": "bash-0:4.4.19-14.el8.ppc64le", + "product_id": "bash-0:4.4.19-14.el8.ppc64le", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash@4.4.19-14.el8?arch=ppc64le" + } + } + }, + { + "category": "product_version", + "name": "bash-doc-0:4.4.19-14.el8.ppc64le", + "product": { + "name": "bash-doc-0:4.4.19-14.el8.ppc64le", + "product_id": "bash-doc-0:4.4.19-14.el8.ppc64le", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-doc@4.4.19-14.el8?arch=ppc64le" + } + } + }, + { + "category": "product_version", + "name": "bash-debugsource-0:4.4.19-14.el8.ppc64le", + "product": { + "name": "bash-debugsource-0:4.4.19-14.el8.ppc64le", + "product_id": "bash-debugsource-0:4.4.19-14.el8.ppc64le", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-debugsource@4.4.19-14.el8?arch=ppc64le" + } + } + }, + { + "category": "product_version", + "name": "bash-debuginfo-0:4.4.19-14.el8.ppc64le", + "product": { + "name": "bash-debuginfo-0:4.4.19-14.el8.ppc64le", + "product_id": "bash-debuginfo-0:4.4.19-14.el8.ppc64le", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-debuginfo@4.4.19-14.el8?arch=ppc64le" + } + } + } + ], + "category": "architecture", + "name": "ppc64le" + }, + { + "branches": [ + { + "category": "product_version", + "name": "bash-0:4.4.19-14.el8.aarch64", + "product": { + "name": "bash-0:4.4.19-14.el8.aarch64", + "product_id": "bash-0:4.4.19-14.el8.aarch64", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash@4.4.19-14.el8?arch=aarch64" + } + } + }, + { + "category": "product_version", + "name": "bash-doc-0:4.4.19-14.el8.aarch64", + "product": { + "name": "bash-doc-0:4.4.19-14.el8.aarch64", + "product_id": "bash-doc-0:4.4.19-14.el8.aarch64", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-doc@4.4.19-14.el8?arch=aarch64" + } + } + }, + { + "category": "product_version", + "name": "bash-debugsource-0:4.4.19-14.el8.aarch64", + "product": { + "name": "bash-debugsource-0:4.4.19-14.el8.aarch64", + "product_id": "bash-debugsource-0:4.4.19-14.el8.aarch64", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-debugsource@4.4.19-14.el8?arch=aarch64" + } + } + }, + { + "category": "product_version", + "name": "bash-debuginfo-0:4.4.19-14.el8.aarch64", + "product": { + "name": "bash-debuginfo-0:4.4.19-14.el8.aarch64", + "product_id": "bash-debuginfo-0:4.4.19-14.el8.aarch64", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash-debuginfo@4.4.19-14.el8?arch=aarch64" + } + } + } + ], + "category": "architecture", + "name": "aarch64" + }, + { + "branches": [ + { + "category": "product_version", + "name": "bash-0:4.4.19-14.el8.src", + "product": { + "name": "bash-0:4.4.19-14.el8.src", + "product_id": "bash-0:4.4.19-14.el8.src", + "product_identification_helper": { + "purl": "pkg:rpm/redhat/bash@4.4.19-14.el8?arch=src" + } + } + } + ], + "category": "architecture", + "name": "src" + } + ], + "category": "vendor", + "name": "Red Hat" + } + ], + "relationships": [ + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-0:4.4.19-14.el8.aarch64 as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.aarch64" + }, + "product_reference": "bash-0:4.4.19-14.el8.aarch64", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-0:4.4.19-14.el8.ppc64le as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.ppc64le" + }, + "product_reference": "bash-0:4.4.19-14.el8.ppc64le", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-0:4.4.19-14.el8.s390x as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.s390x" + }, + "product_reference": "bash-0:4.4.19-14.el8.s390x", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-0:4.4.19-14.el8.src as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.src" + }, + "product_reference": "bash-0:4.4.19-14.el8.src", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-0:4.4.19-14.el8.x86_64 as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.x86_64" + }, + "product_reference": "bash-0:4.4.19-14.el8.x86_64", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-debuginfo-0:4.4.19-14.el8.aarch64 as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.aarch64" + }, + "product_reference": "bash-debuginfo-0:4.4.19-14.el8.aarch64", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-debuginfo-0:4.4.19-14.el8.ppc64le as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.ppc64le" + }, + "product_reference": "bash-debuginfo-0:4.4.19-14.el8.ppc64le", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-debuginfo-0:4.4.19-14.el8.s390x as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.s390x" + }, + "product_reference": "bash-debuginfo-0:4.4.19-14.el8.s390x", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-debuginfo-0:4.4.19-14.el8.x86_64 as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.x86_64" + }, + "product_reference": "bash-debuginfo-0:4.4.19-14.el8.x86_64", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-debugsource-0:4.4.19-14.el8.aarch64 as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.aarch64" + }, + "product_reference": "bash-debugsource-0:4.4.19-14.el8.aarch64", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-debugsource-0:4.4.19-14.el8.ppc64le as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.ppc64le" + }, + "product_reference": "bash-debugsource-0:4.4.19-14.el8.ppc64le", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-debugsource-0:4.4.19-14.el8.s390x as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.s390x" + }, + "product_reference": "bash-debugsource-0:4.4.19-14.el8.s390x", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-debugsource-0:4.4.19-14.el8.x86_64 as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.x86_64" + }, + "product_reference": "bash-debugsource-0:4.4.19-14.el8.x86_64", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-doc-0:4.4.19-14.el8.aarch64 as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.aarch64" + }, + "product_reference": "bash-doc-0:4.4.19-14.el8.aarch64", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-doc-0:4.4.19-14.el8.ppc64le as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.ppc64le" + }, + "product_reference": "bash-doc-0:4.4.19-14.el8.ppc64le", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-doc-0:4.4.19-14.el8.s390x as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.s390x" + }, + "product_reference": "bash-doc-0:4.4.19-14.el8.s390x", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash-doc-0:4.4.19-14.el8.x86_64 as a component of Red Hat Enterprise Linux BaseOS (v. 8)", + "product_id": "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.x86_64" + }, + "product_reference": "bash-doc-0:4.4.19-14.el8.x86_64", + "relates_to_product_reference": "BaseOS-8.4.0.GA" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash as a component of Red Hat Enterprise Linux 5", + "product_id": "red_hat_enterprise_linux_5:bash" + }, + "product_reference": "bash", + "relates_to_product_reference": "red_hat_enterprise_linux_5" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash as a component of Red Hat Enterprise Linux 6", + "product_id": "red_hat_enterprise_linux_6:bash" + }, + "product_reference": "bash", + "relates_to_product_reference": "red_hat_enterprise_linux_6" + }, + { + "category": "default_component_of", + "full_product_name": { + "name": "bash as a component of Red Hat Enterprise Linux 7", + "product_id": "red_hat_enterprise_linux_7:bash" + }, + "product_reference": "bash", + "relates_to_product_reference": "red_hat_enterprise_linux_7" + } + ] + }, + "vulnerabilities": [ + { + "cve": "CVE-2019-18276", + "cwe": { + "id": "CWE-271", + "name": "Privilege Dropping / Lowering Errors" + }, + "discovery_date": "2019-11-29T00:00:00+00:00", + "ids": [ + { + "system_name": "Red Hat Bugzilla ID", + "text": "1778309" + } + ], + "notes": [ + { + "category": "description", + "text": "A privilege escalation vulnerability was found in bash in the way it dropped privileges when started with an effective user id not equal to the real user id. Bash may be vulnerable to this flaw if the setuid permission is set and the owner of the bash program itself is a non-root user. A local attacker could exploit this flaw to escalate their privileges on the system.", + "title": "Vulnerability description" + }, + { + "category": "summary", + "text": "bash: when effective UID is not equal to its real UID the saved UID is not dropped", + "title": "Vulnerability summary" + }, + { + "category": "general", + "text": "The CVSS score(s) listed for this vulnerability do not reflect the associated product's status, and are included for informational purposes to better understand the severity of this vulnerability.", + "title": "CVSS score applicability" + } + ], + "product_status": { + "fixed": [ + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.src", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.x86_64" + ], + "known_affected": [ + "red_hat_enterprise_linux_5:bash", + "red_hat_enterprise_linux_6:bash", + "red_hat_enterprise_linux_7:bash" + ] + }, + "references": [ + { + "category": "self", + "summary": "Canonical URL", + "url": "https://access.redhat.com/security/cve/CVE-2019-18276" + }, + { + "category": "external", + "summary": "RHBZ#1778309", + "url": "https://bugzilla.redhat.com/show_bug.cgi?id=1778309" + }, + { + "category": "external", + "summary": "https://www.cve.org/CVERecord?id=CVE-2019-18276", + "url": "https://www.cve.org/CVERecord?id=CVE-2019-18276" + }, + { + "category": "external", + "summary": "https://nvd.nist.gov/vuln/detail/CVE-2019-18276", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-18276" + } + ], + "release_date": "2019-07-01T00:00:00+00:00", + "remediations": [ + { + "category": "vendor_fix", + "details": "For details on how to apply this update, which includes the changes described in this advisory, refer to:\n\nhttps://access.redhat.com/articles/11258", + "product_ids": [ + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.src", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.x86_64" + ], + "url": "https://access.redhat.com/errata/RHSA-2021:1679" + }, + { + "category": "no_fix_planned", + "details": "Out of support scope", + "product_ids": [ + "red_hat_enterprise_linux_5:bash", + "red_hat_enterprise_linux_6:bash" + ] + }, + { + "category": "no_fix_planned", + "details": "Will not fix", + "product_ids": [ + "red_hat_enterprise_linux_7:bash" + ] + } + ], + "scores": [ + { + "cvss_v3": { + "attackComplexity": "LOW", + "attackVector": "LOCAL", + "availabilityImpact": "HIGH", + "baseScore": 7.8, + "baseSeverity": "HIGH", + "confidentialityImpact": "HIGH", + "integrityImpact": "HIGH", + "privilegesRequired": "LOW", + "scope": "UNCHANGED", + "userInteraction": "NONE", + "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", + "version": "3.1" + }, + "products": [ + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.src", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.x86_64", + "red_hat_enterprise_linux_5:bash", + "red_hat_enterprise_linux_6:bash", + "red_hat_enterprise_linux_7:bash" + ] + } + ], + "threats": [ + { + "category": "impact", + "details": "Low", + "product_ids": [ + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.src", + "BaseOS-8.4.0.GA:bash-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-debuginfo-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-debugsource-0:4.4.19-14.el8.x86_64", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.aarch64", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.ppc64le", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.s390x", + "BaseOS-8.4.0.GA:bash-doc-0:4.4.19-14.el8.x86_64", + "red_hat_enterprise_linux_5:bash", + "red_hat_enterprise_linux_6:bash", + "red_hat_enterprise_linux_7:bash" + ] + } + ], + "title": "bash: when effective UID is not equal to its real UID the saved UID is not dropped" + } + ] +} diff --git a/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2019-16161.json b/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2019-16161.json new file mode 100644 index 00000000..4d78a946 --- /dev/null +++ b/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2019-16161.json @@ -0,0 +1,89 @@ +[ + { + "identifier": "rhel:7/cve-2019-16161", + "item": { + "Vulnerability": { + "CVSS": [ + { + "base_metrics": { + "base_score": 7.5, + "base_severity": "High", + "exploitability_score": 3.9, + "impact_score": 3.6 + }, + "status": "final", + "vector_string": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1" + } + ], + "Description": "A NULL pointer dereference vulnerability was found in Onigmo in the way it handled certain types of \"subexp\" regular expressions. A remote attacker could exploit this flaw by providing a malformed regular expression that when processed by an application linked to Onigmo, would crash the application, causing a denial of service.", + "FixedIn": [ + { + "Name": "ruby", + "NamespaceName": "rhel:7", + "VendorAdvisory": { + "NoAdvisory": true + }, + "Version": "None", + "VersionFormat": "rpm" + } + ], + "Link": "https://access.redhat.com/security/cve/CVE-2019-16161", + "Metadata": {}, + "Name": "CVE-2019-16161", + "NamespaceName": "rhel:7", + "Severity": "Low" + } + }, + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json" + }, + { + "identifier": "rhel:8/cve-2019-16161", + "item": { + "Vulnerability": { + "CVSS": [ + { + "base_metrics": { + "base_score": 7.5, + "base_severity": "High", + "exploitability_score": 3.9, + "impact_score": 3.6 + }, + "status": "final", + "vector_string": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1" + } + ], + "Description": "A NULL pointer dereference vulnerability was found in Onigmo in the way it handled certain types of \"subexp\" regular expressions. A remote attacker could exploit this flaw by providing a malformed regular expression that when processed by an application linked to Onigmo, would crash the application, causing a denial of service.", + "FixedIn": [ + { + "Module": "ruby:2.5", + "Name": "ruby", + "NamespaceName": "rhel:8", + "VendorAdvisory": { + "NoAdvisory": true + }, + "Version": "None", + "VersionFormat": "rpm" + }, + { + "Module": "ruby:2.6", + "Name": "ruby", + "NamespaceName": "rhel:8", + "VendorAdvisory": { + "NoAdvisory": true + }, + "Version": "None", + "VersionFormat": "rpm" + } + ], + "Link": "https://access.redhat.com/security/cve/CVE-2019-16161", + "Metadata": {}, + "Name": "CVE-2019-16161", + "NamespaceName": "rhel:8", + "Severity": "Low" + } + }, + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json" + } +] diff --git a/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2019-18276.json b/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2019-18276.json new file mode 100644 index 00000000..1137041e --- /dev/null +++ b/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2019-18276.json @@ -0,0 +1,160 @@ +[ + { + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json", + "identifier": "rhel:7/cve-2019-18276", + "item": { + "Vulnerability": { + "Severity": "Low", + "NamespaceName": "rhel:7", + "FixedIn": [ + { + "Name": "bash", + "Version": "None", + "VersionFormat": "rpm", + "NamespaceName": "rhel:7", + "VendorAdvisory": { + "NoAdvisory": true + } + } + ], + "Link": "https://access.redhat.com/security/cve/CVE-2019-18276", + "Description": "A privilege escalation vulnerability was found in bash in the way it dropped privileges when started with an effective user id not equal to the real user id. Bash may be vulnerable to this flaw if the setuid permission is set and the owner of the bash program itself is a non-root user. A local attacker could exploit this flaw to escalate their privileges on the system.", + "Metadata": {}, + "Name": "CVE-2019-18276", + "CVSS": [ + { + "version": "3.1", + "status": "final", + "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", + "base_metrics": { + "base_score": 7.8, + "exploitability_score": 1.8, + "impact_score": 5.9, + "base_severity": "High" + } + } + ] + } + } + }, + { + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json", + "identifier": "rhel:5/cve-2019-18276", + "item": { + "Vulnerability": { + "Severity": "Low", + "NamespaceName": "rhel:5", + "FixedIn": [ + { + "Name": "bash", + "Version": "None", + "VersionFormat": "rpm", + "NamespaceName": "rhel:5", + "VendorAdvisory": { + "NoAdvisory": true + } + } + ], + "Link": "https://access.redhat.com/security/cve/CVE-2019-18276", + "Description": "A privilege escalation vulnerability was found in bash in the way it dropped privileges when started with an effective user id not equal to the real user id. Bash may be vulnerable to this flaw if the setuid permission is set and the owner of the bash program itself is a non-root user. A local attacker could exploit this flaw to escalate their privileges on the system.", + "Metadata": {}, + "Name": "CVE-2019-18276", + "CVSS": [ + { + "version": "3.1", + "status": "final", + "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", + "base_metrics": { + "base_score": 7.8, + "exploitability_score": 1.8, + "impact_score": 5.9, + "base_severity": "High" + } + } + ] + } + } + }, + { + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json", + "identifier": "rhel:6/cve-2019-18276", + "item": { + "Vulnerability": { + "Severity": "Low", + "NamespaceName": "rhel:6", + "FixedIn": [ + { + "Name": "bash", + "Version": "None", + "VersionFormat": "rpm", + "NamespaceName": "rhel:6", + "VendorAdvisory": { + "NoAdvisory": true + } + } + ], + "Link": "https://access.redhat.com/security/cve/CVE-2019-18276", + "Description": "A privilege escalation vulnerability was found in bash in the way it dropped privileges when started with an effective user id not equal to the real user id. Bash may be vulnerable to this flaw if the setuid permission is set and the owner of the bash program itself is a non-root user. A local attacker could exploit this flaw to escalate their privileges on the system.", + "Metadata": {}, + "Name": "CVE-2019-18276", + "CVSS": [ + { + "version": "3.1", + "status": "final", + "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", + "base_metrics": { + "base_score": 7.8, + "exploitability_score": 1.8, + "impact_score": 5.9, + "base_severity": "High" + } + } + ] + } + } + }, + { + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json", + "identifier": "rhel:8/cve-2019-18276", + "item": { + "Vulnerability": { + "Severity": "Low", + "NamespaceName": "rhel:8", + "FixedIn": [ + { + "Name": "bash", + "Version": "0:4.4.19-14.el8", + "VersionFormat": "rpm", + "NamespaceName": "rhel:8", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2021:1679", + "Link": "https://access.redhat.com/errata/RHSA-2021:1679" + } + ] + } + } + ], + "Link": "https://access.redhat.com/security/cve/CVE-2019-18276", + "Description": "A privilege escalation vulnerability was found in bash in the way it dropped privileges when started with an effective user id not equal to the real user id. Bash may be vulnerable to this flaw if the setuid permission is set and the owner of the bash program itself is a non-root user. A local attacker could exploit this flaw to escalate their privileges on the system.", + "Metadata": {}, + "Name": "CVE-2019-18276", + "CVSS": [ + { + "version": "3.1", + "status": "final", + "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", + "base_metrics": { + "base_score": 7.8, + "exploitability_score": 1.8, + "impact_score": 5.9, + "base_severity": "High" + } + } + ] + } + } + } +] diff --git a/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2021-46661.json b/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2021-46661.json new file mode 100644 index 00000000..6d387e24 --- /dev/null +++ b/tests/unit/providers/rhel_csaf/test-fixtures/result-for-cve-2021-46661.json @@ -0,0 +1,237 @@ +[ + { + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json", + "identifier": "rhel:8/cve-2021-46661", + "item": { + "Vulnerability": { + "Name": "CVE-2021-46661", + "NamespaceName": "rhel:8", + "Description": "MariaDB through 10.5.9 allows an application crash in find_field_in_tables and find_order_in_list via an unused common table expression (CTE).", + "Severity": "Low", + "Link": "https://access.redhat.com/security/cve/CVE-2021-46661", + "CVSS": [ + { + "version": "3.1", + "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", + "base_metrics": { + "base_score": 5.5, + "exploitability_score": 1.8, + "impact_score": 3.6, + "base_severity": "Medium" + }, + "status": "final" + } + ], + "FixedIn": [ + { + "Name": "galera", + "NamespaceName": "rhel:8", + "VersionFormat": "rpm", + "Version": "25.3.35-1.module+el8.6.0+15949+4ba4ec26", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2022:6443", + "Link": "https://access.redhat.com/errata/RHSA-2022:6443" + } + ] + }, + "VulnerableRange": null + }, + { + "Name": "judy", + "NamespaceName": "rhel:8", + "VersionFormat": "rpm", + "Version": "1.0.5-18.module+el8+2765+cfa4f87b", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2022:6443", + "Link": "https://access.redhat.com/errata/RHSA-2022:6443" + } + ] + }, + "VulnerableRange": null + }, + { + "Name": "mariadb", + "NamespaceName": "rhel:8", + "VersionFormat": "rpm", + "Version": "10.5.16-2.module+el8.6.0+15639+405b7427", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2022:5826", + "Link": "https://access.redhat.com/errata/RHSA-2022:5826" + } + ] + }, + "VulnerableRange": null + }, + { + "Name": "judy", + "NamespaceName": "rhel:8", + "VersionFormat": "rpm", + "Version": "1.0.5-18.module+el8.4.0+9031+9abc7af9", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2022:5826", + "Link": "https://access.redhat.com/errata/RHSA-2022:5826" + } + ] + }, + "VulnerableRange": null + }, + { + "Name": "mariadb", + "NamespaceName": "rhel:8", + "VersionFormat": "rpm", + "Version": "10.3.35-1.module+el8.6.0+15949+4ba4ec26", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2022:6443", + "Link": "https://access.redhat.com/errata/RHSA-2022:6443" + } + ] + }, + "VulnerableRange": null + }, + { + "Name": "galera", + "NamespaceName": "rhel:8", + "VersionFormat": "rpm", + "Version": "26.4.11-1.module+el8.6.0+15639+405b7427", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2022:5826", + "Link": "https://access.redhat.com/errata/RHSA-2022:5826" + } + ] + }, + "VulnerableRange": null + } + ], + "Metadata": {} + } + } + }, + { + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json", + "identifier": "rhel:9/cve-2021-46661", + "item": { + "Vulnerability": { + "Name": "CVE-2021-46661", + "NamespaceName": "rhel:9", + "Description": "MariaDB through 10.5.9 allows an application crash in find_field_in_tables and find_order_in_list via an unused common table expression (CTE).", + "Severity": "Low", + "Link": "https://access.redhat.com/security/cve/CVE-2021-46661", + "CVSS": [ + { + "version": "3.1", + "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", + "base_metrics": { + "base_score": 5.5, + "exploitability_score": 1.8, + "impact_score": 3.6, + "base_severity": "Medium" + }, + "status": "final" + } + ], + "FixedIn": [ + { + "Name": "mariadb", + "NamespaceName": "rhel:9", + "VersionFormat": "rpm", + "Version": "10.5.16-2.el9_0", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2022:5948", + "Link": "https://access.redhat.com/errata/RHSA-2022:5948" + } + ] + }, + "VulnerableRange": null + }, + { + "Name": "mariadb", + "NamespaceName": "rhel:9", + "VersionFormat": "rpm", + "Version": "10.5.16-2.el9_0", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [ + { + "ID": "RHSA-2022:5948", + "Link": "https://access.redhat.com/errata/RHSA-2022:5948" + } + ] + }, + "VulnerableRange": null + } + ], + "Metadata": {} + } + } + }, + { + "schema": "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/os/schema-1.0.0.json", + "identifier": "rhel:7/cve-2021-46661", + "item": { + "Vulnerability": { + "Name": "CVE-2021-46661", + "NamespaceName": "rhel:7", + "Description": "MariaDB through 10.5.9 allows an application crash in find_field_in_tables and find_order_in_list via an unused common table expression (CTE).", + "Severity": "Low", + "Link": "https://access.redhat.com/security/cve/CVE-2021-46661", + "CVSS": [ + { + "version": "3.1", + "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", + "base_metrics": { + "base_score": 5.5, + "exploitability_score": 1.8, + "impact_score": 3.6, + "base_severity": "Medium" + }, + "status": "final" + } + ], + "FixedIn": [ + { + "Name": "mariadb", + "NamespaceName": "rhel:7", + "VersionFormat": "rpm", + "Version": "None", + "Module": "", + "VendorAdvisory": { + "NoAdvisory": false, + "AdvisorySummary": [] + }, + "VulnerableRange": null + } + ], + "Metadata": {} + } + } + } +] diff --git a/tests/unit/providers/rhel_csaf/test_transformer.py b/tests/unit/providers/rhel_csaf/test_transformer.py new file mode 100644 index 00000000..f5d38f50 --- /dev/null +++ b/tests/unit/providers/rhel_csaf/test_transformer.py @@ -0,0 +1,75 @@ +from vunnel.providers.rhel_csaf.transformer import base_vulnerability +from vunnel.utils.csaf_types import ( + TLP, + AggregateSeverity, + CSAFDoc, + Distribution, + Document, + Generator, + GeneratorEngine, + Note, + ProductTree, + Publisher, + Reference, + Tracking, + Vulnerability, +) + + +def csaf_test_builder(cve_id: str, description: str, severity: str, link: str) -> CSAFDoc: + return CSAFDoc( + document=Document( + aggregate_severity=AggregateSeverity(namespace="", text=severity), + category="csaf_vex", + csaf_version="ignored", + distribution=Distribution(text="", tlp=TLP(label="", url="")), + lang="en", + notes=[], + publisher=Publisher(category="", contact_details="", issuing_authority="", name="", namespace=""), + references=[], + title="ignored", + tracking=Tracking( + current_release_date="", + generator=Generator(date="", engine=GeneratorEngine(name="", version="")), + id="", + initial_release_date="", + revision_history=[], + status="", + version="", + ), + ), + product_tree=ProductTree(branches=[], relationships=[]), + vulnerabilities=[ + Vulnerability( + title="example-cve", + cve=cve_id, + notes=[ + Note( + category="description", + title="Vulnerability description", + text=description, + ) + ], + references=[ + Reference(category="self", summary="", url=link), + ], + ), + ], + ) + + +def test_base_vulnerability(): + cve_id = "CVE-123-Example" + description = "example descritpion" + severity = "important" + link = "https://example.com/CVE-123-Example" + namespace = "rhel:8" + csaf = csaf_test_builder(cve_id, description, severity, link) + + vuln = base_vulnerability(csaf, namespace) + + assert vuln.Name == cve_id + assert vuln.NamespaceName == namespace + assert vuln.Description == description + assert vuln.Severity == "High", "failed to normalize description" + assert vuln.Link == link diff --git a/tests/unit/providers/rhel_legacy/__init__.py b/tests/unit/providers/rhel_legacy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3509 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3509 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3509 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3509 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3511 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3511 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3511 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3511 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3526 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3526 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3526 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3526 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3533 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3533 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3533 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3533 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3539 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3539 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3539 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3539 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3544 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3544 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2017-3544 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2017-3544 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2019-25059 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2019-25059 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2019-25059 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2019-25059 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2020-16587 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2020-16587 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2020-16587 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2020-16587 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2020-16588 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2020-16588 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2020-16588 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2020-16588 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2021-20298 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2021-20298 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2021-20298 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2021-20298 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2021-20299 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2021-20299 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2021-20299 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2021-20299 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1921 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1921 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1921 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1921 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1922 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1922 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1922 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1922 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1923 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1923 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1923 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1923 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1924 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1924 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1924 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1924 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1925 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1925 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-1925 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-1925 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-2309 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-2309 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2022-2309 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2022-2309 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2023-4863 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2023-4863 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2023-4863 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2023-4863 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2023-5129 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2023-5129 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2023-5129 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2023-5129 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2023-5217 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2023-5217 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/full/CVE-2023-5217 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/full/CVE-2023-5217 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3509 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3509 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3509 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3509 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3511 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3511 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3511 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3511 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3526 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3526 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3526 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3526 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3533 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3533 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3533 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3533 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3539 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3539 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3539 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3539 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3544 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3544 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2017-3544 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2017-3544 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2019-25059 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2019-25059 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2019-25059 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2019-25059 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2020-16587 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2020-16587 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2020-16587 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2020-16587 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2020-16588 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2020-16588 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2020-16588 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2020-16588 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2021-20298 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2021-20298 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2021-20298 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2021-20298 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2021-20299 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2021-20299 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2021-20299 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2021-20299 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1921 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1921 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1921 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1921 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1922 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1922 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1922 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1922 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1923 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1923 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1923 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1923 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1924 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1924 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1924 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1924 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1925 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1925 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-1925 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-1925 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-2309 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-2309 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2022-2309 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2022-2309 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2023-4863 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2023-4863 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2023-4863 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2023-4863 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2023-5129 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2023-5129 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2023-5129 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2023-5129 diff --git a/tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2023-5217 b/tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2023-5217 similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/cve/min/CVE-2023-5217 rename to tests/unit/providers/rhel_legacy/test-fixtures/input/cve/min/CVE-2023-5217 diff --git a/tests/unit/providers/rhel/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml b/tests/unit/providers/rhel_legacy/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml rename to tests/unit/providers/rhel_legacy/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml diff --git a/tests/unit/providers/rhel/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml.sha256sum b/tests/unit/providers/rhel_legacy/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml.sha256sum similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml.sha256sum rename to tests/unit/providers/rhel_legacy/test-fixtures/input/rhsa/com.redhat.rhsa-all.xml.sha256sum diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3509.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3509.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3509.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3509.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3511.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3511.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3511.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3511.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3526.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3526.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3526.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3526.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3533.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3533.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3533.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3533.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3539.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3539.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3539.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3539.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3544.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3544.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:5/cve-2017-3544.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:5/cve-2017-3544.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3509.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3509.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3509.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3509.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3511.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3511.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3511.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3511.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3526.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3526.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3526.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3526.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3533.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3533.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3533.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3533.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3539.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3539.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3539.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3539.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3544.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3544.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2017-3544.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2017-3544.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2020-16587.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2020-16587.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2020-16587.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2020-16587.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2020-16588.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2020-16588.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2020-16588.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2020-16588.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2021-20298.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2021-20298.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2021-20298.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2021-20298.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2021-20299.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2021-20299.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2021-20299.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2021-20299.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1921.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1921.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1921.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1921.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1922.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1922.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1922.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1922.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1923.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1923.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1923.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1923.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1924.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1924.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1924.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1924.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1925.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1925.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2022-1925.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2022-1925.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2023-4863.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2023-4863.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2023-4863.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2023-4863.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2023-5129.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2023-5129.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2023-5129.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2023-5129.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2023-5217.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2023-5217.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:6/cve-2023-5217.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:6/cve-2023-5217.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3509.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3509.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3509.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3509.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3511.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3511.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3511.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3511.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3526.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3526.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3526.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3526.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3533.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3533.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3533.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3533.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3539.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3539.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3539.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3539.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3544.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3544.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2017-3544.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2017-3544.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2020-16587.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2020-16587.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2020-16587.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2020-16587.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2020-16588.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2020-16588.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2020-16588.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2020-16588.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2021-20298.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2021-20298.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2021-20298.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2021-20298.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2021-20299.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2021-20299.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2021-20299.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2021-20299.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1921.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1921.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1921.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1921.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1922.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1922.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1922.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1922.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1923.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1923.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1923.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1923.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1924.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1924.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1924.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1924.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1925.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1925.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2022-1925.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2022-1925.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2023-4863.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2023-4863.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2023-4863.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2023-4863.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2023-5129.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2023-5129.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2023-5129.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2023-5129.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2023-5217.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2023-5217.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:7/cve-2023-5217.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:7/cve-2023-5217.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2019-25059.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2019-25059.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2019-25059.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2019-25059.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2020-16587.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2020-16587.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2020-16587.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2020-16587.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2021-20298.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2021-20298.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2021-20298.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2021-20298.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2021-20299.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2021-20299.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2021-20299.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2021-20299.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1921.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1921.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1921.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1921.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1922.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1922.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1922.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1922.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1923.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1923.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1923.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1923.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1924.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1924.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1924.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1924.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1925.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1925.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2022-1925.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2022-1925.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2023-4863.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2023-4863.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2023-4863.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2023-4863.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2023-5129.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2023-5129.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2023-5129.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2023-5129.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2023-5217.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2023-5217.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:8/cve-2023-5217.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:8/cve-2023-5217.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2019-25059.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2019-25059.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2019-25059.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2019-25059.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1921.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1921.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1921.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1921.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1922.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1922.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1922.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1922.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1923.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1923.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1923.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1923.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1924.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1924.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1924.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1924.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1925.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1925.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-1925.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-1925.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-2309.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-2309.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2022-2309.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2022-2309.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2023-4863.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2023-4863.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2023-4863.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2023-4863.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2023-5129.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2023-5129.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2023-5129.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2023-5129.json diff --git a/tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2023-5217.json b/tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2023-5217.json similarity index 100% rename from tests/unit/providers/rhel/test-fixtures/snapshots/rhel:9/cve-2023-5217.json rename to tests/unit/providers/rhel_legacy/test-fixtures/snapshots/rhel:9/cve-2023-5217.json diff --git a/tests/unit/providers/rhel/test_rhel.py b/tests/unit/providers/rhel_legacy/test_rhel.py similarity index 99% rename from tests/unit/providers/rhel/test_rhel.py rename to tests/unit/providers/rhel_legacy/test_rhel.py index 186e96ee..527178c4 100644 --- a/tests/unit/providers/rhel/test_rhel.py +++ b/tests/unit/providers/rhel_legacy/test_rhel.py @@ -6,8 +6,8 @@ import pytest from vunnel import result, workspace -from vunnel.providers.rhel import Config, Provider, parser -from vunnel.providers.rhel.parser import Advisory, FixedIn, Parser +from vunnel.providers.rhel_legacy import Config, Provider, parser +from vunnel.providers.rhel_legacy.parser import Advisory, FixedIn, Parser class TestParser: From c793b561be195ba7d4a4dbc02c7d088f60626f3c Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Thu, 9 Jan 2025 12:11:47 -0500 Subject: [PATCH 2/9] chore: run quality gate on larger host Otherwise, the RHEL CSAF provider runs out disk space. Signed-off-by: Will Murphy --- .github/workflows/nightly-quality-gate.yaml | 2 +- .github/workflows/pr-quality-gate.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly-quality-gate.yaml b/.github/workflows/nightly-quality-gate.yaml index 80605a48..f824f10e 100644 --- a/.github/workflows/nightly-quality-gate.yaml +++ b/.github/workflows/nightly-quality-gate.yaml @@ -33,7 +33,7 @@ jobs: echo "providers=$content" >> $GITHUB_OUTPUT validate-provider: - runs-on: ubuntu-22.04 + runs-on: ubuntu-22.04-4core-16gb needs: select-providers strategy: matrix: diff --git a/.github/workflows/pr-quality-gate.yaml b/.github/workflows/pr-quality-gate.yaml index d7e364ec..541b3111 100644 --- a/.github/workflows/pr-quality-gate.yaml +++ b/.github/workflows/pr-quality-gate.yaml @@ -39,7 +39,7 @@ jobs: echo "providers=$content" >> $GITHUB_OUTPUT validate-provider: - runs-on: ubuntu-22.04 + runs-on: ubuntu-22.04-4core-16gb needs: select-providers if: contains(github.event.pull_request.labels.*.name, 'run-pr-quality-gate') From 96b4931be5c5367c81264e36e347f29c2b8a00a2 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 10 Jan 2025 14:49:26 -0500 Subject: [PATCH 3/9] chore: match black and ruff line length Signed-off-by: Will Murphy --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f5370225..54fe69cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -126,7 +126,7 @@ exclude = '''(?x)( )''' [tool.black] -line-length = 130 +line-length = 130 # this should match tool.ruff.line-length below exclude = ''' ( /( @@ -175,7 +175,7 @@ dirty = true [tool.ruff] cache-dir = ".cache/ruff" # allow for a wide-birth relative to what black will correct to -line-length = 150 +line-length = 130 # this should match tool.black.line-length above extend-exclude = [ "**/tests/**", From faba6d6d329ed1c08a40e9a367032dd977c86e4a Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 10 Jan 2025 14:54:19 -0500 Subject: [PATCH 4/9] distinguish not fixed from wont fix Signed-off-by: Will Murphy --- src/vunnel/providers/rhel_csaf/transformer.py | 8 +++++-- .../providers/rhel_csaf/test_transformer.py | 23 ++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/vunnel/providers/rhel_csaf/transformer.py b/src/vunnel/providers/rhel_csaf/transformer.py index af846790..cacd4390 100644 --- a/src/vunnel/providers/rhel_csaf/transformer.py +++ b/src/vunnel/providers/rhel_csaf/transformer.py @@ -2,7 +2,7 @@ from packageurl import PackageURL -from vunnel.utils.csaf_types import CSAFDoc, Score +from vunnel.utils.csaf_types import CSAFDoc, Remediation, Score from vunnel.utils.vulnerability import CVSS, AdvisorySummary, FixedIn, VendorAdvisory, Vulnerability RHEL_CPE_REGEXES = [ @@ -93,6 +93,10 @@ def parse_cvss(scores: list[Score], status: str, full_product_id: str) -> CVSS | return None +def marked_will_not_fix(remediations: list[Remediation], qpi: str) -> bool: + return any(r for r in remediations if qpi in r.product_ids and r.category == "no_fix_planned") + + def vulnerabilities_by_namespace( # noqa: C901, PLR0912, PLR0915 csaf: CSAFDoc, skip_namespaces: set[str] | None = None, @@ -147,7 +151,7 @@ def vulnerabilities_by_namespace( # noqa: C901, PLR0912, PLR0915 ] for qpi in qualified_product_ids: - vendor_advisory = VendorAdvisory(NoAdvisory=True, AdvisorySummary=[]) + vendor_advisory = VendorAdvisory(NoAdvisory=marked_will_not_fix(vuln.remediations, qpi), AdvisorySummary=[]) name = purl.name namespace_name = ns_matcher.namespace_from_product_id(qpi) diff --git a/tests/unit/providers/rhel_csaf/test_transformer.py b/tests/unit/providers/rhel_csaf/test_transformer.py index f5d38f50..2ec06ab8 100644 --- a/tests/unit/providers/rhel_csaf/test_transformer.py +++ b/tests/unit/providers/rhel_csaf/test_transformer.py @@ -1,4 +1,6 @@ -from vunnel.providers.rhel_csaf.transformer import base_vulnerability +import pytest + +from vunnel.providers.rhel_csaf.transformer import base_vulnerability, marked_will_not_fix from vunnel.utils.csaf_types import ( TLP, AggregateSeverity, @@ -11,6 +13,7 @@ ProductTree, Publisher, Reference, + Remediation, Tracking, Vulnerability, ) @@ -73,3 +76,21 @@ def test_base_vulnerability(): assert vuln.Description == description assert vuln.Severity == "High", "failed to normalize description" assert vuln.Link == link + + +@pytest.mark.parametrize("remediations,product_id,want_marked_will_not_fix", + [ + ([], "any", False), + ( + [Remediation(category="no_fix_planned", product_ids=set(["too-old-product"]), details="seriuosly, upgrade")], + "too-old-product", + True + ), + ( + [Remediation(category="no_fix_planned", product_ids=set(["too-old-product"]), details="seriuosly, upgrade")], + "newer-product", + False, + ) + ]) +def test_marked_will_not_fix(remediations, product_id, want_marked_will_not_fix): + assert marked_will_not_fix(remediations, product_id) == want_marked_will_not_fix From 40ee393802ca514ee1746f3a04df7125b4452b68 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Mon, 13 Jan 2025 14:01:46 -0500 Subject: [PATCH 5/9] chore: finish switching to delegating provider Signed-off-by: Will Murphy --- src/vunnel/providers/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vunnel/providers/__init__.py b/src/vunnel/providers/__init__.py index 3a1a309c..92e7bcd6 100644 --- a/src/vunnel/providers/__init__.py +++ b/src/vunnel/providers/__init__.py @@ -14,7 +14,6 @@ nvd, oracle, rhel, - rhel_csaf, sles, ubuntu, wolfi, @@ -32,7 +31,6 @@ nvd.Provider.name(): nvd.Provider, oracle.Provider.name(): oracle.Provider, rhel.Provider.name(): rhel.Provider, - rhel_csaf.Provider.name(): rhel_csaf.Provider, sles.Provider.name(): sles.Provider, ubuntu.Provider.name(): ubuntu.Provider, wolfi.Provider.name(): wolfi.Provider, From b44408ad7c5d75cb92bb06df47ddb2a5291cdc20 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Mon, 13 Jan 2025 14:04:07 -0500 Subject: [PATCH 6/9] fix: name filtering for non-module redundant packages Signed-off-by: Will Murphy --- src/vunnel/providers/rhel_csaf/transformer.py | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/vunnel/providers/rhel_csaf/transformer.py b/src/vunnel/providers/rhel_csaf/transformer.py index cacd4390..96f81efe 100644 --- a/src/vunnel/providers/rhel_csaf/transformer.py +++ b/src/vunnel/providers/rhel_csaf/transformer.py @@ -19,10 +19,16 @@ "critical": "Critical", } +# Product names like this are rarely vulnerable in and of themselves, but +# are listed in the RHEL CSAF data only because their src RPM or module +# versioned +DENY_SUBSTRINGS = ["-langpack-", "-debug", "-debuginfo"] + class NamespaceMatcher: - def __init__(self, csaf: CSAFDoc): + def __init__(self, csaf: CSAFDoc, skip_namespaces: set[str] | None = None): prefixes_to_namespaces = {} + self.skip_namespaces = skip_namespaces or set() for b in csaf.product_tree.branches[0].product_name_branches(): prefix = b.product_id() cpe = b.cpe() @@ -38,6 +44,8 @@ def __init__(self, csaf: CSAFDoc): def namespace_from_product_id(self, pid: str) -> str | None: for prefix, ns in self.prefixes_to_namespaces.items(): + if ns in self.skip_namespaces: + continue if pid.startswith(prefix): return ns return None @@ -45,27 +53,29 @@ def namespace_from_product_id(self, pid: str) -> str | None: class NameFilter: def __init__(self, csaf: CSAFDoc): - affected_top_level_products = [] + self.affected_top_level_products: set[str] = set() for b in csaf.product_tree.branches[0].branches: if b.category == "product_version" and b.product and b.product.product_id: - affected_top_level_products.append(b.product.product_id) + self.affected_top_level_products.add(b.product.product_id) - versionless_source_rpms = [] - rpm_module_names = [] + self.versionless_source_rpms: set[str] = set() + self.rpm_module_names: set[str] = set() for b in csaf.product_tree.branches[0].product_version_branches(): maybe_purl = b.purl() if maybe_purl: purl = PackageURL.from_string(maybe_purl) if purl and purl.qualifiers and isinstance(purl.qualifiers, dict): # noqa: SIM102 if purl.qualifiers.get("arch") in ["src", "noarch"] and not purl.version: - versionless_source_rpms.append(purl.name) + self.versionless_source_rpms.add(purl.name) if purl.type == "rpmmod" and purl.name: - rpm_module_names.append(purl.name) - self.included = set(affected_top_level_products + versionless_source_rpms + rpm_module_names) + self.rpm_module_names.add(purl.name) + self.all_expected_names = self.affected_top_level_products | self.rpm_module_names | self.versionless_source_rpms - def include(self, product_name: str) -> bool: - return product_name in self.included + def include(self, product_name: str, module_name: str | None) -> bool: + if module_name: + return product_name in self.all_expected_names + return not any(deny in product_name for deny in DENY_SUBSTRINGS) def base_vulnerability(csaf: CSAFDoc, namespace_name: str) -> Vulnerability: @@ -124,7 +134,7 @@ def vulnerabilities_by_namespace( # noqa: C901, PLR0912, PLR0915 if not csaf.product_tree.branches: return {} - ns_matcher = NamespaceMatcher(csaf=csaf) + ns_matcher = NamespaceMatcher(csaf=csaf, skip_namespaces=skip_namespaces) ns_to_vulnerability = {} module_pid_to_purl = {} # Keep a map of product IDs that represent modules to the PURLs @@ -199,7 +209,7 @@ def vulnerabilities_by_namespace( # noqa: C901, PLR0912, PLR0915 # doc before emitting a FixedIn for it. # Therefore, only include packages that are part of a module if the # name filter includes them - if module and not name_filter.include(purl.name): + if not name_filter.include(purl.name, module): continue if purl.version: version = purl.version From 6d044b1b57853d08ee6221975ddfa7e05d1dcfb9 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Wed, 15 Jan 2025 13:06:21 -0500 Subject: [PATCH 7/9] wip: more refactoring of transformer Signed-off-by: Will Murphy --- src/vunnel/providers/rhel_csaf/transformer.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/vunnel/providers/rhel_csaf/transformer.py b/src/vunnel/providers/rhel_csaf/transformer.py index 96f81efe..1f0a1c69 100644 --- a/src/vunnel/providers/rhel_csaf/transformer.py +++ b/src/vunnel/providers/rhel_csaf/transformer.py @@ -6,7 +6,8 @@ from vunnel.utils.vulnerability import CVSS, AdvisorySummary, FixedIn, VendorAdvisory, Vulnerability RHEL_CPE_REGEXES = [ - r"^cpe:/[ao]:redhat:enterprise_linux:(\d+)(::(client|server|workstation|appstream|baseos|realtime|crb|supplementary))*$", # appstream has :a: + # AppStream sometimes has ":a:" in CPE, not ":o:" + r"^cpe:/[ao]:redhat:enterprise_linux:(\d+)(::(client|server|workstation|appstream|baseos|realtime|crb|supplementary))*$", r"^cpe:/a:redhat:rhel_extras_rt:(\d+)", r"^cpe:/a:redhat:rhel_extras_rt:(\d+)", r"^cpe:/a:redhat:rhel_virtualization:(\d+)(::(client|server))?", @@ -161,14 +162,13 @@ def vulnerabilities_by_namespace( # noqa: C901, PLR0912, PLR0915 ] for qpi in qualified_product_ids: - vendor_advisory = VendorAdvisory(NoAdvisory=marked_will_not_fix(vuln.remediations, qpi), AdvisorySummary=[]) + if qpi in vuln.product_status.known_not_affected or qpi in vuln.product_status.under_investigation: + continue name = purl.name namespace_name = ns_matcher.namespace_from_product_id(qpi) if not namespace_name: continue - if skip_namespaces and namespace_name in skip_namespaces: - continue if namespace_name not in ns_to_vulnerability: ns_to_vulnerability[namespace_name] = base_vulnerability(csaf, namespace_name) version_format = "rpm" @@ -213,7 +213,7 @@ def vulnerabilities_by_namespace( # noqa: C901, PLR0912, PLR0915 continue if purl.version: version = purl.version - remediations = [r for r in vuln.remediations if qpi in r.product_ids] + remediations = [r for r in vuln.remediations if qpi in r.product_ids and r.category == "vendor_fix"] if remediations and remediations[0].url: vendor_advisory = VendorAdvisory( NoAdvisory=False, @@ -222,12 +222,8 @@ def vulnerabilities_by_namespace( # noqa: C901, PLR0912, PLR0915 ], ) elif qpi in vuln.product_status.known_affected: + vendor_advisory = VendorAdvisory(NoAdvisory=marked_will_not_fix(vuln.remediations, qpi), AdvisorySummary=[]) version = "None" - elif qpi in vuln.product_status.known_not_affected: - continue - elif qpi in vuln.product_status.under_investigation: - # TODO: should this be configurable? - continue if version != "None" and ":" not in version: epoch = purl.qualifiers.get("epoch", "0") if purl.qualifiers and isinstance(purl.qualifiers, dict) else "0" From 7c43c682e740150d09759ce7770365b993ed4300 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Wed, 15 Jan 2025 13:06:52 -0500 Subject: [PATCH 8/9] fix: use branch of grype with rpm version fix Signed-off-by: Will Murphy --- tests/quality/config.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/quality/config.yaml b/tests/quality/config.yaml index 97201f60..5796d807 100644 --- a/tests/quality/config.yaml +++ b/tests/quality/config.yaml @@ -25,7 +25,7 @@ yardstick: # Note: # - ALWAYS leave the "import-db" annotation as-is # - this version should ALWAYS match that of the other "grype" tool below - version: main+import-db=build/grype-db.tar.gz + version: fix-rpm-release-without-build-no+import-db=build/grype-db.tar.gz takes: SBOM - name: grype @@ -36,7 +36,7 @@ yardstick: # - a repo reference and optional "@branch" (e.g. "github.com/my-user-fork/grype@dev-fix-foo") # Note: # - this version should ALWAYS match that of the other "grype" tool above - version: main + version: fix-rpm-release-without-build-no takes: SBOM label: reference @@ -223,8 +223,7 @@ tests: - docker.io/anchore/test_images:appstreams-rhel-8-1a287dd@sha256:524ff8a75f21fd886ec7ed82387766df386671e8b77e898d05786118d5b7880b - docker.io/anchore/test_images:vulnerabilities-centos@sha256:746d31247006cc06434ce91ccf3523b2c230ff6c378ffed7ca1c60bbb48ea86f validations: - - <<: *default-validations - max_f1_regression: 0.09 + - *default-validations expected_namespaces: From 13ba0f3e05da18c1e8d3a1f503c31e5f5a42d3cf Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Wed, 15 Jan 2025 13:08:46 -0500 Subject: [PATCH 9/9] put line length back how it was Signed-off-by: Will Murphy --- pyproject.toml | 4 +-- .../providers/rhel_csaf/test_transformer.py | 30 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 54fe69cf..f5370225 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -126,7 +126,7 @@ exclude = '''(?x)( )''' [tool.black] -line-length = 130 # this should match tool.ruff.line-length below +line-length = 130 exclude = ''' ( /( @@ -175,7 +175,7 @@ dirty = true [tool.ruff] cache-dir = ".cache/ruff" # allow for a wide-birth relative to what black will correct to -line-length = 130 # this should match tool.black.line-length above +line-length = 150 extend-exclude = [ "**/tests/**", diff --git a/tests/unit/providers/rhel_csaf/test_transformer.py b/tests/unit/providers/rhel_csaf/test_transformer.py index 2ec06ab8..db34569e 100644 --- a/tests/unit/providers/rhel_csaf/test_transformer.py +++ b/tests/unit/providers/rhel_csaf/test_transformer.py @@ -78,19 +78,21 @@ def test_base_vulnerability(): assert vuln.Link == link -@pytest.mark.parametrize("remediations,product_id,want_marked_will_not_fix", - [ - ([], "any", False), - ( - [Remediation(category="no_fix_planned", product_ids=set(["too-old-product"]), details="seriuosly, upgrade")], - "too-old-product", - True - ), - ( - [Remediation(category="no_fix_planned", product_ids=set(["too-old-product"]), details="seriuosly, upgrade")], - "newer-product", - False, - ) - ]) +@pytest.mark.parametrize( + "remediations,product_id,want_marked_will_not_fix", + [ + ([], "any", False), + ( + [Remediation(category="no_fix_planned", product_ids=set(["too-old-product"]), details="seriuosly, upgrade")], + "too-old-product", + True, + ), + ( + [Remediation(category="no_fix_planned", product_ids=set(["too-old-product"]), details="seriuosly, upgrade")], + "newer-product", + False, + ), + ], +) def test_marked_will_not_fix(remediations, product_id, want_marked_will_not_fix): assert marked_will_not_fix(remediations, product_id) == want_marked_will_not_fix