CoolFace
Modelpublic

Denash/codebert-vuln-classifier

sourceHugging Facemitupdated 2mo agoView on Hugging Face
0likes14downloads
Model Card

Model Card — CEVuD Vulnerability Classifier

HuggingFace-ready model card. This documents the custom Stage-2 classifier trained by src/training/ and is the artifact to publish at huggingface.co/Denash/codebert-vuln-classifier.

Model Details

Model Description

  • Model ID: Denash/codebert-vuln-classifier
  • Model type: Fine-tuned transformer for binary sequence classification
  • Base model: `microsoft/codebert-base` (RoBERTa-based, ~125 M parameters)
  • Language: Python (code)
  • License: MIT (inherits from CEVuD; CodeBERT itself is MIT)
  • Task: Binary classification — vulnerable vs. safe Python function chunks

This model is the Stage-2 local classifier ("small model") in the CEVuD pipeline. It scores uniform code windows (chunks) of Python functions and outputs a probability P(vulnerable) ∈ [0, 1]. The Stage-2 gate combines this neural probability with Semgrep's static severity via a linear risk equation R = W₁·S_sev + W₂·P_slm to decide whether to escalate a finding to the Stage-3 LLM.

The model is trained on the CEVuD Training Dataset (CVEfixes-based) and is designed to be a component of a gated pipeline, not a standalone vulnerability oracle. Its primary role is to suppress trivially-safe code so that the expensive LLM is only called when truly needed.

Model Architecture

The model uses the standard HuggingFace RobertaForSequenceClassification head on top of the CodeBERT encoder:

Input: Python code chunk (≤ 512 tokens)
  ↓
CodeBERT Encoder (12 layers, 768 hidden dim, 12 attention heads)
  ↓
[CLS] token hidden state (768-dim)
  ↓
Pooler: dense(768 → 768) + tanh
  ↓
Classifier: dense(768 → 768, tanh) + dropout → out_proj(768 → 2)
  ↓
Softmax → P(vulnerable), P(safe)

Key components:

  • Encoder: microsoft/codebert-base — a RoBERTa-based transformer pre-trained on natural language and programming language pairs. Frozen by default; can be unfrozen for fine-tuning.
  • Pooler: Maps the [CLS] token to a 768-dim representation via a dense layer + tanh activation.
  • Classifier head: Two-layer MLP (768 → 768 → 2) with dropout and tanh activation. Outputs logits for the two classes.
  • Output: Softmax probabilities. P(vulnerable) = softmax(logits)[:, 1].

When freeze_backbone=True is used, only the classifier.* submodule is trained; the encoder and pooler stay frozen. This is the recommended setting for small datasets (~1.4k samples) because it is more sample-efficient and stable.


Intended Use

Primary Intended Use

The model is designed to be the Stage-2 local edge classifier in the CEVuD pipeline. Its intended use case is:

  1. 1.CI/CD integration: Scan code changes in pull requests or pushes.
  2. 2.Local gating: Score each Semgrep finding locally (zero marginal cost).
  3. 3.Escalation decision: Combine the neural score with static severity to decide whether to escalate to the Stage-3 LLM.

How to Use

python
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

model_id = "Denash/codebert-vuln-classifier"

tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSequenceClassification.from_pretrained(model_id)
model.eval()

def score_chunk(code_chunk: str) -> float:
    """Return P(vulnerable) for a single code chunk (≤ 512 tokens)."""
    inputs = tokenizer(
        code_chunk,
        truncation=True,
        max_length=512,
        padding="max_length",
        return_tensors="pt",
    )
    with torch.no_grad():
        logits = model(**inputs).logits
    probs = torch.softmax(logits, dim=-1)
    return float(probs[0, 1])  # P(vulnerable)

# Example: score a Python function chunk
code = """
def get_user(user_id):
    query = "SELECT * FROM users WHERE id = " + str(user_id)
    return db.execute(query)
"""
p_vuln = score_chunk(code)
print(f"P(vulnerable) = {p_vuln:.3f}")

Important: This model scores chunks (uniform code windows), not whole functions. For a complete function, chunk it into 64-line windows with 8-line overlap, score each chunk, and aggregate using max (default) or mean.

Out-of-Scope Uses

  • Standalone vulnerability oracle: The model is not designed to be used alone. Its standalone recall is 28.9% (on CVEfixes test) and 70.5% (on VUDENC). It is meant to be part of a gated pipeline.
  • Other languages: The model is trained on Python only. Performance on other languages is unverified.
  • Adversarial settings: The model has not been evaluated against adversarially crafted code.
  • Definitive security verdict: The model's output is one input to a composite gate. It should not be used as the sole determinant of whether code is vulnerable.

Training Data

Dataset Overview

The model is fine-tuned on the CEVuD Training Dataset (CVEfixes-based), a curated corpus of 2,181 Python function chunks derived from real-world vulnerability fixes.

PropertyValue
Sourcehitoshura25/cvefixes (HuggingFace)
Total samples2,181
Projects (repos)554
Vulnerable474 (21.7%)
Safe1,707 (78.3%) — 1,643 benignsibling + 64 benigncontrol
Unique CWEs93
Unique CVEs470
Chunk size64 lines with 8-line overlap
Hunk-centeringEnabled (vulnerable chunks contain the sink)
Near-duplicate threshold0.75 token-similarity

Data Creation

The training data is created through a multi-stage pipeline:

  1. 1.CVEfixes conversion: src/scripts/convert_cvefixes.py streams the CVEfixes dataset, filters to Python, applies noise and trivial-change filters, and emits only vulnerable samples (label=1). The post-fix function is retained in fixed_code but not emitted as label=0.
  1. 1.Benign control mining: src/scripts/mine_benign_functions.py extracts safe functions from files the fix commit did not touch. These are tagged sample_subtype="benign_control" and serve as the genuine safe class.
  1. 1.Enrichment: src/training/dataset_builder.py enriches each sample with the full enclosing function (AST-expanded) and module-level imports.
  1. 1.Chunking: Functions are cut into 64-line windows with 8-line overlap. For vulnerable samples, only chunks overlapping the diff hunk are kept (hunk-centering).
  1. 1.Quality filters: Hard contradictions and near-duplicate safe chunks (>0.75 token-similar to vulnerable chunks) are removed.
  1. 1.Splitting: Project-level 60/20/20 split with seed=42. No project appears in more than one split.

Safe Class Construction

The safe class is constructed from two sources:

  • Benign siblings (1,643 samples): Functions from the same file as the vulnerable function, but in commits the fix did not touch.
  • Benign controls (64 samples): Functions from files the fix commit never touched, mined from verified-benign repositories.

Both sources are passed through a token-similarity guard (>0.75 to any vulnerable function ⇒ dropped) to prevent near-duplicates from entering the safe class.

The post-fix function is explicitly not used as `label=0` because it is a near-duplicate of its vulnerable twin (median token-similarity ≈ 0.94). Using it would create contradictory pairs and collapse training to P = 0.5.

Data Splits

SplitSamplesVulnerableSafeProjects
Train1,4643161,148330
Validation35876282
Test35982277

Preprocessing

  • Tokenizer: AutoTokenizer from microsoft/codebert-base with max_length=512, padding="max_length", truncation=True.
  • Chunking: Uniform 64-line windows with 8-line overlap. Matches inference format.
  • Labels: 0 = safe, 1 = vulnerable. Mapped to id2label = {0: "safe", 1: "vulnerable"} and label2id = {"safe": 0, "vulnerable": 1}.
  • Problem type: single_label_classification (softmax).

Evaluation Data

Datasets Used

The model is evaluated on two datasets:

  1. 1.CVEfixes test split (same corpus as training): 359 samples, project-level split. This measures the model's standalone performance on held-out projects.
  2. 2.VUDENC test split (held-out corpus): 821 samples, project-level split. This measures the model's performance on a completely different dataset.

Metrics

MetricCVEfixes TestVUDENC Test
Accuracy81.9%
Precision100.0%
Recall20.7%70.5%
F134.3%
ROC-AUC0.0*
PR-AUC0.496

\* The standalone evaluator initially reported ROC-AUC=0.0 due to loading the wrong checkpoint. This was fixed; the correct ROC-AUC on the CVEfixes validation split is 74.9%.

The gate study (full CEVuD pipeline) is evaluated on VUDENC using F2 (beta=2.0) as the primary metric, with Token Reduction Rate (TRR) and Cost Reduction as efficiency metrics.


