
نموذج لغوي كبير (LLM) متخصص في الاستدلال لكشف الثغرات في الكود المصدري بلغتي C/C++ وPython، مع بناء مجموعات البيانات، وتدريب SFT/DPO، ونصوص برمجية لإعادة إنتاج النتائج.
git lfs install # one-time setup
git clone https://github.com/ucsb-mlsec/VulnLLM-R.git
cd VulnLLM-R
# If you cloned before installing Git LFS, run: git lfs pull
conda create -n vulnscan python=3.11
conda activate vulnscan
pip install -e . -e ./vulscan/train/LLaMA-Factory -e ./vulscan/model_zoo
# generate VulnLLM-R-7B's results
python -m vulscan.test.test --output_dir results/test_data --dataset_path ./datasets/test/function_level/ ./datasets/test/repo_level/ --language python c java --model UCSB-SURFI/VulnLLM-R-7B --requests_per_minute 1000 --save --use_cot --batch_size 4 --tp 2 --vllm --max_tokens 8192 --random_cwe
python -m vulscan.test.test_hf \
--output_dir results/test_hf \
--hf_dataset UCSB-SURFI/VulnLLM-R-Test-Data \
--hf_split repo_level function_level \
--language c python java \
--model UCSB-SURFI/VulnLLM-R-7B \
--save --use_cot --vllm --tp 2
# [optional] generate other models' results with our shell script
# remember to add your API keys to .env file if you want to run commercial models
# use ./run_test.sh -h for more options
./vulscan/test/run_test.sh -o results/test_data -t 2 # -o means output directory, -t means tensor parallelism
./vulscan/test/run_test.sh -o results/test_data -M o3-mini # -M means model name, which runs only one model.
./vulscan/test/run_test.sh -o results/test_data -M gpt-5.4 -e high # -e sets reasoning effort (e.g., none/low/medium/high/xhigh)
./vulscan/test/run_test.sh -o results/test_data -M claude-opus-4-6 -e high
# [optional] draw plot to compare with other models
python plots/plot_language_comparison_models.py --results-dir results/test_data
python plots/plot_model_size_scatter.py --results-dir results/test_data # Note: Labels may overlap with scatter points. Adjust text positions manually if needed.
نوفر أيضًا نسخة مختصرة الاستدلال من مجموعات البيانات المقطّرة:
دمج مجموعات البيانات الحالية لاكتشاف الثغرات على مستوى الدوال: PrimeVul [1], SecCodePLT [2], Juliet [3], Sven [4], وArvo [5]. ضمن هذه المجموعات، تحتوي PrimeVul على أكثر الدوال تعقيدًا. ننشئ مجموعتي تدريب: نظيفة (بدون PrimeVul) وصاخبة (مع PrimeVul)، حتى نتمكن من التدريب على مجموعات بسيطة نسبيًا والاختبار على مجموعة PrimeVul المعقدة. لاحظ أن تسميتنا لمجموعة التدريب التي تتضمن PrimeVul باسم "صاخبة" لا تعني أن المجموعة صاخبة (noisy). إنه اسم تعسفي نسبيًا استخدمناه في البداية.
vulscan/data_process/data_utils على مجموعة من البرامج النصية لمعالجة البيانات ودمجها.
raw_to_us.py: دمج البيانات الخام في مجموعتنا وإزالة البيانات المكررةcheck_cwe_correct.py: حساب الدقة لكل فئة CWEgenerate_arvo_raw_data.py: توليد بيانات خام منظمة من مجموعة بيانات arvoarvo_to_us.py: إعادة تنسيق البيانات الخام المنظمة من arvo إلى تنسيق مجموعتناsplit_good_bad_for_juliet.py: استخراج البيانات من مجموعة Juliet 1.3 الخام وتحويلها إلى التنسيق المطلوب، والتي تشكل جزءًا من مجموعة بياناتنا النظيفة c clean_datasetadd_sven_to_clean_dataset.py: استخراج البيانات من مجموعة بيانات Sven، لتشكيل جزء من مجموعة البيانات النظيفة C الخاصة بناsync_large_small.py: مزامنة التعديلات على noisy_dataset/large_train/c إلى noisy_dataset/small_train/cremove_testing_from_training.py: إضافة وسم human إلى كل بيانات، بمعنى أن النقطة تم التحقق منها بواسطة إنسان وتُستخدم كبيانات اختبار
-: إضافة حقل related_cwe إلى مجموعة البيانات.بعد إنشاء مجموعات البيانات، سنقوم بتوليد بيانات الاستدلال لمجموعة التدريب الخاصة بنا.
سوف نستعلم من نموذجي الاستدلال DeepSeek-r1 وQwQ لتوليد بيانات الاستدلال وتصفية تلك التي تحتوي على سلاسل استدلال طويلة جدًا.
الكود الخاص بتوليد بيانات الاستدلال موجود في vulscan/data_process/generate_reasoning وسيتم حفظ بيانات الاستدلال
في datasets/reasoning_data.
cd vulscan/data_process/generate_reasoning
generate_reasoning/generate.py هو البرنامج النصي الرئيسي لتوليد بيانات الاستدلال.
لكل نقطة بيانات، سيولّد n عينات من بيانات الاستدلال ويختار تلك التي تحتوي على الإجابة الصحيحة وأقصر طول.
أمثلة على تشغيله مع نموذجي QwQ وDeepSeek-r1 (باستخدام واجهة together.AI API، وهي أبطأ ولكنها أكثر استقرارًا من الواجهة الرسمية) هي كما يلي:
python generate.py \
--tp 2 \
--dataset_type clean_dataset \
--batch_size 200 \
--n 8 \
--training_set train \
--model_name Qwen/QwQ-32B
# or
python generate.py \
--dataset_type noisy_dataset \
--batch_size 200 \
--n 8 \
--training_set small_train \
--model_name together-deepseek-reasoner \
--together_deepseek
بعد توليد بيانات الاستدلال الخام، يمكننا استخدام نموذج آخر لتلخيصها وجعلها أقصر دون كسر البنية
python extract_reasoning.py
يمكننا أيضًا تصفية بيانات الاستدلال بناءً على طول معين باستخدام generate_reasoning/filter.py؛ يتم تغيير num_processes وفقًا لعدد أنوية وحدة المعالجة المركزية لديك.
python filter.py \
--dataset_type noisy_dataset \
--training_set small_train \
--model_name Qwen/QwQ-32B \
--filter_input_length 16000 \
--filter_all_length 32000 \
--num_processes 16 \
--filter_correct_only # for filtering wrong predictions
# --model_name together-deepseek-reasoner \
أخيرًا، سنحتاج إلى إعادة تنسيق بيانات الاستدلال المولدة للنموذج المستهدف الذي سنقوم بتدريبه (Qwen-Instruct).
python reformat_ds.py \
--dataset_type noisy_dataset \
--training_set small_train \
--model_name Qwen/QwQ-32B \
--filter_input_length 16000 \
--filter_all_length 32000 \
--push_to_hub \
--push_to_hub_organization secmlr \
--filter_correct_only
لمجموعة بيانات DPO:
python generate_dpo.py \
--tp 2 --dataset_type clean_dataset \
--batch_size 200 --n 8 --training_set train \
--model secmlr/VD-QWQ-Clean-8k_qwen2_7B_full_sft_1e-5
راجع vulscan/train/README.md لمزيد من التفاصيل
سيتم حفظ النتائج في دليل results/test_qwen/results.json.
إذا كنت تريد إعادة إنتاج نتائجنا، يمكنك تشغيل الأمر التالي:
# open-source model
python -m vulscan.test.test --output_dir results/one_of_4 \
--dataset_path ./datasets/test/test_clean ./datasets/test/test_primevul_pair \
--language c python --model Qwen/Qwen2.5-7B-Instruct \
--requests_per_minute 100 --save --use_cot \
--use_policy --batch_size 4 --tp 2 --vllm --max_tokens 16384 \
--random_cwe
# api model
python -m vulscan.test.test --output_dir results/one_of_4 \
--dataset_path ./datasets/test/test_clean ./datasets/test/test_primevul_pair \
--language c python --model o3-mini-2025-01-14 \
--requests_per_minute 100 --save --use_cot \
--use_policy --batch_size 4 --max_tokens 16384 --random_cwe
# local saved model
python -m vulscan.test.test --output_dir results/one_of_4 \
--dataset_path ./datasets/test/test_clean ./datasets/test/test_primevul_pair \
--language c python \
--model vulscan/train/result/VD-QWQ-Clean-16k/qwen2_7B_full_sft_1e-5 \
--requests_per_minute 100 --save --use_cot --use_policy \
--batch_size 4 --tp 2 --vllm --max_tokens 16384 --random_cwe
# our model
python -m vulscan.test.test --output_dir results/one_of_4 \
--dataset_path ./datasets/test/test_clean ./datasets/test/test_primevul_pair \
--language c python \
--model secmlr/VD-QWQ-Noisy-Small-8k_qwen2_7B_full_sft_1e-5 --revision aa3235b \
--requests_per_minute 100 --save --use_cot --use_policy \
--batch_size 4 --tp 2 --vllm --max_tokens 16384 \
--random_cwe # whether to randomize the order of cwe and related cwes
بعد الاختبار، سيتم حفظ استجابات النموذج والأداء في دليل results/test_data.
إذا كنت تريد حساب الأداء بناءً على استجابات النموذج، يمكنك تشغيل الأمر التالي:
python -m vulscan.test.test_existing_json \
--json_file results/test_data/datasets_test_test_clean__cot_c_policy_QwQ-32B-Preview.json # the results file
python generate_constitution.py --model gpt-4o --input_dir results/train --output_dir results/train/constitution
@article{nie2025vulnllmrspecializedreasoningllm,
title={VulnLLM-R: Specialized Reasoning LLM with Agent Scaffold for Vulnerability Detection},
author={Yuzhou Nie and Hongwei Li and Chengquan Guo and Ruizhe Jiang and Zhun Wang and Bo Li and Dawn Song and Wenbo Guo},
year={2025},
journal={arXiv preprint arXiv:2512.07533},
url={https://arxiv.org/abs/2512.07533},
}
data_utils.pydatasets/clean_dataset: بيانات التدريب بدون PrimeVul
datasets/clean_dataset/python يحتوي على بيانات من SVEN وSecCodePLTdatasets/clean_dataset/c يحتوي على بيانات من Juliet وSVENdatasets/noisy_dataset
datasets/noisy_dataset/small_train: يحتوي على بيانات التدريب من PrimeVul وSVEN مع CWEs محددة (نستخدم بيانات PrimeVul في هذه المجموعة كتدريب)datasets/noisy_dataset/large_train: يحتوي على بيانات التدريب من PrimeVul وSVEN وSecCodePLT مع المزيد من CWEs (يمكن استخدام هذه المجموعة لاحقًا لتدريب نماذج أكبر)datasets/noisy_dataset/test: مجموعة اختبار صغيرة من PrimeVul تم التحقق منها بواسطة إنسانdatasets/test
datasets/test/test_clean: بيانات الاختبار من SVEN وSecCodePLT وJuliet؛ مع CWEs خارج التوزيع (OOD) غير المدرجة في مجموعة التدريبdatasets/test/test_primevul_pair: بيانات اختبار PrimeVul الأصليةvulscan/data_process/data_utils/get_cwe_stat.py للحصول على الرسم البياني للمجموعة| Dataset | Language | Train/test | CWE | # Benign | # Vuln. | average length |
|---|
| Clean (seccodeplt) | Python | Train | 20 | 1281 | 1281 | 741 |
| Clean (juliet) | C/C++ | Train | 22 | 1716 | 1653 | 3689 |
| Hard (primevul filtered) | C/C++ | Train | 26 | 2717 | 2952 | 4689 |
| Long Context (Oss-fuzz) | C/C++ | Train | 3 | 475 | 604 | 12761 |
| Simple (seccodeplt) | Python | Test | 24 (6 ood) | 74 | 74 | 814 |
| Simple (juliet) | C/C++ | Test | 38 (14 ood) | 358 | 376 | 2575 |
| Hard (PrimeVul, SecLLMHolmes) | C/C++ | Test | 13 (5 ood) | 145 | 152 | 4545 |
| Long Context (Oss-fuzz) | C/C++ | Test | 3 (0 ood) | 0 | 320 | 18929 |
| primevul test (noisy) | C/C++ | Test | 56 (34 ood) | 421 | 422 | 5341 |