summaryrefslogtreecommitdiffstats
path: root/bin/update-cve-descriptions
blob: e251865e24e9f30d0d05b8b4da9650aba25e08a5 (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
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/python3
#
# Fetch CVE descriptions from the MITRE CVE v5 and update the DB
#
# TODO: dedup code from check-new-issues
# TODO: change DB schema and remove unused columns and rename table
#
# Copyright © 2023 Emilio Pozuelo Monfort <pochu@debian.org>
#
# This file is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This file is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this file.  If not, see <https://www.gnu.org/licenses/>.

import io
import json
import os.path
import sys
import zipfile

import requests
import setup_paths
import security_db

cve5_zip = None

def get_cve5_zipfile():
    global cve5_zip

    if cve5_zip is None:
        cve5_file_url = 'https://github.com/CVEProject/cvelistV5/archive/refs/heads/main.zip'

        r = requests.get(cve5_file_url)
        cve5_zip_data = io.BytesIO(r.content)
        cve5_zip = zipfile.ZipFile(cve5_zip_data)

    return cve5_zip

def read_cve5_file():
    cve5s = {}

    z = get_cve5_zipfile()
    for fname in z.namelist():
        if os.path.basename(fname).startswith('CVE-'):
            #debug("found record " + fname)
            cve_id = os.path.basename(fname)[:-5]
            cve5s[cve_id] = fname

    return cve5s

def get_cve5(cve_id):
    global cve5_zip

    if cve_id not in cve5s:
        return None

    fname = cve5s[cve_id]

    #logging.info('loading file')
    f = cve5_zip.open(fname)
    #logging.info('loading json')
    return json.load(f)

def get_cve5_description(cve_id):
    cve = get_cve5(cve_id)
    desc = None

    if cve:
        if 'descriptions' in cve['containers']['cna']:
            desc = [desc['value']
                    for desc in cve['containers']['cna']['descriptions']
                    if desc['lang'].startswith('en')]
    if desc:
        desc = desc[0]

        # for some reason descriptions may contain new lines
        desc = desc.replace('\n', ' ')

        # and some contain leading spaces
        desc = desc.strip()

    return desc


base = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
db_file = os.path.join(base, 'data/security.db')
db = security_db.DB(db_file)

data = []
cve5s = read_cve5_file()

for cve_id, cve_file in cve5s.items():
    cve_desc = get_cve5_description(cve_id)

    # The DB schema requires the desc to not be NULL
    if not cve_desc:
        cve_desc = ""

    data.append((cve_id,
                 cve_desc,
                 "", # discovered
                 "", # published
                 "", # severity
                 "", # range local
                 "", # range remote
                 "", # range user init
                 "", # loss avail
                 "", # loss conf
                 "", # loss int
                 "", # loss sec prot user
                 "", # loss sec prot admin
                 "", # loss sec prot other
               ))

# Sort afterwards to increase locality in the insert process
data.sort()

cursor = db.writeTxn()
db.updateNVD(cursor, data, False)
db.commit(cursor)

© 2014-2024 Faster IT GmbH | imprint | privacy policy