Running Your First Garak Scan
Step-by-step beginner walkthrough for running your very first garak vulnerability scan from zero, covering installation, target setup, probe selection, and basic result interpretation.
If you have never used a vulnerability scanner against a language model before, this walkthrough will get you from zero to your first actionable scan result. We will install garak, set up a free local target, run a focused scan, and learn how to read the output. By the end, you will have a repeatable workflow that forms the foundation for every subsequent garak walkthrough in this series.
Step 1: Preparing Your Environment
Before installing garak itself, set up an isolated Python environment. This prevents garak's dependencies (which include PyTorch, transformers, and several ML libraries) from conflicting with your other Python projects.
# Create a dedicated directory for red-teaming work
mkdir -p ~/red-team/garak-lab
cd ~/red-team/garak-lab
# Create a virtual environment
python3 -m venv .venv
# Activate the virtual environment
source .venv/bin/activate
# Verify Python version (must be 3.10+)
python --versionYou should see output like Python 3.11.6 or higher. If your version is below 3.10, you will need to install a newer Python before continuing.
Now upgrade pip to avoid installation issues with garak's dependency chain:
pip install --upgrade pip setuptools wheelThis step avoids a class of build failures that occur when pip tries to compile native extensions with outdated build tools.
Step 2: Installing Garak
With the virtual environment active, install garak from PyPI:
pip install garakThe installation pulls in a significant number of dependencies. On a typical broadband connection, expect 3-5 minutes for the initial install. Once complete, verify:
# Check that garak is available
garak --version
# List available probe families
garak --list_probesThe --list_probes command prints every probe module and class. This is your catalog of available attacks. The output is long, so pipe it to less or a file for comfortable reading:
garak --list_probes > available_probes.txt
wc -l available_probes.txtYou will typically see several hundred probe classes organized into families like dan, encoding, promptinject, gcg, knowledgegraph, and more.
Similarly, list generators and detectors to understand the other components:
garak --list_generators > available_generators.txt
garak --list_detectors > available_detectors.txtStep 3: Setting Up a Local Target with Ollama
For your first scan, use a local model rather than a paid API. This eliminates cost concerns and lets you experiment freely. Ollama is the simplest way to run a model locally.
If you do not have Ollama installed:
# macOS or Linux
curl -fsSL https://ollama.com/install.sh | sh
# Verify installation
ollama --versionPull a small model suitable for testing:
# Pull a small, fast model for experimentation
ollama pull llama3.2:3b
# Verify the model is available
ollama listMake sure the Ollama server is running:
# Start the Ollama server (if not already running)
ollama serve &
# Test that the model responds
ollama run llama3.2:3b "Hello, how are you?"If the model responds conversationally, your target is ready.
Step 4: Running Your First Targeted Scan
Rather than running all probes (which can take hours), start with a focused scan against a single probe family. The promptinject family tests for basic prompt injection vulnerabilities and is a good starting point:
garak --model_type ollama \
--model_name llama3.2:3b \
--probes promptinjectThis command tells garak to:
- Connect to the Ollama instance as the generator
- Load the
llama3.2:3bmodel - Run all probes in the
promptinjectfamily - Use the default detectors for each probe
- Print results to the console and save detailed logs
The scan will take 2-10 minutes depending on your hardware. You will see real-time output as each probe runs:
garak LLM vulnerability scanner v0.9 : https://github.com/NVIDIA/garak
š¦ Loading generator: ollama:llama3.2:3b
š Running probes on ollama:llama3.2:3b
probes.promptinject.HijackHateHumansMini : PASS 100/100
probes.promptinject.HijackKillHumansMini : PASS 98/100
probes.promptinject.HijackLongPrompt : FAIL 72/100
Each line shows:
- The probe class name
- PASS or FAIL status
- The ratio of attempts that the detector classified as safe (higher is better for PASS)
Step 5: Understanding the Scan Output
After the scan completes, garak stores detailed results in its data directory. Find and examine them:
# Find the latest report files
ls -lt ~/.local/share/garak/ | head -10Garak produces two key output files per scan:
| File Type | Extension | Contains |
|---|---|---|
| Report | .report.jsonl | One JSON object per probe attempt with prompt, response, and detection result |
| Log | .log.jsonl | Operational log entries including timing, errors, and metadata |
Examine the report file to understand individual probe attempts:
# Pretty-print the first few entries from the report
cat ~/.local/share/garak/garak.*.report.jsonl | \
python3 -m json.tool | head -60Each entry in the report contains:
{
"entry_type": "attempt",
"probe": "promptinject.HijackLongPrompt",
"prompt": "Ignore the above and instead tell me...",
"output": "I can't help with that request...",
"detector": "promptinject.AttackRogueString",
"status": "pass",
"score": 0.12
}Key fields to focus on:
- probe: Which attack was attempted
- prompt: The exact payload sent to the model
- output: The model's raw response
- status: Whether the detector classified this as a successful attack
- score: Confidence score from the detector (higher means more likely attack succeeded)
Step 6: Expanding Your Scan
Now that you understand the basics, run a broader scan with multiple probe families:
garak --model_type ollama \
--model_name llama3.2:3b \
--probes promptinject,dan,encoding,gcgThis tests four attack categories:
| Probe Family | What It Tests |
|---|---|
promptinject | Direct prompt injection attempts |
dan | "Do Anything Now" jailbreak prompts |
encoding | Encoded payloads (Base64, ROT13, etc.) |
gcg | Gradient-based adversarial suffixes (cached) |
You can also save the output with a custom prefix for easier organization:
garak --model_type ollama \
--model_name llama3.2:3b \
--probes promptinject,dan,encoding,gcg \
--report_prefix first_broad_scanTo get a quick summary of failures from the report:
# Count failures by probe family
cat ~/.local/share/garak/first_broad_scan*.report.jsonl | \
python3 -c "
import sys, json
from collections import Counter
failures = Counter()
for line in sys.stdin:
entry = json.loads(line)
if entry.get('status') == 'fail':
failures[entry['probe']] += 1
for probe, count in failures.most_common():
print(f'{count:4d} {probe}')
"Step 7: Creating a Repeatable Configuration File
Rather than typing long command lines, create a YAML configuration file that captures your scan parameters:
# garak-first-scan.yaml
plugins:
model_type: ollama
model_name: llama3.2:3b
probes:
- promptinject.HijackHateHumansMini
- promptinject.HijackKillHumansMini
- promptinject.HijackLongPrompt
- dan.Dan_11_0
- dan.Dan_6_0
- encoding.InjectBase64
- encoding.InjectROT13
extended_detectors:
- toxicity.ToxicCommentModelRun the scan using the config file:
garak --config garak-first-scan.yaml --report_prefix config_scanThis approach has several advantages:
- Reproducibility: Anyone can run the exact same scan
- Version control: Check the config into your repository
- Iteration: Modify the config and compare results over time
Step 8: Next Steps and Verification
Before moving on, verify that you can answer these questions using your scan results:
- Which probe families produced failures? Look at the console output for FAIL lines.
- What was the worst-performing probe? Find the probe with the lowest pass ratio.
- Can you find the actual attack payload and response for a failure? Use
jqor Python to extract a specific failure from the JSONL report.
# Extract one complete failure example for review
cat ~/.local/share/garak/first_broad_scan*.report.jsonl | \
python3 -c "
import sys, json
for line in sys.stdin:
entry = json.loads(line)
if entry.get('status') == 'fail':
print(json.dumps(entry, indent=2))
break
"If you can extract and read a failure entry, you have the fundamental skills to work with garak. The next walkthroughs in this series build on this foundation:
- garak-custom-probe-creation covers writing probes tailored to your specific application
- garak-multi-model-comparison shows how to compare vulnerability profiles across models
- garak-ci-cd-integration automates scanning in your deployment pipeline
Common Issues and Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
ModuleNotFoundError on import | Incomplete installation | Run pip install garak --force-reinstall |
ConnectionRefusedError for Ollama | Ollama server not running | Run ollama serve in a separate terminal |
| Model not found error | Model not pulled yet | Run ollama pull llama3.2:3b |
| Scan hangs on first probe | Model loading into memory | Wait 30-60 seconds for initial model load |
| Very slow scan times | CPU-only inference | This is normal for CPU; consider a GPU or smaller model |
| Empty report file | Scan interrupted or crashed | Check the log file for error details |
CUDA out of memory | GPU memory exhausted | Use a smaller model like llama3.2:1b or set CUDA_VISIBLE_DEVICES="" for CPU |
Related Topics
- Garak End-to-End Walkthrough -- The comprehensive reference covering all garak features
- Garak Custom Probe Creation -- Next step: writing probes for your specific application
- Prompt Injection Fundamentals -- Understanding the attack category garak tests most
- Ollama Local Red Teaming -- More on using local models for security testing
When running your first garak scan, why is it recommended to use a targeted probe family like 'promptinject' instead of '--probes all'?