bziemba commited on
Commit
4c82e5c
·
verified ·
1 Parent(s): 36b782b

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +132 -2
README.md CHANGED
@@ -1,9 +1,139 @@
1
  ---
2
- license: apache-2.0
 
3
  datasets:
4
  - bziemba/cve_cwe_cvss
5
  language:
6
  - en
7
  base_model:
8
  - cisco-ai/SecureBERT2.0-biencoder
9
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+
3
+ license: mit
4
  datasets:
5
  - bziemba/cve_cwe_cvss
6
  language:
7
  - en
8
  base_model:
9
  - cisco-ai/SecureBERT2.0-biencoder
10
+ tags:
11
+ - cybersecurity
12
+ - vulnerability-classification
13
+ - cvss
14
+ - cwe
15
+ - securebert
16
+ - multi-task-learning
17
+ ---
18
+
19
+ # SecureBERT Vulnerability Classifier (CVSS & CWE Flat Classifier)
20
+
21
+ This model automatically analyzes raw vulnerability descriptions (e.g., CVE reports, bug bounty submissions) and predicts **CVSS v3.1 metrics** alongside a 4-level **CWE taxonomy** (Pillar, Class, Base, Variant).
22
+
23
+ It is a fine-tuned version of the domain-specific [`cisco-ai/SecureBERT2.0`](https://huggingface.co/cisco-ai/SecureBERT2.0) utilizing a Multi-Task Learning (MTL) architecture with flat classification heads.
24
+
25
+ ## 🎯 Intended Use
26
+
27
+ The primary use case is automating the initial **Vulnerability Triage** process. By inputting unstructured threat narratives, security analysts can instantly receive:
28
+ * **8 CVSS v3.1 Metrics:** Attack Vector, Attack Complexity, Privileges Required, User Interaction, Scope, Confidentiality, Integrity, and Availability.
29
+ * **CWE Classification:** Probabilistic mapping to the MITRE CWE tree across 4 levels of abstraction (Top-K predictions).
30
+
31
+ ## 🧠 Model Architecture
32
+
33
+ The model uses a shared `SecureBERT2.0` backbone with 12 distinct classification heads attached to the pooled outputs:
34
+ * **CVSS Heads (8):** Multi-Layer Perceptrons (MLP) consisting of `LayerNorm -> Linear -> GELU -> Dropout -> Linear -> Softmax`. They use the `[CLS]` token embedding to predict nominal and ordinal CVSS categories.
35
+ * **CWE Heads (4):** Multi-Layer Perceptrons (MLP) consisting of `LayerNorm -> Linear -> GELU -> Dropout -> Linear. These heads utilize the Mean-Pooled token embeddings.
36
+
37
+ ## 📂 Repository Structure & Custom Config
38
+
39
+ Unlike standard Hugging Face models, this repository features a highly customized `config.json`. It dynamically dictates the architecture and handles label decoding.
40
+ * `cvss_map`: Contains the exact string labels for all 8 CVSS metrics (e.g., `["Network", "Adjacent", "Local", "Physical"]`).
41
+ * `cwe_labels`: Contains ID-to-Name mappings for all supported CWEs across `pillar`, `class`, `base`, and `variant` levels.
42
+
43
+ **Note:** Because of the custom multi-head architecture, you cannot use the default `AutoModelForSequenceClassification`. You must define the custom PyTorch class provided in the usage snippet below.
44
+
45
+ ## 💻 Usage & Inference
46
+
47
+ Below is a complete, standalone Python snippet to load the model, tokenizer, and configuration directly from this Hugging Face repository and perform predictions.
48
+
49
+ ```python
50
+ import json
51
+ import torch
52
+ import torch.nn as nn
53
+ import torch.nn.functional as F
54
+ from transformers import AutoConfig, AutoModel, AutoTokenizer
55
+ from huggingface_hub import hf_hub_download
56
+
57
+ # 1. Define the Custom Architecture
58
+ class SecureBERTFlatClassifier(nn.Module):
59
+ def __init__(self, model_name, cvss_map, class_counts):
60
+ super().__init__()
61
+ config = AutoConfig.from_pretrained(model_name)
62
+ if hasattr(config, "reference_compile"): config.reference_compile = False
63
+ self.bert = AutoModel.from_pretrained(model_name, config=config)
64
+
65
+ def make_head(out_features, is_cvss=False):
66
+ layers =[
67
+ nn.LayerNorm(768), nn.Dropout(0.1),
68
+ nn.Linear(768, 768), nn.GELU(), nn.Dropout(0.1),
69
+ nn.Linear(768, 768), nn.GELU(), nn.Dropout(0.1),
70
+ nn.Linear(768, out_features)
71
+ ]
72
+ if is_cvss: layers.append(nn.Softmax(dim=1))
73
+ return nn.Sequential(*layers)
74
+
75
+ self.cvss_heads = nn.ModuleDict({k: make_head(len(v), True) for k, v in cvss_map.items()})
76
+ self.cwe_heads = nn.ModuleDict({k: make_head(v) for k, v in class_counts.items()})
77
+
78
+ def forward(self, input_ids, attention_mask):
79
+ out = self.bert(input_ids=input_ids, attention_mask=attention_mask).last_hidden_state
80
+ cls_emb = out[:, 0, :]
81
+ mask = attention_mask.unsqueeze(-1).expand(out.size()).float()
82
+ mean_emb = torch.sum(out * mask, 1) / torch.clamp(mask.sum(1), min=1e-9)
83
+
84
+ res = {}
85
+ for k, head in self.cvss_heads.items(): res[k] = head(cls_emb)
86
+ for k, head in self.cwe_heads.items(): res[k] = head(mean_emb)
87
+ return res
88
+
89
+ # 2. Inference Wrapper
90
+ class VulnPredictor:
91
+ def __init__(self, repo_id):
92
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
93
+
94
+ conf_path = hf_hub_download(repo_id=repo_id, filename="config.json")
95
+ model_path = hf_hub_download(repo_id=repo_id, filename="pytorch_model.bin")
96
+
97
+ with open(conf_path, "r") as f: self.config = json.load(f)
98
+
99
+ base_model = self.config.get("base_model", "cisco-ai/SecureBERT2.0-biencoder")
100
+ counts = {k: len(v) for k, v in self.config.get("cwe_labels", {}).items()}
101
+
102
+ self.tokenizer = AutoTokenizer.from_pretrained(base_model)
103
+ self.model = SecureBERTFlatClassifier(base_model, self.config["cvss_map"], counts)
104
+ self.model.load_state_dict(torch.load(model_path, map_location=self.device), strict=False)
105
+ self.model.to(self.device).eval()
106
+
107
+ def predict(self, text, top_k=3):
108
+ inputs = self.tokenizer(text, return_tensors="pt", truncation=True, max_length=512).to(self.device)
109
+ with torch.no_grad():
110
+ out = self.model(inputs['input_ids'], inputs['attention_mask'])
111
+
112
+ res = {'cvss': {}, 'cwe': {}}
113
+ for task, labels in self.config.get("cvss_map", {}).items():
114
+ score, idx = torch.max(out[task], dim=1)
115
+ res['cvss'][task] = {"value": labels[idx.item()], "confidence": round(score.item(), 4)}
116
+
117
+ for lv, cwe_data in self.config.get("cwe_labels", {}).items():
118
+ if lv in out:
119
+ probs = F.softmax(out[lv], dim=1)
120
+ scores, idxs = torch.topk(probs, k=min(top_k, probs.size(1)))
121
+ res['cwe'][lv] =[
122
+ {"id": int(str(cwe_data[i.item()]['id']).replace('CWE-','')),
123
+ "name": cwe_data[i.item()]['name'],
124
+ "score": round(s.item(), 4)} for s, i in zip(scores[0], idxs[0])
125
+ ]
126
+ return res
127
+
128
+ # 3. Quickstart
129
+ if __name__ == "__main__":
130
+ # REPALCE WITH YOUR REPOSITORY ID
131
+ REPO_ID = "YourUsername/Your-Repo-Name"
132
+
133
+ predictor = VulnPredictor(REPO_ID)
134
+
135
+ sample_cve = "An issue was discovered in the login panel allowing attackers to bypass authentication via crafted SQL queries."
136
+ results = predictor.predict(sample_cve)
137
+
138
+ print(json.dumps(results, indent=2))
139
+