Skip to content

About

LLM specialized in pecking out security and vulnerability bugs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

10 Commits

Folders and files

Repository files navigation

CodePecker Logo

CodePecker is an LLM specialized in pecking out security and vulnerability bugs

CodePecker is an LLM fine-tuned on hundreds of thousands of real vulnerability samples to detect security bugs. By understanding code semantics and context rather than just pattern matching, it identifies complex vulnerabilities like logic flaws, race conditions, and injection attacks. CodePecker not only finds these hidden threats but explains why they're dangerous and suggests how to fix them – pecking out the bugs that matter before they bite.

Features

  • Detect vulnerabilities in C code with detailed explanations
  • Identify CWE types (buffer overflows, use-after-free, etc.)
  • Suggest fixes based on real security patches from the wild
  • Explain the why - not just binary classification

Installation

# Sync dependencies with uv
uv sync

Quick Start

Training Pipeline

CodePecker uses a three-stage training pipeline:

  1. SFT (Supervised Fine-Tuning): Teaches the model to answer vulnerability questions
  2. DPO (Direct Preference Optimization): Teaches the model to prefer secure code over vulnerable code
  3. GRPO (Group Relative Policy Optimization): Optimizes fix quality using online RL with reward signals

Stage 1: SFT Training

# Train on full BigVul dataset
uv run python -m codepecker.sft.train

# Quick test with limited samples
uv run python -m codepecker.sft.train --max-train-samples 1000 --max-eval-samples 100

# Resume from checkpoint
uv run python -m codepecker.sft.train --resume-from-checkpoint ./codepecker_sft_model/checkpoint-500

Stage 2: DPO Training

After SFT training completes, run DPO training to teach preference for secure code:

# Train DPO on SFT model
uv run python -m codepecker.dpo.train \
    --base-model ./codepecker_sft_model \
    --output-dir ./codepecker_dpo_model

# Quick test with limited samples
uv run python -m codepecker.dpo.train \
    --base-model ./codepecker_sft_model \
    --max-train-samples 1000

# Resume from checkpoint
uv run python -m codepecker.dpo.train \
    --base-model ./codepecker_sft_model \
    --resume-from-checkpoint ./codepecker_dpo_model/checkpoint-100

Stage 3: GRPO Training

After DPO training, run GRPO to optimize fix quality using online RL:

# Train GRPO on DPO model
uv run python -m codepecker.grpo.train \
    --base-model ./codepecker_dpo_model \
    --output-dir ./codepecker_grpo_model \
    --reward-type similarity

# With more generations for better learning
uv run python -m codepecker.grpo.train \
    --base-model ./codepecker_dpo_model \
    --num-generations 8

# Quick test with limited samples
uv run python -m codepecker.grpo.train \
    --base-model ./codepecker_dpo_model \
    --max-train-samples 1000

# Resume from checkpoint
uv run python -m codepecker.grpo.train \
    --base-model ./codepecker_dpo_model \
    --resume-from-checkpoint ./codepecker_grpo_model/checkpoint-50

Inference

# Analyze a code snippet
uv run python -m codepecker.inference \
    --model-path ./codepecker_model \
    --code "void foo() { char* p = malloc(100); free(p); free(p); }"

# Analyze code from file
uv run python -m codepecker.inference \
    --model-path ./codepecker_model \
    --code-file ./vulnerable.c

# Evaluate on test set
uv run python -m codepecker.inference \
    --model-path ./codepecker_model \
    --evaluate \
    --max-samples 100 \
    --output results.json

Python API

SFT Training

from codepecker.sft import train

# Stage 1: Supervised Fine-Tuning
trainer = train(
    output_dir="./codepecker_sft_model",
    max_train_samples=5000,  # Optional: limit for testing
    max_eval_samples=500
)

DPO Training

from codepecker.dpo import train_dpo

# Stage 2: Direct Preference Optimization
dpo_trainer = train_dpo(
    base_model_path="./codepecker_sft_model",  # Use SFT-trained model
    output_dir="./codepecker_dpo_model",
    max_train_samples=5000  # Optional: limit for testing
)

