Text Generation
PEFT
Safetensors
English
code
security
vulnerability-detection
injection
code-analysis
lora
qwen2
cybersecurity
sast
cwe
conversational
Eval Results (legacy)
Instructions to use vikramdgx/injection-vulnerability-detector with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use vikramdgx/injection-vulnerability-detector with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("unsloth/Qwen2.5-Coder-7B-Instruct") model = PeftModel.from_pretrained(base_model, "vikramdgx/injection-vulnerability-detector") - Notebooks
- Google Colab
- Kaggle
File size: 16,113 Bytes
2c8eefc 04ee056 2c8eefc 04ee056 2c8eefc d76de14 bfd166d d76de14 2c8eefc bfd166d 2c8eefc 1176256 2c8eefc 7e8329d 2c8eefc bfd166d 2c8eefc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | ---
library_name: peft
license: apache-2.0
base_model: Qwen/Qwen2.5-Coder-7B-Instruct
tags:
- security
- vulnerability-detection
- injection
- code-analysis
- lora
- qwen2
- cybersecurity
- sast
- cwe
datasets:
- hitoshura25/cvefixes
- claudios/DiverseVul
- CyberNative/Code_Vulnerability_Security_DPO
language:
- en
- code
pipeline_tag: text-generation
model-index:
- name: injection-vulnerability-detector
results:
- task:
type: text-generation
name: Injection Vulnerability Detection
dataset:
name: Injection Vulnerability Novel Test Set (leakage-controlled)
type: injection-vuln-novel
metrics:
- name: F1
type: f1
value: 0.6803519061583577
verified: false
- name: Precision
type: precision
value: 0.8169014084507042
verified: false
- name: Recall
type: recall
value: 0.5829145728643216
verified: false
---
# Injection Vulnerability Detector v1.0
A fine-tuned **Qwen2.5-Coder-7B-Instruct** model specialized in detecting injection
vulnerabilities in source code. Built with LoRA (Low-Rank Adaptation) for efficient
fine-tuning on consumer/workstation hardware.
**Key contribution:** Existing vulnerability datasets lack CWE-specific labels for
injection subtypes β most group all injections generically, and rare types like LDAP,
XPath, EL injection, and SSTI have near-zero representation. We solved this with a
**template-based synthetic data generator** (151 templates, 9 CWEs) that produces
CWE-specific injection samples at scale without requiring an LLM, combined with
filtered real-world vulnerability data from open-source datasets.
## What it does
Given a code snippet, the model identifies whether it contains an **injection vulnerability**
and, if so, classifies the specific CWE (Common Weakness Enumeration) type. It outputs
structured JSON with a verdict, CWE ID, vulnerability type, tainted data-flow analysis,
an explanation, and a fix suggestion.
### Supported vulnerability types (9 CWEs)
| CWE | Vulnerability Type |
|-----|-------------------|
| CWE-89 | SQL Injection |
| CWE-78 | OS Command Injection |
| CWE-94 | Code Injection |
| CWE-611 | XXE (XML External Entity) |
| CWE-90 | LDAP Injection |
| CWE-643 | XPath Injection |
| CWE-917 | Expression Language Injection |
| CWE-1336 | Server-Side Template Injection (SSTI) |
| CWE-113 | CRLF Injection |
## Evaluation results
**Our primary metrics are computed on novel code only** (template clones removed; the full-set figure is shown for comparison) β test samples verified
to be structurally distinct from all training data. Of 1572 total
test samples, 1007 (64.1%) were identified as structural
clones of training data and excluded (see Evaluation Methodology below).
### Evaluation: three levels of rigor
| Evaluation set | Precision | Recall | F1 |
|---|---|---|---|
| Full test set (includes template clones) | 96.2% | 83.6% | **89.5%** |
| Novel code, all injection-related CWEs (n=565) | 82.8% | 46.6% | 59.7% |
| **Novel code, in-scope 9 target CWEs (n=496)** | **81.7%** | **58.3%** | **68.0%** |
Our **primary metric is the in-scope novel row** β performance on the 9 CWEs the model targets, on code it has never seen in any structural form. The full-set figure is what most detectors report; we consider it inflated by template-clone memorisation (see Evaluation Methodology). The all-CWE novel row additionally counts out-of-scope vulnerability types the model does not target.
### Primary metrics (novel code, in-scope 9 CWEs, n=496)
| Metric | Score |
|--------|-------|
| **Precision** | 81.7% |
| **Recall** | 58.3% |
| **F1 Score** | 68.0% |
| **Accuracy** | 78.0% |
| JSON Parse Rate | 94.9% |
### Per-CWE performance (novel code)
| CWE | Vulnerability | Precision | Recall | F1 | Samples |
|-----|--------------|-----------|--------|-----|---------|
| CWE-89 | SQL Injection | 76.5% | 67.2% | 71.6% | 58 |
| CWE-78 | OS Command Injection | 75.9% | 42.3% | 54.3% | 52 |
| CWE-94 | Code Injection | 77.4% | 46.2% | 57.8% | 52 |
| CWE-611 | XXE (XML External Entity) | 100.0% | 75.0% | 85.7% | 16 |
| CWE-90 | LDAP Injection | 100.0% | 60.0% | 75.0% | 5 |
| CWE-643 | XPath Injection | 100.0% | 100.0% | 100.0% | 4 |
| CWE-917 | Expression Language Injection | 100.0% | 100.0% | 100.0% | 2 |
| CWE-1336 | Server-Side Template Injection | 100.0% | 100.0% | 100.0% | 6 |
| CWE-113 | CRLF Injection | 100.0% | 100.0% | 100.0% | 4 |
### High-confidence mode (zero false positives)
The `tainted_flow` field doubles as a confidence signal. Accepting a `VULNERABLE`
verdict **only when the model names a concrete source and sink** filters out its
weakest calls:
| Mode | Precision | Recall | F1 |
|---|---|---|---|
| Standard (all VULNERABLE verdicts) | 81.7% | 58.3% | 68.0% |
| High-confidence (concrete `tainted_flow` required) | **100.0%** | 22.1% | 36.2% |
On the in-scope novel test set this yielded **44 true positives and 0 false
positives** (n=496). Use high-confidence mode where alert fatigue matters more than
coverage (CI gating, auto-filing issues); use standard mode for triage sweeps where
a human reviews each finding.
```python
import json
r = json.loads(response)
flow = r.get("tainted_flow") or {}
high_confidence = r.get("verdict") == "VULNERABLE" and flow.get("source") and flow.get("sink")
```
### Evaluation methodology
Standard group-aware splitting (by CVE ID / project) prevents the *same* code
from appearing in both train and test, but it does not prevent **template
clones** β structurally identical code differing only in variable names,
string literals, and numeric constants β from leaking across the split. A
skeleton-hashing analysis revealed that 64.1% of the initial test set
were structural clones of training samples, scoring near-perfect F1 from
memorisation rather than generalisation.
**Skeleton hashing method:** strip comments, string literals, identifiers, and
numeric literals from each code sample, then SHA-256 hash the normalised
skeleton. Any test sample whose skeleton matches a training sample is
classified as a clone and excluded from the metrics reported above.
The scores above therefore reflect performance on genuinely novel code that
the model has never seen in any structural form during training. We report
these numbers β not the inflated full-test-set figures β because they are
what matters for real-world deployment.
## Usage
### Quick start with transformers + PEFT
```python
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
# Load base model + LoRA adapter
base_model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-Coder-7B-Instruct",
torch_dtype="auto",
device_map="auto",
)
model = PeftModel.from_pretrained(base_model, "vikramdgx/injection-vulnerability-detector")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-Coder-7B-Instruct")
# Analyze code β use the EXACT prompt format the model was trained on
code_snippet = '''import sqlite3
def get_user(username):
conn = sqlite3.connect("app.db")
query = f"SELECT * FROM users WHERE name = '{username}'"
return conn.execute(query).fetchone()
'''
SYSTEM_PROMPT = (
"You are a code security analyzer specialized in detecting injection "
"vulnerabilities. Analyze the provided code and respond with a JSON "
"object containing: verdict, cwe, vulnerability_type, tainted_flow, "
"explanation, and fix_suggestion."
)
user_message = (
"Analyze the following code for injection vulnerabilities. "
"Respond with JSON.\n\n"
+ code_snippet
)
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(text, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=768, do_sample=False)
response = tokenizer.decode(outputs[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
print(response)
```
### Expected output format
The model returns structured JSON matching its training schema:
```json
{
"verdict": "VULNERABLE",
"cwe": "CWE-89",
"vulnerability_type": "SQL Injection",
"tainted_flow": {
"source": "username parameter",
"sink": "conn.execute(query)",
"sanitizer": null
},
"explanation": "User input is directly interpolated into SQL query string via f-string without parameterization, enabling SQL injection.",
"fix_suggestion": "Use parameterized queries: conn.execute('SELECT * FROM users WHERE name = ?', (username,))"
}
```
For safe code, the model returns:
```json
{
"verdict": "SAFE",
"cwe": null,
"vulnerability_type": null,
"tainted_flow": null,
"explanation": "No injection vulnerability is present; untrusted input is not passed unsanitized to a sensitive sink.",
"fix_suggestion": null
}
```
## Training details
### Hardware
- **NVIDIA DGX Spark** (Grace Blackwell GB10)
- 128 GB unified LPDDR5X memory
- CUDA 13.0, compute capability sm_121
### Configuration
| Parameter | Value |
|-----------|-------|
| Base model | Qwen/Qwen2.5-Coder-7B-Instruct |
| Base model checkpoint used | `unsloth/Qwen2.5-Coder-7B-Instruct` (Unsloth mirror of the same Apache-2.0 weights; the adapter loads against either) |
| Method | LoRA (PEFT) |
| LoRA rank (r) | 16 |
| LoRA alpha | 32 |
| Target modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj |
| Trainable parameters | 40.3M (0.53% of total) |
| Epochs | 3 |
| Batch size | 2 (gradient accumulation: 4, effective 8) |
| Learning rate | 2e-4 |
| Max sequence length | 4096 |
| Optimizer | AdamW (8-bit) |
| LR scheduler | Cosine |
| Packing | Enabled |
| Loss | Completion-only |
### Why we built a custom dataset
Existing open-source vulnerability datasets (CVEfixes, DiverseVul, BigVul, etc.)
provide valuable real-world code samples, but they share a common gap: **they lack
fine-grained, CWE-specific labels for injection subtypes.** Most label code broadly
as "vulnerable" or group all injections under generic categories like CWE-74 or
CWE-20 β without distinguishing SQL injection (CWE-89) from command injection
(CWE-78) from SSTI (CWE-1336). For niche injection types like LDAP injection
(CWE-90), XPath injection (CWE-643), or EL injection (CWE-917), labeled samples
in public datasets are extremely scarce (often single digits).
This makes it impossible to train a detector that both identifies vulnerabilities
AND classifies the specific CWE type β which is what security engineers actually
need for triage.
### Our approach: template-based synthetic generation
To solve this, we built a **procedural code generator** that produces CWE-specific
injection samples at scale β no LLM in the loop, pure template expansion:
- **151 handcrafted code templates** covering all 9 target CWEs, each with
`@@PLACEHOLDER@@` tokens for variable names, function names, table names,
database fields, and code patterns
- **Randomized variable pools** (200+ variable names, 100+ function names, 50+
table names per CWE) ensure each generated sample is syntactically unique
- **Paired generation**: every vulnerable template has a corresponding safe version
that uses parameterized queries, input validation, or proper escaping β teaching
the model the difference, not just the pattern
- **~5,000 synthetic samples** generated in seconds, balanced across all 9 CWEs
including the rare ones that have near-zero representation in public datasets
This approach is deterministic, reproducible, and produces exactly the CWE
distribution the model needs β no data collection bottleneck, no labeling errors,
no class imbalance.
### Dataset composition
The final training set combines three sources:
1. **Real-world vulnerabilities** β filtered from open-source CVE/vulnerability
datasets, keeping only injection-related CWEs. Provides realistic code patterns
from production software.
2. **Template-based synthetic data** (~5,000 samples) β our original procedural
generator. Fills the CWE-specific gap that public datasets leave open,
especially for rare injection types (LDAP, XPath, EL, SSTI, Header Injection).
3. **Hard negatives** β safe code samples including post-patch fixes and
non-vulnerable functions from vulnerability-adjacent codebases. Teaches the
model what secure code looks like.
Group-aware splitting ensures no data leakage between train and test sets (samples
sharing a CVE ID or project stay together). Additionally, a skeleton-hashing pass
excludes structural template clones from the evaluation set (see Evaluation
Methodology above).
## Dataset sources and attribution
This model was trained on data from the following open-source datasets, combined
with our original synthetic generation. We gratefully acknowledge the dataset creators:
| Dataset | Source | License | Role |
|---------|--------|---------|------|
| [CVEfixes](https://huggingface.co/datasets/hitoshura25/cvefixes) | Bhandari et al. | Apache 2.0 (data: CC BY 4.0) | Real-world vuln + patch pairs |
| [DiverseVul](https://huggingface.co/datasets/claudios/DiverseVul) | Chen & Bhatt (RAID 2023) | Not specified on HF card | Safe code (non-vuln functions) |
| [Code Vulnerability Security DPO](https://huggingface.co/datasets/CyberNative/Code_Vulnerability_Security_DPO) | CyberNative AI | Apache 2.0 | Injection code examples |
| **Template-based synthetic generator** | **Original work** | **Apache 2.0** | **CWE-specific injection samples (core contribution)** |
**License notes:**
- The DiverseVul dataset does not declare an explicit license on its HuggingFace
card as of this writing. This model's own adapter
weights are original work released under Apache 2.0, but users should check the
current licensing status of these upstream datasets before commercial deployment.
## Limitations
- **Injection-only scope:** This model detects 9 injection-related CWEs. It does not
cover other vulnerability classes (buffer overflow, authentication, crypto, etc.).
- **Synthetic training bias:** The model is trained partly on template-generated code.
While this solves the CWE-distribution problem, performance on novel real-world
patterns is lower than on template-similar code, reflecting the generalisation gap
that template-based training introduces. See Evaluation Results for exact numbers.
- **Rare CWEs are synthetic-validated only:** The five rare injection types (LDAP,
XPath, EL, SSTI, Header) have near-zero representation in public vulnerability
datasets. Our evaluation on novel code therefore cannot validate these CWEs β
their coverage relies entirely on synthetic templates. Real-world performance on
these types is unknown.
- **CWE classification accuracy:** While detection (vulnerable vs. safe) is reliable,
the specific CWE label assigned to a detected vulnerability may be incorrect in some
cases β particularly between similar injection types (e.g. CWE-94 code injection vs CWE-1336 template injection, or CWE-78 vs CWE-94).
- **Code context:** The model analyzes individual functions/snippets. It cannot trace
data flow across files or understand application-level sanitization.
- **Language coverage:** Primarily trained on Python, Java, PHP, C/C++, and JavaScript.
Performance on other languages may vary.
- **Not a replacement for manual review:** Use as a triage/prioritization tool alongside
established SAST tooling and expert code review.
## License
This model adapter is released under the **Apache 2.0** license. The base model
(Qwen2.5-Coder-7B-Instruct) is also Apache 2.0.
## Citation
If you use this model in your research, please cite:
```bibtex
@misc{injection-detector-v10,
title={Injection Vulnerability Detector v1.0},
author={Thrivikram Gujarathi},
year={2026},
publisher={HuggingFace},
url={https://huggingface.co/vikramdgx/injection-vulnerability-detector}
}
```
|