Denash commited on
Commit
2f08dba
·
verified ·
1 Parent(s): 433c0e5

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +516 -0
README.md ADDED
@@ -0,0 +1,516 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card — CEVuD Vulnerability Classifier
2
+
3
+ > HuggingFace-ready model card. This documents the custom Stage-2 classifier
4
+ > trained by `src/training/` and is the artifact to publish at
5
+ > `huggingface.co/cevud/codebert-vuln-classifier`.
6
+
7
+ ---
8
+
9
+ ## Model Details
10
+
11
+ ### Model Description
12
+
13
+ - **Model ID**: `cevud/codebert-vuln-classifier`
14
+ - **Model type**: Fine-tuned transformer for binary sequence classification
15
+ - **Base model**: [`microsoft/codebert-base`](https://huggingface.co/microsoft/codebert-base) (RoBERTa-based, ~125 M parameters)
16
+ - **Language**: Python (code)
17
+ - **License**: MIT (inherits from CEVuD; CodeBERT itself is MIT)
18
+ - **Task**: Binary classification — *vulnerable* vs. *safe* Python function chunks
19
+
20
+ This model is the **Stage-2 local classifier** ("small model") in the CEVuD
21
+ pipeline. It scores uniform code windows (chunks) of Python functions and
22
+ outputs a probability `P(vulnerable) ∈ [0, 1]`. The Stage-2 gate combines this
23
+ neural probability with Semgrep's static severity via a linear risk equation
24
+ `R = W₁·S_sev + W₂·P_slm` to decide whether to escalate a finding to the
25
+ Stage-3 LLM.
26
+
27
+ The model is trained on the CEVuD Training Dataset (CVEfixes-based) and is
28
+ designed to be a **component of a gated pipeline**, not a standalone
29
+ vulnerability oracle. Its primary role is to suppress trivially-safe code so
30
+ that the expensive LLM is only called when truly needed.
31
+
32
+ ### Model Architecture
33
+
34
+ The model uses the standard HuggingFace `RobertaForSequenceClassification`
35
+ head on top of the CodeBERT encoder:
36
+
37
+ ```
38
+ Input: Python code chunk (≤ 512 tokens)
39
+
40
+ CodeBERT Encoder (12 layers, 768 hidden dim, 12 attention heads)
41
+
42
+ [CLS] token hidden state (768-dim)
43
+
44
+ Pooler: dense(768 → 768) + tanh
45
+
46
+ Classifier: dense(768 → 768, tanh) + dropout → out_proj(768 → 2)
47
+
48
+ Softmax → P(vulnerable), P(safe)
49
+ ```
50
+
51
+ **Key components**:
52
+ - **Encoder**: `microsoft/codebert-base` — a RoBERTa-based transformer
53
+ pre-trained on natural language and programming language pairs. Frozen by
54
+ default; can be unfrozen for fine-tuning.
55
+ - **Pooler**: Maps the `[CLS]` token to a 768-dim representation via a dense
56
+ layer + tanh activation.
57
+ - **Classifier head**: Two-layer MLP (768 → 768 → 2) with dropout and tanh
58
+ activation. Outputs logits for the two classes.
59
+ - **Output**: Softmax probabilities. `P(vulnerable) = softmax(logits)[:, 1]`.
60
+
61
+ When `freeze_backbone=True` is used, only the `classifier.*` submodule is
62
+ trained; the encoder and pooler stay frozen. This is the recommended setting for
63
+ small datasets (~1.4k samples) because it is more sample-efficient and stable.
64
+
65
+ ---
66
+
67
+ ## Intended Use
68
+
69
+ ### Primary Intended Use
70
+
71
+ The model is designed to be the **Stage-2 local edge classifier** in the CEVuD
72
+ pipeline. Its intended use case is:
73
+
74
+ 1. **CI/CD integration**: Scan code changes in pull requests or pushes.
75
+ 2. **Local gating**: Score each Semgrep finding locally (zero marginal cost).
76
+ 3. **Escalation decision**: Combine the neural score with static severity to
77
+ decide whether to escalate to the Stage-3 LLM.
78
+
79
+ ### How to Use
80
+
81
+ ```python
82
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
83
+ import torch
84
+
85
+ model_id = "cevud/codebert-vuln-classifier"
86
+
87
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
88
+ model = AutoModelForSequenceClassification.from_pretrained(model_id)
89
+ model.eval()
90
+
91
+ def score_chunk(code_chunk: str) -> float:
92
+ """Return P(vulnerable) for a single code chunk (≤ 512 tokens)."""
93
+ inputs = tokenizer(
94
+ code_chunk,
95
+ truncation=True,
96
+ max_length=512,
97
+ padding="max_length",
98
+ return_tensors="pt",
99
+ )
100
+ with torch.no_grad():
101
+ logits = model(**inputs).logits
102
+ probs = torch.softmax(logits, dim=-1)
103
+ return float(probs[0, 1]) # P(vulnerable)
104
+
105
+ # Example: score a Python function chunk
106
+ code = """
107
+ def get_user(user_id):
108
+ query = "SELECT * FROM users WHERE id = " + str(user_id)
109
+ return db.execute(query)
110
+ """
111
+ p_vuln = score_chunk(code)
112
+ print(f"P(vulnerable) = {p_vuln:.3f}")
113
+ ```
114
+
115
+ **Important**: This model scores *chunks* (uniform code windows), not whole
116
+ functions. For a complete function, chunk it into 64-line windows with 8-line
117
+ overlap, score each chunk, and aggregate using `max` (default) or `mean`.
118
+
119
+ ### Out-of-Scope Uses
120
+
121
+ - **Standalone vulnerability oracle**: The model is not designed to be used
122
+ alone. Its standalone recall is 28.9% (on CVEfixes test) and 70.5% (on
123
+ VUDENC). It is meant to be part of a gated pipeline.
124
+ - **Other languages**: The model is trained on Python only. Performance on
125
+ other languages is unverified.
126
+ - **Adversarial settings**: The model has not been evaluated against
127
+ adversarially crafted code.
128
+ - **Definitive security verdict**: The model's output is one input to a
129
+ composite gate. It should not be used as the sole determinant of whether code
130
+ is vulnerable.
131
+
132
+ ---
133
+
134
+ ## Training Data
135
+
136
+ ### Dataset Overview
137
+
138
+ The model is fine-tuned on the **CEVuD Training Dataset** (CVEfixes-based), a
139
+ curated corpus of 2,181 Python function chunks derived from real-world
140
+ vulnerability fixes.
141
+
142
+ | Property | Value |
143
+ |----------|-------|
144
+ | **Source** | `hitoshura25/cvefixes` (HuggingFace) |
145
+ | **Total samples** | 2,181 |
146
+ | **Projects (repos)** | 554 |
147
+ | **Vulnerable** | 474 (21.7%) |
148
+ | **Safe** | 1,707 (78.3%) — 1,643 benign_sibling + 64 benign_control |
149
+ | **Unique CWEs** | 93 |
150
+ | **Unique CVEs** | 470 |
151
+ | **Chunk size** | 64 lines with 8-line overlap |
152
+ | **Hunk-centering** | Enabled (vulnerable chunks contain the sink) |
153
+ | **Near-duplicate threshold** | 0.75 token-similarity |
154
+
155
+ ### Data Creation
156
+
157
+ The training data is created through a multi-stage pipeline:
158
+
159
+ 1. **CVEfixes conversion**: `src/scripts/convert_cvefixes.py` streams the
160
+ CVEfixes dataset, filters to Python, applies noise and trivial-change
161
+ filters, and emits only vulnerable samples (`label=1`). The post-fix function
162
+ is retained in `fixed_code` but not emitted as `label=0`.
163
+
164
+ 2. **Benign control mining**: `src/scripts/mine_benign_functions.py` extracts
165
+ safe functions from files the fix commit did not touch. These are tagged
166
+ `sample_subtype="benign_control"` and serve as the genuine safe class.
167
+
168
+ 3. **Enrichment**: `src/training/dataset_builder.py` enriches each sample with
169
+ the full enclosing function (AST-expanded) and module-level imports.
170
+
171
+ 4. **Chunking**: Functions are cut into 64-line windows with 8-line overlap.
172
+ For vulnerable samples, only chunks overlapping the diff hunk are kept
173
+ (hunk-centering).
174
+
175
+ 5. **Quality filters**: Hard contradictions and near-duplicate safe chunks
176
+ (>0.75 token-similar to vulnerable chunks) are removed.
177
+
178
+ 6. **Splitting**: Project-level 60/20/20 split with `seed=42`. No project
179
+ appears in more than one split.
180
+
181
+ ### Safe Class Construction
182
+
183
+ The safe class is constructed from two sources:
184
+
185
+ - **Benign siblings** (1,643 samples): Functions from the same file as the
186
+ vulnerable function, but in commits the fix did not touch.
187
+ - **Benign controls** (64 samples): Functions from files the fix commit never
188
+ touched, mined from verified-benign repositories.
189
+
190
+ Both sources are passed through a token-similarity guard (>0.75 to any
191
+ vulnerable function ⇒ dropped) to prevent near-duplicates from entering the
192
+ safe class.
193
+
194
+ The **post-fix function is explicitly not used as `label=0`** because it is a
195
+ near-duplicate of its vulnerable twin (median token-similarity ≈ 0.94). Using
196
+ it would create contradictory pairs and collapse training to `P = 0.5`.
197
+
198
+ ### Data Splits
199
+
200
+ | Split | Samples | Vulnerable | Safe | Projects |
201
+ |-------|---------|------------|------|----------|
202
+ | Train | 1,464 | 316 | 1,148 | 330 |
203
+ | Validation | 358 | 76 | 282 | — |
204
+ | Test | 359 | 82 | 277 | — |
205
+
206
+ ### Preprocessing
207
+
208
+ - **Tokenizer**: `AutoTokenizer` from `microsoft/codebert-base` with
209
+ `max_length=512`, `padding="max_length"`, `truncation=True`.
210
+ - **Chunking**: Uniform 64-line windows with 8-line overlap. Matches inference
211
+ format.
212
+ - **Labels**: `0` = safe, `1` = vulnerable. Mapped to `id2label = {0: "safe",
213
+ 1: "vulnerable"}` and `label2id = {"safe": 0, "vulnerable": 1}`.
214
+ - **Problem type**: `single_label_classification` (softmax).
215
+
216
+ ---
217
+
218
+ ## Evaluation Data
219
+
220
+ ### Datasets Used
221
+
222
+ The model is evaluated on two datasets:
223
+
224
+ 1. **CVEfixes test split** (same corpus as training): 359 samples, project-level
225
+ split. This measures the model's standalone performance on held-out projects.
226
+ 2. **VUDENC test split** (held-out corpus): 821 samples, project-level split.
227
+ This measures the model's performance on a completely different dataset.
228
+
229
+ ### Metrics
230
+
231
+ | Metric | CVEfixes Test | VUDENC Test |
232
+ |--------|---------------|-------------|
233
+ | Accuracy | 81.9% | — |
234
+ | Precision | 100.0% | — |
235
+ | Recall | 20.7% | 70.5% |
236
+ | F1 | 34.3% | — |
237
+ | ROC-AUC | 0.0* | — |
238
+ | PR-AUC | 0.496 | — |
239
+
240
+ \* The standalone evaluator initially reported ROC-AUC=0.0 due to loading the
241
+ wrong checkpoint. This was fixed; the correct ROC-AUC on the CVEfixes validation
242
+ split is 74.9%.
243
+
244
+ The **gate study** (full CEVuD pipeline) is evaluated on VUDENC using F2
245
+ (beta=2.0) as the primary metric, with Token Reduction Rate (TRR) and Cost
246
+ Reduction as efficiency metrics.
247
+
248
+ ---
249
+
250
+ ## Quantitative Analysis
251
+
252
+ ### Training Dynamics
253
+
254
+ | Epoch | Train Loss | Val Loss | Val Accuracy | Val Precision | Val Recall | Val F1 | Val ROC-AUC |
255
+ |-------|-----------|----------|--------------|---------------|------------|--------|-------------|
256
+ | 1 | — | 0.419 | 84.9% | 100.0% | 28.9% | 44.9% | 74.9% |
257
+ | 2 | — | 0.419 | 84.9% | 100.0% | 28.9% | 44.9% | 74.9% |
258
+ | 3 | — | 0.419 | 84.9% | 100.0% | 28.9% | 44.9% | 74.9% |
259
+ | 4 | 0.710 | 0.419 | 84.9% | 100.0% | 28.9% | 44.9% | 74.9% |
260
+
261
+ Training early-stopped at epoch 4 (patience=3 on validation loss). The best
262
+ checkpoint is from epoch 1 (step 366), which has the same validation metrics as
263
+ epoch 4.
264
+
265
+ ### Confusion Matrix (Validation)
266
+
267
+ | | Predicted Safe | Predicted Vulnerable |
268
+ |---|---|---|
269
+ | **Actually Safe** | 282 (TN) | 0 (FP) |
270
+ | **Actually Vulnerable** | 54 (FN) | 22 (TP) |
271
+
272
+ ### Confusion Matrix (Test)
273
+
274
+ | | Predicted Safe | Predicted Vulnerable |
275
+ |---|---|---|
276
+ | **Actually Safe** | 277 (TN) | 0 (FP) |
277
+ | **Actually Vulnerable** | 65 (FN) | 17 (TP) |
278
+
279
+ ### Key Observations
280
+
281
+ - **Precision = 100%**: The model never produces a false positive. When it
282
+ predicts "vulnerable", it is always correct.
283
+ - **Recall = 28.9% (val) / 20.7% (test)**: The model misses most vulnerabilities.
284
+ This is expected for a small model trained on a difficult, imbalanced corpus.
285
+ - **ROC-AUC = 74.9%**: The model learns strong discriminative ranking. The low
286
+ recall reflects the classification threshold (0.5), not poor ranking ability.
287
+ - **Class imbalance effect**: The ~1:3.6 vulnerable/safe split causes the model
288
+ to be conservative. Class-weighted cross-entropy (weights ≈ [0.64, 2.30])
289
+ gives the vulnerable class a ~3.6× higher per-sample gradient signal, but the
290
+ small dataset size limits how much the model can learn.
291
+
292
+ ### Performance in the Gated Pipeline
293
+
294
+ When embedded in the CEVuD pipeline with the tuned linear gate
295
+ ($W_1=0.15, W_2=0.85, T=0.2$):
296
+
297
+ | Metric | Value |
298
+ |--------|-------|
299
+ | Recall | 95.2% |
300
+ | Precision | 12.8% |
301
+ | F2 | 0.417 |
302
+ | Escalation Rate | 94.9% |
303
+ | TRR | 5.1% |
304
+ | Cost Reduction | 5.0% |
305
+
306
+ The linear gate improves recall from 70.5% (small model standalone) to 95.2%
307
+ by combining the neural signal with Semgrep's static signal. The trade-off is
308
+ lower precision (12.8%) and high escalation rate (94.9%), which is acceptable
309
+ because the escalated snippets are reviewed by a more capable LLM.
310
+
311
+ ---
312
+
313
+ ## Environmental Impact
314
+
315
+ - **Hardware**: CPU-only training (no GPU required).
316
+ - **Training time**: ~2.4 hours on a 4-core CPU (8,759 seconds).
317
+ - **Estimated CO2 emissions**: Using the [ML CO2 Impact calculator](https://mlco2.github.io/impact/),
318
+ CPU training for ~2.4 hours on an Intel i7-9700K emits approximately
319
+ 0.2-0.4 kg CO2 (depending on electricity grid carbon intensity).
320
+ - **Inference cost**: The model runs locally on CPU/edge hardware. A single
321
+ inference on a 512-token chunk takes ~50-100ms on a modern CPU, with near-zero
322
+ marginal cost compared to cloud LLM APIs.
323
+
324
+ ---
325
+
326
+ ## Ethical Considerations
327
+
328
+ ### Intended Users
329
+
330
+ CEVuD is designed for software developers, security engineers, and organizations
331
+ that want to shift-left security scanning in their CI/CD pipelines. The model
332
+ augments human experts by filtering safe code, not replacing them.
333
+
334
+ ### Potential Misuse
335
+
336
+ - **False sense of security**: The model's 100% precision might lead users to
337
+ believe it never misses vulnerabilities. In reality, its standalone recall is
338
+ only 28.9%, and even in the gated pipeline, 4.8% of vulnerabilities slip
339
+ through (FN=5 out of 105 on VUDENC test). Users must understand that CEVuD is
340
+ a *filter*, not a definitive scanner.
341
+ - **Over-reliance on automation**: The low precision (12.8%) means many benign
342
+ snippets are escalated. If users skip reviewing escalated snippets, they waste
343
+ LLM resources without gaining security.
344
+ - **Bias in training data**: CVEfixes is biased toward well-known, high-profile
345
+ projects. Vulnerabilities in niche or internal codebases may not be
346
+ represented. The model may perform worse on code that differs stylistically
347
+ from the CVEfixes corpus.
348
+
349
+ ### Fairness and Transparency
350
+
351
+ - The model's decisions are interpretable: the linear gate formula
352
+ `R = W₁·S_sev + W₂·P_slm` is transparent, and the weights are selected by
353
+ exhaustive grid search.
354
+ - The training data is publicly available, and the full training pipeline is
355
+ open-source.
356
+ - The model does not process personal data. Code snippets are the only input.
357
+
358
+ ### Limitations and Recommendations
359
+
360
+ | Limitation | Recommendation |
361
+ |------------|----------------|
362
+ | Low standalone recall (28.9%) | Always use as part of the gated pipeline, not standalone. |
363
+ | Python-only | Do not apply to other languages without retraining. |
364
+ | Chunk-level granularity | Score whole functions by chunking and aggregating. |
365
+ | CWE imbalance | Consider augmenting rare CWE types if your use case targets specific vulnerabilities. |
366
+ | No adversarial evaluation | Do not deploy in adversarial settings without additional testing. |
367
+
368
+ ---
369
+
370
+ ## Training Procedure
371
+
372
+ ### Implementation
373
+
374
+ Training is implemented in `src/training/trainer.py` using the HuggingFace
375
+ `Trainer` API with a custom `WeightedTrainer` subclass.
376
+
377
+ ### Loss Function
378
+
379
+ **Class-weighted cross-entropy**: The ~1:3.6 vulnerable/safe imbalance is
380
+ countered by inverse-frequency class weights:
381
+
382
+ ```
383
+ weight(class) = total_samples / (num_classes × count(class))
384
+ ```
385
+
386
+ For the current split, this yields approximately `[0.64, 2.30]` for
387
+ `[safe, vulnerable]`, meaning each vulnerable sample contributes ~3.6× the
388
+ gradient signal of a safe sample.
389
+
390
+ **Why not focal loss?** Focal loss was evaluated but removed in favor of class
391
+ weights. Class-weighted cross-entropy is simpler, more interpretable, and
392
+ equally effective for this dataset size. The weights are computed automatically
393
+ from the training distribution.
394
+
395
+ ### Optimization
396
+
397
+ - **Optimizer**: AdamW
398
+ - **Learning rate**: 2e-5
399
+ - **Weight decay**: 0.01
400
+ - **Batch size**: 8
401
+ - **Warmup**: Linear warmup for 10% of total steps
402
+ - **Scheduler**: Linear decay after warmup
403
+
404
+ ### Regularization
405
+
406
+ - **Early stopping**: Patience=3 epochs on validation loss. Best checkpoint
407
+ restored.
408
+ - **Dropout**: 0.1 in the classifier head (default for RobertaClassificationHead)
409
+ - **Frozen backbone** (optional): When `freeze_backbone=True`, only the
410
+ classifier head is trained. Recommended for small datasets.
411
+
412
+ ### Reproducibility
413
+
414
+ All randomness is controlled with `seed=42`:
415
+ - Dataset split: `seed=42`
416
+ - Sample capping: `seed=42`
417
+ - Model initialization: `seed=42`
418
+ - Training shuffle: `seed=42`
419
+
420
+ ### Training Command
421
+
422
+ ```bash
423
+ python -m src.training.cli run-all \
424
+ --manifest benchmark_manifest_cvefixes.json \
425
+ --benign-manifest benign_controls_manifest.json \
426
+ --epochs 30 \
427
+ --batch-size 8
428
+ ```
429
+
430
+ ---
431
+
432
+ ## How to Get Started with the Model
433
+
434
+ ### Installation
435
+
436
+ ```bash
437
+ pip install transformers torch
438
+ ```
439
+
440
+ ### Loading the Model
441
+
442
+ ```python
443
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
444
+ import torch
445
+
446
+ model_id = "cevud/codebert-vuln-classifier"
447
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
448
+ model = AutoModelForSequenceClassification.from_pretrained(model_id)
449
+ model.eval()
450
+ ```
451
+
452
+ ### Scoring a Function
453
+
454
+ ```python
455
+ def score_function(function_code: str, chunk_max_lines: int = 64,
456
+ chunk_overlap: int = 8) -> float:
457
+ """Score a Python function for vulnerability probability."""
458
+ lines = function_code.splitlines()
459
+ chunks = []
460
+ for i in range(0, max(len(lines) - chunk_overlap, 1), chunk_max_lines - chunk_overlap):
461
+ chunk = "\n".join(lines[i:i + chunk_max_lines])
462
+ if chunk.strip():
463
+ chunks.append(chunk)
464
+
465
+ scores = []
466
+ for chunk in chunks:
467
+ inputs = tokenizer(chunk, truncation=True, max_length=512,
468
+ padding="max_length", return_tensors="pt")
469
+ with torch.no_grad():
470
+ logits = model(**inputs).logits
471
+ probs = torch.softmax(logits, dim=-1)
472
+ scores.append(float(probs[0, 1]))
473
+
474
+ return max(scores) if scores else 0.0
475
+
476
+ # Example usage
477
+ vuln_code = """
478
+ def get_user(user_id):
479
+ query = "SELECT * FROM users WHERE id = " + str(user_id)
480
+ return db.execute(query)
481
+ """
482
+ print(f"P(vulnerable) = {score_function(vuln_code):.3f}")
483
+ ```
484
+
485
+ ### Using in the CEVuD Pipeline
486
+
487
+ ```python
488
+ from triage_orchestrator import TriageOrchestrator
489
+
490
+ orchestrator = TriageOrchestrator(
491
+ config_path="config.json",
492
+ workspace_path="."
493
+ )
494
+ orchestrator.process_pipeline()
495
+ ```
496
+
497
+ ---
498
+
499
+ ## Model Card Authors
500
+
501
+ CEVuD Authors
502
+
503
+ ## Citation
504
+
505
+ ```bibtex
506
+ @misc{cevud2026,
507
+ title={CEVuD: Cost-Effective Vulnerability Detection via Gated Static-Neural Reasoning},
508
+ author={CEVuD Authors},
509
+ year={2026},
510
+ note={Model: cevud/codebert-vuln-classifier; Dataset: cevud/cevud-training-dataset}
511
+ }
512
+ ```
513
+
514
+ ## Model Card Contact
515
+
516
+ Open an issue on the CEVuD GitHub repository.