What is DPO?

DPO teaches the model to prefer secure code patterns over vulnerable ones using preference pairs:

  • Chosen response: Fixed/secure code (func_after from BigVul)
  • Rejected response: Vulnerable/buggy code (func_before from BigVul)

This preference-based learning makes the model better at suggesting secure fixes rather than just identifying vulnerabilities.

GRPO Training

from codepecker.grpo import train_grpo

# Stage 3: Group Relative Policy Optimization
grpo_trainer = train_grpo(
    base_model_path="./codepecker_dpo_model",  # Use DPO-trained model
    output_dir="./codepecker_grpo_model",
    reward_type="similarity",  # or "verification"
    num_generations=4,  # Generate 4 completions per prompt
    max_train_samples=5000  # Optional: limit for testing
)

What is GRPO?

GRPO is online reinforcement learning that optimizes fix quality through automated evaluation:

  • Generates multiple completions per prompt (4-128) during training
  • Evaluates each with a reward function (0.0-1.0 score based on code quality)
  • Learns from the best responses in each group

Reward Functions:

  • Similarity: Compares generated fix to ground truth (fast, simple)
  • Verification: Uses static analysis to verify vulnerability is fixed (advanced, robust)

This online learning process produces higher-quality fixes than offline methods alone.

Inference

from codepecker.inference import CodePeckerInference

# Load model
engine = CodePeckerInference(
    model_path="./codepecker_model",
    temperature=0.7
)

# Analyze code
code = """
void process_data(char* input) {
    char buffer[100];
    strcpy(buffer, input);  // Buffer overflow!
}
"""

result = engine.analyze_code(code)
print(result)

Example Output:

**Vulnerability Detected: Yes**

**CWE-120: Buffer Copy without Checking Size of Input**

**Explanation:**
The function uses strcpy() without bounds checking, allowing an
attacker to overflow the buffer if input is longer than 100 bytes.

**Suggested Fix:**
Use strncpy() or strlcpy() with proper size limits, or validate
input length before copying.

**Fixed Code:**
void process_data(char* input) {
    char buffer[100];
    strncpy(buffer, input, sizeof(buffer) - 1);
    buffer[sizeof(buffer) - 1] = '\0';
}

Dataset

CodePecker is trained on BigVul - a large-scale vulnerability dataset:

  • Source: HuggingFace benjis/bigvul
  • Size: 200k+ C code samples
  • Labels: Real CVE/CWE from major projects (Linux kernel, Chrome, tcpdump, etc.)
  • Content: Before/after patches with commit messages

Training Approach

CodePecker uses a three-stage training pipeline to achieve superior vulnerability detection and fix generation:

Stage 1: SFT (Supervised Fine-Tuning)

SFT teaches the model to understand and respond to vulnerability analysis questions:

Input format:

System: You are CodePecker, a security-focused code analysis assistant...
User: Analyze the following C code for security vulnerabilities:
      [vulnerable code]

Output format:

