Skip to content

Commit de41d84

Browse files
author
John Andersen
committed
feat: documentation on out of tree parsers
Signed-off-by: John Andersen <[email protected]>
1 parent d0b0a76 commit de41d84

File tree

13 files changed

+715
-9
lines changed

13 files changed

+715
-9
lines changed

cve_bin_tool/cvedb.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from __future__ import annotations
88

99
import asyncio
10+
import contextlib
1011
import datetime
1112
import json
1213
import logging
@@ -1193,3 +1194,11 @@ def fetch_from_mirror(self, mirror, pubkey, ignore_signature, log_signature_erro
11931194
else:
11941195
self.clear_cached_data()
11951196
return -1
1197+
1198+
@contextlib.contextmanager
1199+
def with_cursor(self):
1200+
cursor = self.db_open_and_get_cursor()
1201+
try:
1202+
yield cursor
1203+
finally:
1204+
self.db_close()

cve_bin_tool/parsers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"php",
2727
"perl",
2828
"dart",
29+
"env",
2930
]
3031

3132

cve_bin_tool/parsers/env.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Copyright (C) 2024 Intel Corporation
2+
# SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
from __future__ import annotations
5+
6+
import dataclasses
7+
import pathlib
8+
import re
9+
10+
from packageurl import PackageURL
11+
12+
from cve_bin_tool.parsers import Parser
13+
from cve_bin_tool.util import ProductInfo, ScanInfo
14+
15+
16+
@dataclasses.dataclass
17+
class EnvNamespaceConfig:
18+
ad_hoc_cve_id: str
19+
vendor: str
20+
product: str
21+
version: str
22+
location: str = "/usr/local/bin/product"
23+
24+
25+
@dataclasses.dataclass
26+
class EnvConfig:
27+
namespaces: dict[str, EnvNamespaceConfig]
28+
29+
30+
class EnvParser(Parser):
31+
"""
32+
Parser for Python requirements files.
33+
This parser is designed to parse Python requirements files (usually named
34+
requirements.txt) and generate PURLs (Package URLs) for the listed packages.
35+
"""
36+
37+
PARSER_MATCH_FILENAMES = [
38+
".env",
39+
]
40+
41+
@staticmethod
42+
def parse_file_contents(contents):
43+
lines = list(
44+
[
45+
line
46+
for line in contents.replace("\r\n", "\n").split("\n")
47+
if line.strip() and line.startswith("CVE_BIN_TOOL_")
48+
]
49+
)
50+
namespaces = {}
51+
for i, line in enumerate(lines):
52+
key, value = line.split("=", maxsplit=1)
53+
namespace, key = key[len("CVE_BIN_TOOL_") :].split("_", maxsplit=1)
54+
if value.startswith('"'):
55+
value = value[1:]
56+
if value.endswith('"'):
57+
value = value[:-1]
58+
namespaces.setdefault(namespace, {})
59+
namespaces[namespace][key.lower()] = value
60+
for namespace, config in namespaces.items():
61+
namespaces[namespace] = EnvNamespaceConfig(**config)
62+
return EnvConfig(namespaces=namespaces)
63+
64+
def run_checker(self, filename):
65+
"""
66+
Parse the .env file and yield ScanInfo objects for the listed packages.
67+
Args:
68+
filename (str): The path to the .env file.
69+
Yields:
70+
str: ScanInfo objects for the packages listed in the file.
71+
"""
72+
self.filename = filename
73+
contents = pathlib.Path(self.filename).read_text()
74+
75+
env_config = self.parse_file_contents(contents)
76+
77+
data_source = "environment"
78+
affected_data = [
79+
{
80+
"cve_id": cve.ad_hoc_cve_id,
81+
"vendor": cve.vendor,
82+
"product": cve.product,
83+
# TODO Version MUST be unique to this bug!
84+
"version": cve.version,
85+
"versionStartIncluding": "",
86+
# "versionStartIncluding": cve.version,
87+
"versionStartExcluding": "",
88+
"versionEndIncluding": "",
89+
# "versionEndIncluding": cve.version,
90+
"versionEndExcluding": "",
91+
}
92+
for _namespace, cve in env_config.namespaces.items()
93+
]
94+
severity_data = [
95+
{
96+
"ID": cve.ad_hoc_cve_id,
97+
# TODO severity
98+
"severity": "LOW",
99+
# TODO description
100+
"description": "TODO",
101+
# TODO score
102+
"score": 0,
103+
# TODO CVSS_version
104+
"CVSS_version": 3,
105+
# TODO CVSS_vector
106+
"CVSS_vector": "",
107+
"last_modified": "",
108+
}
109+
for _namespace, cve in env_config.namespaces.items()
110+
]
111+
112+
with self.cve_db.with_cursor() as cursor:
113+
self.cve_db.populate_cve_metrics(severity_data, cursor)
114+
self.cve_db.populate_severity(severity_data, cursor, data_source)
115+
self.cve_db.populate_affected(affected_data, cursor, data_source)
116+
117+
for _namespace, cve in env_config.namespaces.items():
118+
yield ScanInfo(
119+
ProductInfo(
120+
cve.vendor,
121+
cve.product,
122+
cve.version,
123+
cve.location,
124+
PackageURL(
125+
type="ad-hoc",
126+
namespace=cve.vendor,
127+
name=re.sub(r"[^a-zA-Z0-9._-]", "", cve.product).lower(),
128+
version=cve.version,
129+
qualifiers={},
130+
subpath=None,
131+
),
132+
),
133+
pathlib.Path(filename).resolve(),
134+
)

0 commit comments

Comments
 (0)