aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/test_cve.py
blob: cd098d7bb12dbc84861c92f8127a00a6e08c89fa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
from __future__ import annotations

from pathlib import Path
from typing import Any

import pytest

import tests.data.cc.analysis.auxillary_datasets
from sec_certs.dataset import CVEDataset
from sec_certs.sample import CVE
from sec_certs.sample.cpe import CPE
from sec_certs.serialization.json import SerializationError


@pytest.mark.slow
@pytest.mark.monitor_test
@pytest.mark.xfail(reason="May fail due to errors on NIST server.")
def test_from_web():
    dset = CVEDataset.from_web()
    assert dset is not None
    assert "CVE-2019-15809" in dset.cves
    assert "CVE-2017-15361" in dset.cves


@pytest.fixture(scope="module")
def cve_dataset_path() -> Path:
    return Path(tests.data.cc.analysis.auxillary_datasets.__path__[0]) / "cve_dataset.json"


@pytest.fixture(scope="module")
def cve_dset(cves: list[CVE]) -> CVEDataset:
    cve_dset = CVEDataset({x.cve_id: x for x in cves})
    cve_dset.build_lookup_dict(use_nist_mapping=False)
    return cve_dset


@pytest.fixture(scope="module")
def cve_dict() -> dict[str, Any]:
    return {
        "cve_id": "CVE-1999-0001",
        "vulnerable_cpes": [
            {
                "uri": "cpe:2.3:o:freebsd:freebsd:1.0:*:*:*:*:*:*:*",
                "title": None,
                "start_version": None,
                "end_version": None,
            }
        ],
        "impact": {
            "_type": "Impact",
            "base_score": 5,
            "severity": "MEDIUM",
            "explotability_score": 10,
            "impact_score": 2.9,
        },
        "published_date": "1999-12-30T05:00:00+00:00",
        "cwe_ids": {"CWE-20"},
    }


@pytest.fixture(scope="module")
def cves() -> list[CVE]:
    cpe_single_sign_on = CPE(
        "cpe:2.3:a:ibm:security_access_manager_for_enterprise_single_sign-on:8.2.2:*:*:*:*:*:*:*",
        "IBM Security Access Manager For Enterprise Single Sign-On 8.2.2",
    )

    return [
        CVE(
            "CVE-2017-1732",
            [cpe_single_sign_on],
            CVE.Impact(5.3, "MEDIUM", 3.9, 1.4),
            "2021-05-26T04:15Z",
            {"CWE-200"},
        ),
        CVE(
            "CVE-2019-4513",
            [cpe_single_sign_on],
            CVE.Impact(8.2, "HIGH", 3.9, 4.2),
            "2000-05-26T04:15Z",
            {"CVE-611"},
        ),
    ]


def test_cve_dset_lookup_dicts(cves: list[CVE], cve_dset: CVEDataset):
    alt_lookup = {x: set(y) for x, y in cve_dset.cpe_to_cve_ids_lookup.items()}
    assert alt_lookup == {
        "cpe:2.3:a:ibm:security_access_manager_for_enterprise_single_sign-on:8.2.2:*:*:*:*:*:*:*": {
            x.cve_id for x in cves
        }
    }


def test_cve_dset_from_json(cve_dataset_path: Path, cve_dset: CVEDataset):
    dset = CVEDataset.from_json(cve_dataset_path)
    assert dset == cve_dset


def test_cve_from_to_dict(cve_dict: dict[str, Any]):
    cve = CVE.from_dict(cve_dict)
    ret = cve.to_dict()
    assert ret == cve_dict
    other_cve = CVE.from_dict(ret)
    assert cve == other_cve


def test_to_pandas(cve_dset: CVEDataset):
    df = cve_dset.to_pandas()
    assert df.shape == (len(cve_dset), len(CVE.pandas_columns) - 1)
    assert df.index.name == "cve_id"
    assert set(df.columns) == set(CVE.pandas_columns) - {"cve_id"}


def test_serialization_missing_path():
    dummy_dset = CVEDataset({})
    with pytest.raises(SerializationError):
        dummy_dset.to_json()