Vulnerability Detected: Yes/No
CWE-XXX: [Weakness type]
Explanation: [Why it's vulnerable]
Suggested Fix: [How to fix it]
Fixed Code: [Corrected version]

Dataset transformation: Each BigVul sample → Q&A pair with vulnerability analysis

Stage 2: DPO (Direct Preference Optimization)

DPO teaches the model to prefer secure code patterns over vulnerable ones:

Preference pairs:

  • Chosen: Fixed/secure code (func_after from BigVul patches)
  • Rejected: Vulnerable/buggy code (func_before from BigVul patches)

How it works:

  1. Takes the SFT-trained model as starting point
  2. Shows the model pairs of (vulnerable code, secure code)
  3. Optimizes the model to assign higher probability to secure code
  4. Uses implicit reference model for memory efficiency

Benefits:

  • Better fix suggestions (prefers real-world secure patterns)
  • More confident in distinguishing safe vs unsafe code
  • Learns from actual security patches in the wild

Example preference pair:

Prompt: "Fix the buffer overflow in: strcpy(buf, input);"
Chosen: "strncpy(buf, input, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0';"
Rejected: "strcpy(buf, input);"  # Original vulnerable code

The model learns to strongly prefer the chosen (secure) response over the rejected (vulnerable) one.

Stage 3: GRPO (Group Relative Policy Optimization)

GRPO optimizes fix quality using online reinforcement learning with automated reward evaluation:

How it works:

  1. Takes the DPO-trained model as starting point
  2. For each prompt, generates multiple completions (4-128 responses)
  3. Evaluates each completion with a reward function (0.0-1.0 score)
  4. Learns from the highest-reward responses in each group
  5. Iteratively improves generation quality through online feedback

Reward Functions:

Similarity-based (default):

# Compares generated fix to ground truth (func_after)
# Rewards: 1.0 if highly similar, proportional otherwise
reward = similarity(generated_code, ground_truth_code)

Verification-based (advanced):

# Uses static analysis to verify vulnerability is fixed
# Rewards: 1.0 if fixed + compiles, 0.5 if fixed only, 0.0 otherwise
reward = verify_vulnerability_fixed(original, generated, cwe_id)

Benefits:

  • Generates higher-quality fixes (optimized through feedback)
  • Learns from actual evaluation during training (online learning)
  • Adapts to reward signal (can optimize for different metrics)
  • Produces more diverse solutions (generates multiple options)

Example GRPO training step:

Prompt: "Fix the buffer overflow in: strcpy(buf, input);"

Generated completions:
1. "strcpy(buf, input);"           → Reward: 0.0 (no fix)
2. "strncpy(buf, input, 99);"      → Reward: 0.6 (partial fix)
3. "strncpy(buf, input, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0';" → Reward: 1.0 ✓
4. "strlcpy(buf, input, sizeof(buf));" → Reward: 0.9 (good alternative)

Model learns to prefer completion #3 (highest reward)

Model Architecture

  • Base Model: Qwen/Qwen2.5-Coder-1.5B
  • Training Method: QLoRA (4-bit quantization + LoRA adapters)
  • Trainable Params: ~9.4M (0.6% of total)
  • Memory: ~6GB VRAM for training, ~4GB for inference
  • Model Format: SafeTensors (secure, no pickle vulnerabilities)

Configuration

Edit codepecker/config.py to customize:

SFT Configuration

# Model settings
BASE_MODEL = "Qwen/Qwen2.5-Coder-1.5B"
USE_QUANTIZATION = True  # 4-bit quantization
USE_LORA = True

# Security settings
SAFE_SERIALIZATION = True  # Use SafeTensors format (secure)

# LoRA settings
LORA_R = 16
LORA_ALPHA = 32

# SFT training settings
LEARNING_RATE = 2e-4
NUM_EPOCHS = 3
BATCH_SIZE = 4
MAX_SEQ_LENGTH = 2048

DPO Configuration

# DPO-specific settings
BETA = 0.2              # KL divergence coefficient (controls preference strength)
LEARNING_RATE = 5e-5    # Lower LR for DPO (more stable)
NUM_EPOCHS = 1          # Usually 1-2 epochs for DPO
BATCH_SIZE = 1          # Smaller batch for preference pairs
GRADIENT_ACCUMULATION_STEPS = 8
LOSS_TYPE = "sigmoid"   # Options: sigmoid, hinge, ipo, kto
USE_REF_MODEL = False   # False = implicit reference (more memory efficient)

GRPO Configuration

# GRPO-specific settings
LEARNING_RATE = 5e-6           # Even lower LR for online RL (very stable)
NUM_EPOCHS = 1                 # Usually 1 epoch for GRPO
BATCH_SIZE = 1                 # Per device
GRADIENT_ACCUMULATION_STEPS = 8
NUM_GENERATIONS = 4            # Generate N completions per prompt (4-128)
REWARD_TYPE = "similarity"     # "similarity" or "verification"
SIMILARITY_THRESHOLD = 0.7     # Min similarity for full reward

Project Structure

codepecker/
├── __init__.py
├── config.py          # Configuration (SFT + DPO + GRPO)
├── inference.py       # Inference engine
├── sft/               # Supervised Fine-Tuning
│   ├── __init__.py
│   ├── train.py       # SFT training script
│   └── data/
│       ├── __init__.py
│       └── dataset.py # BigVul Q&A format
├── dpo/               # Direct Preference Optimization
│   ├── __init__.py
│   ├── train.py       # DPO training script
│   └── data/
│       ├── __init__.py
│       └── dataset.py # BigVul preference pairs
└── grpo/              # Group Relative Policy Optimization
    ├── __init__.py
    ├── train.py       # GRPO training script
    ├── reward.py      # Reward functions (similarity/verification)
    └── data/
        ├── __init__.py
        └── dataset.py # BigVul prompts + ground truth

Hardware Requirements

Training:

  • GPU: 16GB+ VRAM (with 4-bit quantization)
  • RAM: 32GB recommended
  • Storage: ~50GB (model + dataset cache)

Inference:

  • GPU: 8GB+ VRAM recommended (CPU also supported)
  • RAM: 16GB

Tips

SFT Tips

Faster Training:

  • Reduce MAX_SEQ_LENGTH to 1024 or 512
  • Increase GRADIENT_ACCUMULATION_STEPS to reduce memory
  • Use smaller model: Qwen/Qwen2.5-Coder-0.5B

Better Quality:

  • Train for more epochs (5-10)
  • Increase LoRA rank to 32-64
  • Use full dataset (don't limit samples)

DPO Tips

Memory Optimization:

  • Use USE_REF_MODEL = False (implicit reference, saves ~50% memory)
  • Reduce BATCH_SIZE to 1 (DPO needs less due to preference pairs)
  • Increase GRADIENT_ACCUMULATION_STEPS for effective batch size

Better Preference Learning:

  • Adjust BETA (0.1-0.5): Higher = stronger preference, lower = more exploration
  • Try different LOSS_TYPE: sigmoid (default), hinge, ipo, kto
  • Usually 1-2 epochs is enough for DPO (over-training can hurt)

Training Order:

  1. Always run SFT first (model needs base understanding)
  2. Then run DPO on the SFT checkpoint
  3. Use DPO model for final inference

GRPO Tips

Memory Optimization:

  • GRPO generates multiple completions, so memory usage is higher
  • Use NUM_GENERATIONS = 4 for testing, increase to 8-16 for better results
  • Reduce BATCH_SIZE to 1 if running out of memory

Better Quality Optimization:

  • Increase NUM_GENERATIONS (8-32): More diverse responses, better learning
  • Adjust SIMILARITY_THRESHOLD (0.5-0.9): Higher = stricter, lower = more lenient
  • Try REWARD_TYPE = "verification" for advanced static analysis (requires setup)

Training Order:

  1. Run SFT first (base understanding)
  2. Run DPO second (preference learning)
  3. Run GRPO third (quality optimization)
  4. Use GRPO model for final inference (highest quality)

When to use GRPO:

  • ✅ When you need highest-quality fixes (critical systems)
  • ✅ When you have compute budget for online RL
  • ✅ When you want to optimize for specific metrics
  • ❌ Skip if DPO results are sufficient (GRPO is slower)

Security

CodePecker uses SafeTensors format for all model weights and adapters:

  • ✅ No pickle vulnerabilities - Cannot execute arbitrary code
  • ✅ Secure by default - Safe to download and share models
  • ✅ Fast loading - Memory-mapped for efficient loading
  • ✅ Cross-platform - Works across PyTorch, TensorFlow, JAX

All model files (.safetensors) are validated on load to prevent corruption or tampering.

About

LLM specialized in pecking out security and vulnerability bugs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages