
Pentest R1 Autonomous Penetration Testing
- 1 installs
- 10 repo stars
- Updated August 4, 2026
- aradotso/security-skills
Pentest-R1 is a Claude skill documenting a two-stage reinforcement-learning framework that trains LLMs for autonomous penetration testing and CTF challenges.
About
Pentest-R1 is a two-stage reinforcement-learning framework for training large language models to perform autonomous penetration testing and CTF challenges. Stage 1 does offline RL on 500+ expert walkthroughs and Stage 2 does online RL inside interactive CTF Docker environments. A researcher uses it to fine-tune a model like Llama 3.1 8B with LoRA to develop attack-reasoning capabilities.
- Two-stage RL framework to train LLMs for autonomous pentesting
- Offline RL on 500+ expert walkthroughs, then online RL in CTF envs
- Docker + GPU setup with unsloth/LoRA fine-tuning
Pentest R1 Autonomous Penetration Testing by the numbers
- 1 all-time installs (skills.sh)
- Ranked #14,098 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
pentest-r1-autonomous-penetration-testing capabilities & compatibility
Free code, but training needs a GPU with CUDA and significant compute.
- Capabilities
- agent training · reinforcement learning · security audit
- Works with
- docker
- Use cases
- orchestration · research
- Platforms
- Linux
- Pricing
- Free
What pentest-r1-autonomous-penetration-testing says it does
Pentest-R1 is a two-stage reinforcement learning framework that trains Large Language Models for autonomous penetration testing.
Stage 1 trains the base LLM on a curated dataset of 500+ real-world expert penetration testing walkthroughs.
npx skills add https://github.com/aradotso/security-skills --skill pentest-r1-autonomous-penetration-testingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 10 |
| Last updated | August 4, 2026 |
| Repository | aradotso/security-skills ↗ |
What it does
Train and fine-tune an LLM for autonomous penetration testing using offline and online reinforcement learning.
Who is it for?
ML researchers building autonomous security-testing agents from an LLM base.
Skip if: Practitioners who want to run a pentest now; this trains models rather than testing targets.
When should I use this skill?
You want to fine-tune an LLM for autonomous pentesting with offline and online RL.
What you get
A two-stage RL pipeline produces an LLM that reasons through pentest and CTF tasks.
By the numbers
- Two-stage RL pipeline
- Stage 1 trains on 500+ expert penetration-testing walkthroughs
Files
Pentest-R1 Autonomous Penetration Testing
Skill by ara.so — Security Skills collection
Pentest-R1 is a two-stage reinforcement learning framework that trains Large Language Models for autonomous penetration testing. It combines offline RL on expert walkthroughs with online RL in interactive CTF environments to develop robust attack reasoning capabilities.
Installation
Prerequisites
- Python 3.11.11
- Docker (for Stage 2 and reproducible environments)
- NVIDIA Container Toolkit (for GPU support)
- CUDA 12.4 runtime (optional, for GPU acceleration)
Basic Setup
git clone https://github.com/KHenryAegis/Pentest-R1.git
cd Pentest-R1
pip install -r requirements.txtDocker Environment (Recommended for Reproducibility)
# Build the reproducible research environment
source setup-docker.sh
# Run container with optimized cache mounting
docker run --rm -it \
--name pentest-r1 \
-v "$(pwd)":/root/Pentest-R1 \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-v ~/.cache/triton:/root/.cache/triton \
-v ~/.cache/torch_extensions:/root/.cache/torch_extensions \
-w /root/Pentest-R1 \
--gpus all \
--net=host \
pentest-r1:ubuntu22.04Core Training Pipeline
Stage 1: Offline Reinforcement Learning
Stage 1 trains the base LLM on a curated dataset of 500+ real-world expert penetration testing walkthroughs.
python grpo_stage1.pyKey configuration in `grpo_stage1.py`:
from transformers import AutoTokenizer, AutoModelForCausalLM
from unsloth import FastLanguageModel
import torch
# Model configuration
model_name = "unsloth/Meta-Llama-3.1-8B-Instruct"
max_seq_length = 4096
dtype = None # Auto-detect
load_in_4bit = True # Use 4-bit quantization
# Load model with unsloth optimization
model, tokenizer = FastLanguageModel.from_pretrained(
model_name=model_name,
max_seq_length=max_seq_length,
dtype=dtype,
load_in_4bit=load_in_4bit,
)
# PEFT configuration for efficient training
from peft import LoraConfig, get_peft_model
peft_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
model = get_peft_model(model, peft_config)Stage 2: Online Reinforcement Learning
Stage 2 fine-tunes the model in interactive CTF environments with real-time feedback.
Setup CTF environment:
cd train_ctf_env
docker build -t intercode-ctf .
cd ..Run Stage 2 training:
python grpo_multi_turn_stage2.pyKey Components
Data Loading and Preprocessing
from datasets import load_dataset
# Load expert walkthrough dataset
dataset = load_dataset("json", data_files="path/to/expert_walkthroughs.jsonl")
# Example dataset format
# {
# "challenge": "SQL Injection in login form",
# "steps": [
# {"action": "reconnaissance", "command": "sqlmap -u http://target/login", "reasoning": "..."},
# {"action": "exploit", "command": "sqlmap --dump", "reasoning": "..."}
# ],
# "flag": "CTF{...}"
# }
def preprocess_function(examples):
"""Format data for training"""
prompts = []
responses = []
for challenge, steps in zip(examples["challenge"], examples["steps"]):
prompt = f"Challenge: {challenge}\nWhat are the steps to solve this?"
response = "\n".join([
f"Step {i+1}: {step['reasoning']}\nCommand: {step['command']}"
for i, step in enumerate(steps)
])
prompts.append(prompt)
responses.append(response)
return {"prompt": prompts, "response": responses}
tokenized_dataset = dataset.map(preprocess_function, batched=True)Reward Model Configuration
class PentestRewardModel:
"""Reward model for evaluating penetration testing actions"""
def __init__(self):
self.success_reward = 1.0
self.partial_reward = 0.5
self.failure_penalty = -0.1
def calculate_reward(self, action, environment_feedback):
"""Calculate reward based on action outcome"""
if "flag" in environment_feedback.lower():
return self.success_reward
elif "error" in environment_feedback.lower():
return self.failure_penalty
elif "progress" in environment_feedback.lower():
return self.partial_reward
return 0.0
reward_model = PentestRewardModel()Interacting with CTF Environment
import docker
class CTFEnvironment:
"""Wrapper for InterCode-CTF Docker environment"""
def __init__(self, image_name="intercode-ctf"):
self.client = docker.from_env()
self.image_name = image_name
self.container = None
def start(self, challenge_id):
"""Start a CTF challenge container"""
self.container = self.client.containers.run(
self.image_name,
detach=True,
environment={"CHALLENGE_ID": challenge_id},
network_mode="host",
remove=True
)
return self.container
def execute_command(self, command):
"""Execute a command in the container"""
if not self.container:
raise RuntimeError("Container not started")
exec_result = self.container.exec_run(command)
return {
"stdout": exec_result.output.decode('utf-8'),
"exit_code": exec_result.exit_code
}
def cleanup(self):
"""Stop and remove container"""
if self.container:
self.container.stop()
self.container = None
# Usage example
env = CTFEnvironment()
env.start(challenge_id="sql_injection_001")
result = env.execute_command("sqlmap -u http://localhost/login --batch")
print(result["stdout"])
env.cleanup()Training Configuration
GRPO (Group Relative Policy Optimization) Settings
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./pentest-r1-checkpoints",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=5e-5,
warmup_steps=100,
logging_steps=10,
save_steps=500,
save_total_limit=3,
fp16=True, # Mixed precision training
report_to="wandb", # Optional: integration with Weights & Biases
remove_unused_columns=False,
)Environment Variables
import os
# Model and training configuration
os.environ["HF_TOKEN"] = os.getenv("HUGGINGFACE_TOKEN") # For model downloads
os.environ["WANDB_API_KEY"] = os.getenv("WANDB_API_KEY") # For logging
os.environ["CUDA_VISIBLE_DEVICES"] = "0" # GPU selection
# Cache directories (mounted in Docker)
os.environ["HF_HOME"] = "/root/.cache/huggingface"
os.environ["TRITON_CACHE_DIR"] = "/root/.cache/triton"Common Patterns
Multi-Turn Reasoning
class MultiTurnAgent:
"""Agent for multi-turn penetration testing reasoning"""
def __init__(self, model, tokenizer):
self.model = model
self.tokenizer = tokenizer
self.conversation_history = []
def generate_action(self, observation):
"""Generate next action based on current observation"""
# Build prompt with conversation history
prompt = self._build_prompt(observation)
inputs = self.tokenizer(prompt, return_tensors="pt")
outputs = self.model.generate(
**inputs,
max_new_tokens=512,
temperature=0.7,
do_sample=True,
top_p=0.95
)
action = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
self.conversation_history.append({
"observation": observation,
"action": action
})
return action
def _build_prompt(self, observation):
"""Build prompt with conversation history"""
prompt = "You are a penetration testing expert. Analyze and exploit:\n\n"
for turn in self.conversation_history[-3:]: # Last 3 turns
prompt += f"Observation: {turn['observation']}\n"
prompt += f"Action: {turn['action']}\n\n"
prompt += f"Current Observation: {observation}\n"
prompt += "Next Action:"
return promptEvaluation Loop
def evaluate_on_ctf_challenges(model, tokenizer, challenge_set):
"""Evaluate model on a set of CTF challenges"""
agent = MultiTurnAgent(model, tokenizer)
results = []
for challenge in challenge_set:
env = CTFEnvironment()
env.start(challenge["id"])
solved = False
max_turns = 20
for turn in range(max_turns):
# Get current state
observation = env.execute_command("cat /challenge/description.txt")
# Generate action
action = agent.generate_action(observation["stdout"])
# Execute action
result = env.execute_command(action)
# Check for success
if "CTF{" in result["stdout"]:
solved = True
break
results.append({
"challenge_id": challenge["id"],
"solved": solved,
"turns": turn + 1
})
env.cleanup()
return resultsTroubleshooting
CUDA Out of Memory
# Use gradient checkpointing
model.gradient_checkpointing_enable()
# Reduce batch size
training_args.per_device_train_batch_size = 1
training_args.gradient_accumulation_steps = 8
# Use 8-bit or 4-bit quantization
load_in_4bit = TrueDocker Container Issues
# Check container logs
docker logs intercode-ctf
# Verify network connectivity
docker run --rm --net=host intercode-ctf ping -c 4 localhost
# Rebuild with no cache if issues persist
docker build --no-cache -t intercode-ctf train_ctf_env/Unsloth Version Compatibility
The research used unsloth==2025.5.10. If unavailable, the closest match is specified in requirements.txt:
unsloth_zoo==2025.5.11
unsloth @ git+https://github.com/unslothai/unsloth.git@45f26cda996ec0b9a2e28cb18a03251095aa29e8Model Loading Errors
# If model fails to load, try without quantization first
model, tokenizer = FastLanguageModel.from_pretrained(
model_name=model_name,
max_seq_length=max_seq_length,
dtype=torch.float16,
load_in_4bit=False,
)
# Clear cache if needed
import shutil
shutil.rmtree(os.path.expanduser("~/.cache/huggingface"), ignore_errors=True)Performance Optimization
Cache Mounting for Faster Training
Always mount HuggingFace, Triton, and PyTorch caches when using Docker:
-v ~/.cache/huggingface:/root/.cache/huggingface \
-v ~/.cache/triton:/root/.cache/triton \
-v ~/.cache/torch_extensions:/root/.cache/torch_extensionsDistributed Training
# For multi-GPU training
training_args.ddp_find_unused_parameters = False
training_args.local_rank = int(os.environ.get("LOCAL_RANK", -1))
# Launch with torchrun
# torchrun --nproc_per_node=4 grpo_stage1.pyReferences
- Paper: arXiv:2508.07382
- Base model: Meta-Llama-3.1-8B-Instruct
- Framework: Unsloth for optimized fine-tuning
- Environment: InterCode-CTF for interactive training
Related skills
FAQ
What are the two stages?
Stage 1 is offline RL on expert walkthroughs; Stage 2 is online RL in interactive CTF Docker environments.
What base model does it use?
The example config fine-tunes unsloth/Meta-Llama-3.1-8B-Instruct with 4-bit quantization and LoRA.