Quantitative Analysis

Training Dynamics

EpochTrain LossVal LossVal AccuracyVal PrecisionVal RecallVal F1Val ROC-AUC
10.41984.9%100.0%28.9%44.9%74.9%
20.41984.9%100.0%28.9%44.9%74.9%
30.41984.9%100.0%28.9%44.9%74.9%
40.7100.41984.9%100.0%28.9%44.9%74.9%

Training early-stopped at epoch 4 (patience=3 on validation loss). The best checkpoint is from epoch 1 (step 366), which has the same validation metrics as epoch 4.

Confusion Matrix (Validation)

Predicted SafePredicted Vulnerable
Actually Safe282 (TN)0 (FP)
Actually Vulnerable54 (FN)22 (TP)

Confusion Matrix (Test)

Predicted SafePredicted Vulnerable
Actually Safe277 (TN)0 (FP)
Actually Vulnerable65 (FN)17 (TP)

Key Observations

  • Precision = 100%: The model never produces a false positive. When it predicts "vulnerable", it is always correct.
  • Recall = 28.9% (val) / 20.7% (test): The model misses most vulnerabilities. This is expected for a small model trained on a difficult, imbalanced corpus.
  • ROC-AUC = 74.9%: The model learns strong discriminative ranking. The low recall reflects the classification threshold (0.5), not poor ranking ability.
  • Class imbalance effect: The ~1:3.6 vulnerable/safe split causes the model to be conservative. Class-weighted cross-entropy (weights ≈ [0.64, 2.30]) gives the vulnerable class a ~3.6× higher per-sample gradient signal, but the small dataset size limits how much the model can learn.

Performance in the Gated Pipeline

When embedded in the CEVuD pipeline with the tuned linear gate ($W1=0.15, W2=0.85, T=0.2$):

MetricValue
Recall95.2%
Precision12.8%
F20.417
Escalation Rate94.9%
TRR5.1%
Cost Reduction5.0%

The linear gate improves recall from 70.5% (small model standalone) to 95.2% by combining the neural signal with Semgrep's static signal. The trade-off is lower precision (12.8%) and high escalation rate (94.9%), which is acceptable because the escalated snippets are reviewed by a more capable LLM.


Environmental Impact

  • Hardware: CPU-only training (no GPU required).
  • Training time: ~2.4 hours on a 4-core CPU (8,759 seconds).
  • Estimated CO2 emissions: Using the ML CO2 Impact calculator, CPU training for ~2.4 hours on an Intel i7-9700K emits approximately 0.2-0.4 kg CO2 (depending on electricity grid carbon intensity).
  • Inference cost: The model runs locally on CPU/edge hardware. A single inference on a 512-token chunk takes ~50-100ms on a modern CPU, with near-zero marginal cost compared to cloud LLM APIs.

Ethical Considerations

Intended Users

CEVuD is designed for software developers, security engineers, and organizations that want to shift-left security scanning in their CI/CD pipelines. The model augments human experts by filtering safe code, not replacing them.

Potential Misuse

  • False sense of security: The model's 100% precision might lead users to believe it never misses vulnerabilities. In reality, its standalone recall is only 28.9%, and even in the gated pipeline, 4.8% of vulnerabilities slip through (FN=5 out of 105 on VUDENC test). Users must understand that CEVuD is a filter, not a definitive scanner.
  • Over-reliance on automation: The low precision (12.8%) means many benign snippets are escalated. If users skip reviewing escalated snippets, they waste LLM resources without gaining security.
  • Bias in training data: CVEfixes is biased toward well-known, high-profile projects. Vulnerabilities in niche or internal codebases may not be represented. The model may perform worse on code that differs stylistically from the CVEfixes corpus.

Fairness and Transparency

  • The model's decisions are interpretable: the linear gate formula R = W₁·S_sev + W₂·P_slm is transparent, and the weights are selected by exhaustive grid search.
  • The training data is publicly available, and the full training pipeline is open-source.
  • The model does not process personal data. Code snippets are the only input.

Limitations and Recommendations

LimitationRecommendation
Low standalone recall (28.9%)Always use as part of the gated pipeline, not standalone.
Python-onlyDo not apply to other languages without retraining.
Chunk-level granularityScore whole functions by chunking and aggregating.
CWE imbalanceConsider augmenting rare CWE types if your use case targets specific vulnerabilities.
No adversarial evaluationDo not deploy in adversarial settings without additional testing.

Training Procedure

Implementation

Training is implemented in src/training/trainer.py using the HuggingFace Trainer API with a custom WeightedTrainer subclass.

Loss Function

Class-weighted cross-entropy: The ~1:3.6 vulnerable/safe imbalance is countered by inverse-frequency class weights:

weight(class) = total_samples / (num_classes × count(class))

For the current split, this yields approximately [0.64, 2.30] for [safe, vulnerable], meaning each vulnerable sample contributes ~3.6× the gradient signal of a safe sample.

Why not focal loss? Focal loss was evaluated but removed in favor of class weights. Class-weighted cross-entropy is simpler, more interpretable, and equally effective for this dataset size. The weights are computed automatically from the training distribution.

Optimization

  • Optimizer: AdamW
  • Learning rate: 2e-5
  • Weight decay: 0.01
  • Batch size: 8
  • Warmup: Linear warmup for 10% of total steps
  • Scheduler: Linear decay after warmup

Regularization

  • Early stopping: Patience=3 epochs on validation loss. Best checkpoint restored.
  • Dropout: 0.1 in the classifier head (default for RobertaClassificationHead)
  • Frozen backbone (optional): When freeze_backbone=True, only the classifier head is trained. Recommended for small datasets.

Reproducibility

All randomness is controlled with seed=42:

  • Dataset split: seed=42
  • Sample capping: seed=42
  • Model initialization: seed=42
  • Training shuffle: seed=42

Training Command

bash
python -m src.training.cli run-all \
  --manifest benchmark_manifest_cvefixes.json \
  --benign-manifest benign_controls_manifest.json \
  --epochs 30 \
  --batch-size 8

How to Get Started with the Model

Installation

bash
pip install transformers torch

Loading the Model

python
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

model_id = "Denash/codebert-vuln-classifier"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSequenceClassification.from_pretrained(model_id)
model.eval()

Scoring a Function

python
def score_function(function_code: str, chunk_max_lines: int = 64,
                   chunk_overlap: int = 8) -> float:
    """Score a Python function for vulnerability probability."""
    lines = function_code.splitlines()
    chunks = []
    for i in range(0, max(len(lines) - chunk_overlap, 1), chunk_max_lines - chunk_overlap):
        chunk = "\n".join(lines[i:i + chunk_max_lines])
        if chunk.strip():
            chunks.append(chunk)
    
    scores = []
    for chunk in chunks:
        inputs = tokenizer(chunk, truncation=True, max_length=512,
                          padding="max_length", return_tensors="pt")
        with torch.no_grad():
            logits = model(**inputs).logits
        probs = torch.softmax(logits, dim=-1)
        scores.append(float(probs[0, 1]))
    
    return max(scores) if scores else 0.0

# Example usage
vuln_code = """
def get_user(user_id):
    query = "SELECT * FROM users WHERE id = " + str(user_id)
    return db.execute(query)
"""
print(f"P(vulnerable) = {score_function(vuln_code):.3f}")

Using in the CEVuD Pipeline

python
from triage_orchestrator import TriageOrchestrator

orchestrator = TriageOrchestrator(
    config_path="config.json",
    workspace_path="."
)
orchestrator.process_pipeline()

Model Card Authors

CEVuD Authors

Citation

bibtex
@misc{cevud2026,
  title={CEVuD: Cost-Effective Vulnerability Detection via Gated Static-Neural Reasoning},
  author={CEVuD Authors},
  year={2026},
  note={Model: Denash/codebert-vuln-classifier; Training Dataset: Denash/cevud-training-dataset; Pipeline Dataset: Denash/cevud-pipeline-dataset}
}

Model Card Contact

Open an issue on the CEVuD GitHub repository.

Related Resources

ResourceLink
Training Dataset (CVEfixes)`Denash/cevud-training-dataset`
Pipeline Dataset (VUDENC)`Denash/cevud-pipeline-dataset`
Source Dataset (CVEfixes)`hitoshura25/cvefixes`
Source Dataset (VUDENC)`DetectVul/Vudenc`
CEVuD GitHubhttps://github.com/Denash/CEVuD