VulnTrain 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.3
2
+ Name: VulnTrain
3
+ Version: 0.1.0
4
+ Summary: Generate datasets amd models based on vulnerabilities descriptions from Vulnerability-Lookup.
5
+ License: GPL-3.0-or-later
6
+ Author: Cédric Bonhomme
7
+ Author-email: cedric.bonhomme@circl.lu
8
+ Requires-Python: >=3.10,<4.0
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Security
21
+ Requires-Dist: datasets (>=3.3.1,<4.0.0)
22
+ Requires-Dist: nltk (>=3.9.1,<4.0.0)
23
+ Requires-Dist: pandas (>=2.2.3,<3.0.0)
24
+ Requires-Dist: valkey (>=6.1.0,<7.0.0)
25
+ Project-URL: Homepage, https://github.com/vulnerability-lookup/VulnTrain
26
+ Project-URL: Repository, https://github.com/vulnerability-lookup/VulnTrain
27
+ Description-Content-Type: text/markdown
28
+
29
+ # VulnTrain
30
+
31
+ Generate datasets amd models based on vulnerabilities descriptions from Vulnerability-Lookup.
32
+
33
+ Uses data from the ``vulnerability-lookup:meta`` container such as vulnrichment and FKIE.
34
+
35
+
36
+ ## Usage
37
+
38
+ ### Generate datasets
39
+
40
+ Authenticate to HuggingFace:
41
+
42
+ ```bash
43
+ huggingface-cli login
44
+ ```
45
+
46
+ Creation of datasets:
47
+
48
+ ```bash
49
+ $ pipx install VulnTrain
50
+
51
+ $ vulntrain-create-dataset
52
+ DatasetDict({
53
+ train: Dataset({
54
+ features: ['id', 'title', 'description'],
55
+ num_rows: 4
56
+ })
57
+ test: Dataset({
58
+ features: ['id', 'title', 'description'],
59
+ num_rows: 1
60
+ })
61
+ })
62
+ Creating parquet from Arrow format: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1317.72ba/s]
63
+ Uploading the dataset shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1.16it/s]
64
+ Creating parquet from Arrow format: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 2233.39ba/s]
65
+ Uploading the dataset shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1.39it/s]
66
+ README.md: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 428/428 [00:00<00:00, 1.70MB/s]
67
+ ```
68
+
69
+
70
+ Train:
71
+
72
+ ```bash
73
+ $ vulntrain-train-dataset
74
+ ```
@@ -0,0 +1,46 @@
1
+ # VulnTrain
2
+
3
+ Generate datasets amd models based on vulnerabilities descriptions from Vulnerability-Lookup.
4
+
5
+ Uses data from the ``vulnerability-lookup:meta`` container such as vulnrichment and FKIE.
6
+
7
+
8
+ ## Usage
9
+
10
+ ### Generate datasets
11
+
12
+ Authenticate to HuggingFace:
13
+
14
+ ```bash
15
+ huggingface-cli login
16
+ ```
17
+
18
+ Creation of datasets:
19
+
20
+ ```bash
21
+ $ pipx install VulnTrain
22
+
23
+ $ vulntrain-create-dataset
24
+ DatasetDict({
25
+ train: Dataset({
26
+ features: ['id', 'title', 'description'],
27
+ num_rows: 4
28
+ })
29
+ test: Dataset({
30
+ features: ['id', 'title', 'description'],
31
+ num_rows: 1
32
+ })
33
+ })
34
+ Creating parquet from Arrow format: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1317.72ba/s]
35
+ Uploading the dataset shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1.16it/s]
36
+ Creating parquet from Arrow format: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 2233.39ba/s]
37
+ Uploading the dataset shards: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1.39it/s]
38
+ README.md: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 428/428 [00:00<00:00, 1.70MB/s]
39
+ ```
40
+
41
+
42
+ Train:
43
+
44
+ ```bash
45
+ $ vulntrain-train-dataset
46
+ ```
@@ -0,0 +1,54 @@
1
+ [build-system]
2
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
3
+ build-backend = "poetry.core.masonry.api"
4
+
5
+
6
+ [project]
7
+ name = "VulnTrain"
8
+ version = "0.1.0"
9
+ description = "Generate datasets amd models based on vulnerabilities descriptions from Vulnerability-Lookup."
10
+ authors = [
11
+ {name = "Cédric Bonhomme",email = "cedric.bonhomme@circl.lu"}
12
+ ]
13
+ license = "GPL-3.0-or-later"
14
+ readme = "README.md"
15
+
16
+ dynamic = ["classifiers"]
17
+
18
+ requires-python = ">=3.10,<4.0"
19
+
20
+
21
+ [project.urls]
22
+ Homepage = "https://github.com/vulnerability-lookup/VulnTrain"
23
+ Repository = "https://github.com/vulnerability-lookup/VulnTrain"
24
+
25
+
26
+ [project.scripts]
27
+ vulntrain-create-dataset = "vulntrain.create_dataset:main"
28
+ # vulntrain-train-dataset = "vulntrain.train:main"
29
+
30
+
31
+ [tool.poetry]
32
+ requires-poetry = ">=2.0"
33
+ classifiers = [
34
+ "Development Status :: 5 - Production/Stable",
35
+ "Environment :: Console",
36
+ "Intended Audience :: Developers",
37
+ "Intended Audience :: Science/Research",
38
+ "Topic :: Security",
39
+ "Operating System :: POSIX :: Linux",
40
+ "Programming Language :: Python :: 3.10",
41
+ "Programming Language :: Python :: 3.11",
42
+ "Programming Language :: Python :: 3.12",
43
+ "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)"
44
+ ]
45
+ include = [
46
+ "README.md",
47
+ "COPYING",
48
+ ]
49
+
50
+ [tool.poetry.dependencies]
51
+ nltk = "^3.9.1"
52
+ pandas = "^2.2.3"
53
+ datasets = "^3.3.1"
54
+ valkey = "^6.1.0"
File without changes
@@ -0,0 +1,151 @@
1
+ """
2
+ Creates a text/description dataset using vulnerabilities description from Vulnerability-Lookup.
3
+
4
+ Author: Cédric Bonhomme / CIRCL
5
+
6
+ """
7
+ import json
8
+ from typing import Any, Generator
9
+
10
+ import valkey
11
+ from datasets import Dataset, DatasetDict
12
+
13
+
14
+ class VulnExtractor:
15
+ def __init__(self):
16
+ self.valkey_client = valkey.Valkey(
17
+ host="127.0.0.1",
18
+ port=10002,
19
+ decode_responses=True,
20
+ )
21
+
22
+
23
+ def get_vulnerability_meta(self, vulnerability_id: str) -> dict[str, str | dict[str, Any]]:
24
+ _vid = vulnerability_id.lower()
25
+ to_return: dict[str, str | dict[str, Any]] = {}
26
+ for meta_name, meta_uuid in self.valkey_client.hgetall(f'{_vid}:meta').items():
27
+ if self.valkey_client.exists(f'{meta_name}:{meta_uuid}'):
28
+ if self.valkey_client.type(f'{meta_name}:{meta_uuid}') == 'string': # type: ignore[no-untyped-call] # noqa
29
+ if _meta_str := self.valkey_client.get(f'{meta_name}:{meta_uuid}'):
30
+ to_return[meta_name] = _meta_str
31
+ elif self.valkey_client.type(f'{meta_name}:{meta_uuid}') == 'hash': # type: ignore[no-untyped-call] # noqa
32
+ if _meta_hash := self.valkey_client.hgetall(f'{meta_name}:{meta_uuid}'):
33
+ to_return[meta_name] = _meta_hash
34
+ else:
35
+ print(f'Unable to find meta {meta_uuid} for {meta_name}')
36
+ return to_return
37
+
38
+
39
+ def get_vulnerability(self, vulnerability_id: str,
40
+ *, with_meta: bool | None=False) -> dict[str, Any] | None:
41
+ _vid = vulnerability_id.lower()
42
+ _vuln = self.valkey_client.get(_vid)
43
+ if not _vuln:
44
+ return None
45
+ vuln = json.loads(_vuln)
46
+ if with_meta:
47
+ if meta := self.get_vulnerability_meta(_vid):
48
+ vuln['vulnerability-lookup:meta'] = meta
49
+ return vuln
50
+
51
+ def get_all(self, source: str = "", /, with_meta: bool=False) -> Generator[dict[str, Any], None, None]:
52
+ """This method will scan a complete source and yield the vulnerabilities.
53
+ It is up to the caller to handle the yielded entries as it will be a lot"""
54
+ if source:
55
+ key = f'index:{source}'
56
+ else:
57
+ key = 'index'
58
+ for vuln_id, _ in self.valkey_client.zscan_iter(key):
59
+ if vuln := self.get_vulnerability(vuln_id, with_meta=with_meta):
60
+ yield vuln
61
+
62
+ def __call__(self):
63
+ count = 0
64
+ for vuln in self.get_all("nvd", True):
65
+ count += 1
66
+ if count == 10000:
67
+ return
68
+
69
+ vuln_cpes = []
70
+ if vulnrichment := vuln["vulnerability-lookup:meta"].get("vulnrichment", False):
71
+ containers = json.loads(vulnrichment["containers"])
72
+
73
+ # Check ADP section
74
+ if "adp" in containers:
75
+ for entry in containers["adp"]:
76
+ if "affected" in entry:
77
+ for affected in entry["affected"]:
78
+ if "cpes" in affected:
79
+ vuln_cpes.extend(affected["cpes"])
80
+
81
+ # Check CNA section
82
+ if "cna" in containers and "affected" in containers["cna"]:
83
+ for affected in containers["cna"]["affected"]:
84
+ if "cpes" in affected:
85
+ vuln_cpes.extend(affected["cpes"])
86
+
87
+ # for elem in vulnrichment["containers"]["adp"]["affected"]:
88
+ # if "cpes" in elem:
89
+ # print(elem)
90
+ # vuln_cpes = elem["cpes"]
91
+ # break
92
+ # else:
93
+ # vuln_cpes = []
94
+
95
+ vuln_id = vuln["cveMetadata"]["cveId"]
96
+
97
+ vuln_title = vuln["containers"]["cna"].get("title", "")
98
+
99
+ for description in vuln["containers"]["cna"].get("descriptions", []):
100
+ if description["lang"].lower() in ["en", "en-sn", "en-us"]:
101
+ vuln_description = description["value"]
102
+ break
103
+ else:
104
+ continue
105
+
106
+ # if not vuln_cpes:
107
+ # for elem in vuln["containers"]["cna"]["affected"]:
108
+ # if "cpes" in elem:
109
+ # vuln_cpes = elem["cpes"]
110
+ # break
111
+ # else:
112
+ # vuln_cpes = []
113
+
114
+
115
+
116
+ # print(vuln_cpes)
117
+
118
+ vuln_data = {
119
+ "id": vuln_id,
120
+ "title": vuln_title,
121
+ "description": vuln_description,
122
+ "cpes": vuln_cpes,
123
+ }
124
+ yield vuln_data
125
+
126
+
127
+
128
+
129
+
130
+ def main():
131
+ extractor = VulnExtractor()
132
+
133
+ vulns = list(extractor())
134
+
135
+ def gen():
136
+ for vuln in vulns:
137
+ yield vuln
138
+
139
+ dataset = Dataset.from_generator(gen)
140
+ train_test_split = dataset.train_test_split(test_size=0.1)
141
+ dataset_dict = DatasetDict(
142
+ {"train": train_test_split["train"], "test": train_test_split["test"]}
143
+ )
144
+
145
+ print(dataset_dict)
146
+ # dataset_dict.push_to_hub("cedricbonhomme/vulnerability-descriptions")
147
+ dataset_dict.push_to_hub("circl/vulnerability-dataset")
148
+
149
+
150
+ if __name__ == "__main__":
151
+ main()
@@ -0,0 +1,5 @@
1
+ from nltk.tokenize import sent_tokenize
2
+
3
+ def sentences(text, num_sentences=5):
4
+ sentences = sent_tokenize(text)[:num_sentences]
5
+ return " ".join(sentences)