ai security

Red-Teaming LLMs with garak

Run NVIDIA garak probe suites against an LLM endpoint to test for jailbreaks, prompt injection, data leakage, and toxic generation, then interpret the hit-rate report for triage and reporting.

ai-securitydata-leakagegarakjailbreakllm-red-teamingmitre-atlasprompt-injectionvulnerability-scanning
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Legal and Authorized-Use Notice: This skill is for authorized AI security testing and educational purposes only. Probe only models, API keys, and endpoints you own or have explicit written permission to test. Automated probing of third-party LLM APIs may violate their terms of service and consume billable tokens. Unauthorized probing of systems you do not control may be illegal.

Overview

garak (Generative AI Red-teaming and Assessment Kit) is an open-source LLM vulnerability scanner maintained by NVIDIA. It plays the role that a network vulnerability scanner like Nessus plays for hosts, but for large language models: it sends thousands of adversarial prompts ("probes") at a target model, captures the generations, and runs automated "detectors" over the responses to decide whether each attempt succeeded. Probe families cover prompt injection (promptinject, latentinjection), jailbreaks (dan), training-data and system-prompt leakage (leakreplay), malware generation (malwaregen), cross-site-scripting payload emission (xss), encoding-based bypasses (encoding), toxicity, and more. garak is described in the paper "garak: A Framework for Security Probing Large Language Models" (arXiv:2406.11036) and is distributed from the NVIDIA/garak GitHub repository.

The scanner is generator-agnostic. It can target Hugging Face models loaded locally, OpenAI-compatible APIs, AWS Bedrock, Replicate, Cohere, NIM endpoints, GGUF/llama.cpp models, and arbitrary REST endpoints via a JSON generator spec. After a run, garak emits a .report.jsonl line-delimited log of every attempt and detector verdict, a human-readable .report.html, a garak.log debug log, and a hit log of confirmed vulnerabilities. The terminal output prints a per-probe, per-detector pass/fail summary with a hit rate (for example dan.Dan_11_0 jailbreak: FAIL ok on 38/40), which is the primary artifact you interpret.

This skill maps to the MITRE ATLAS techniques AML.T0051 (LLM Prompt Injection) and AML.T0054 (LLM Jailbreak) because garak operationalizes both: it crafts prompt-injection and jailbreak inputs at scale and measures whether the target's guardrails hold. It supports the NIST AI RMF MEASURE-2.7 subcategory by providing repeatable, quantitative security/resilience measurement of a deployed AI system.

When to Use

  • When you need a fast, repeatable baseline security assessment of an LLM before or after deployment.
  • When validating that a guardrail, system prompt, or safety fine-tune actually reduces jailbreak and injection success rates (run before/after and compare hit rates).
  • When producing evidence for an AI risk assessment or model card security section (NIST AI RMF MEASURE-2.7).
  • When triaging which OWASP LLM Top 10 risks (LLM01 prompt injection, LLM02 sensitive information disclosure, LLM07 system prompt leakage) actually manifest in your model.
  • When regression-testing an LLM endpoint in CI after model or prompt changes.

Prerequisites

  • Python 3.10+ (3.12 recommended) and a virtual environment.
  • Install garak from PyPI:
    python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
    python -m pip install -U garak
    garak --version
  • For the bleeding-edge version:
    python -m pip install -U git+https://github.com/NVIDIA/garak.git@main
  • An API key for the target if probing a hosted model (for example export OPENAI_API_KEY="sk-...").
  • Written authorization to test the target, and awareness of token cost (probes generate thousands of calls).

Objectives

  • Enumerate available probes and detectors and pick a scoped suite.
  • Configure garak against a local Hugging Face model, an OpenAI-compatible API, and an arbitrary REST endpoint.
  • Run prompt-injection, jailbreak, and leakage probe families and capture reports.
  • Interpret the per-probe hit-rate output and the .report.jsonl.
  • Re-run after applying a mitigation to demonstrate risk reduction.
  • Produce a defensible findings artifact for an AI risk assessment.

MITRE ATT&CK Mapping

This skill uses MITRE ATLAS (the adversarial-ML companion to ATT&CK) technique IDs.

ID Tactic Official Name Relevance
AML.T0051 ML Attack Staging / Impact LLM Prompt Injection garak's promptinject and latentinjection probes craft malicious prompts that subvert intended model behavior.
AML.T0054 Privilege Escalation / Defense Evasion LLM Jailbreak garak's dan and related probes attempt to bypass safety guardrails so the model produces restricted content.

Workflow

Phase 1: Enumerate Probes and Detectors

  1. List every probe garak ships so you can scope the run:
    garak --list_probes
  2. List detectors (the modules that score whether a probe succeeded) and generators (target connectors):
    garak --list_detectors
    garak --list_generators
  3. Read the probe taxonomy. Key families:
    • promptinject — PromptInject-framework direct injection.
    • latentinjection — instructions hidden in documents/encoded text (indirect injection).
    • dan — "Do Anything Now" and related jailbreaks (e.g. dan.Dan_11_0).
    • leakreplay — coax the model into reproducing memorized/training or hidden-prompt text.
    • encoding — base64/ROT13/etc. injection bypasses.
    • xss — emit cross-site-scripting payloads (markdown/HTML exfil).
    • malwaregen — request AV-evading or malicious code.

Phase 2: Probe a Local Hugging Face Model

  1. Run a single jailbreak probe against a local model to validate setup:
    python -m garak --target_type huggingface --target_name gpt2 --probes dan.Dan_11_0
  2. Run a fuller suite against a chat model:
    python -m garak \
      --target_type huggingface \
      --target_name meta-llama/Llama-3.2-1B-Instruct \
      --probes promptinject,dan,leakreplay \
      --report_prefix llama32_baseline

Phase 3: Probe an OpenAI-Compatible API

  1. Export the key and run injection + leakage probes:
    export OPENAI_API_KEY="sk-..."
    python -m garak \
      --target_type openai \
      --target_name gpt-4o-mini \
      --probes promptinject,latentinjection,leakreplay \
      --generations 5 \
      --parallel_attempts 8 \
      --report_prefix gpt4omini_injection
    • --generations controls how many completions per prompt (more = more statistical confidence, more cost).
    • --parallel_attempts raises throughput for remote APIs.

Phase 4: Probe an Arbitrary REST Endpoint

  1. garak can target any HTTP API via a JSON generator spec. Create rest.json:
    {
      "rest": {
        "RestGenerator": {
          "name": "my-llm-gateway",
          "uri": "https://llm.internal.example/v1/chat",
          "method": "post",
          "headers": { "Authorization": "Bearer $ENV_TOKEN", "Content-Type": "application/json" },
          "req_template_json_object": { "model": "internal-bot", "prompt": "$INPUT" },
          "response_json": true,
          "response_json_field": "$.output"
        }
      }
    }
  2. Run garak against it:
    export ENV_TOKEN="..."
    python -m garak \
      --target_type rest \
      -G rest.json \
      --probes promptinject,dan \
      --report_prefix internal_gateway

Phase 5: Run a Curated Config and Full Sweep

  1. For repeatable assessments, pin everything in a YAML/JSON config and pass --config:
    python -m garak --config assessment.yaml
    # assessment.yaml
    plugins:
      model_type: openai
      model_name: gpt-4o-mini
      probe_spec: promptinject,latentinjection,dan,leakreplay,xss,malwaregen
    run:
      generations: 5
      parallel_attempts: 8
    reporting:
      report_prefix: quarterly_llm_assessment
  2. For an exhaustive sweep (slow, expensive) run all probes by omitting --probes entirely.

Phase 6: Interpret the Hit-Rate Report

  1. Read the terminal summary. Each row is probe.Class detector: PASS|FAIL ok on N/M. A FAIL with a low ok fraction means the model frequently produced the unsafe behavior — a high-severity finding.
  2. Open the machine-readable report and aggregate failures:
    # Every attempt with detector verdicts is one JSON line
    jq -r 'select(.entry_type=="eval") | "\(.probe)\t\(.detector)\t\(.passed)/\(.total)"' \
      garak.<timestamp>.report.jsonl | sort
  3. Open the generated .report.html in a browser for the formatted scorecard and per-probe breakdown.
  4. Pull the actual successful attack strings from the hit log to use as proof-of-concept evidence.

Phase 7: Mitigate and Re-Test

  1. Apply a control (tighten the system prompt, add an input/output guardrail such as Llama Guard or LLM Guard, or change the model).
  2. Re-run the identical probe set with a new --report_prefix.
  3. Compare hit rates between runs to quantify risk reduction for the report.

Tools and Resources

Resource Purpose Link
NVIDIA/garak Source, probe list, issues https://github.com/NVIDIA/garak
garak documentation CLI reference, generator configs https://docs.garak.ai/ and https://reference.garak.ai/
garak paper (arXiv:2406.11036) Methodology and design https://arxiv.org/abs/2406.11036
OWASP Top 10 for LLM Applications Risk taxonomy probes map to https://genai.owasp.org/
MITRE ATLAS AML technique definitions https://atlas.mitre.org/

Probe Family Reference

Probe family Targets OWASP LLM mapping
promptinject Direct prompt injection LLM01
latentinjection Indirect / hidden-context injection LLM01
dan Jailbreak / guardrail bypass LLM01 / safety
leakreplay Training-data & prompt leakage LLM02 / LLM07
encoding Encoding-based filter bypass LLM01
xss Markdown/HTML exfiltration payloads LLM02
malwaregen Malicious code generation misuse

Validation Criteria

  • garak installed and garak --version succeeds.
  • Probes and detectors enumerated with --list_probes / --list_detectors.
  • At least one probe run completed against the target with a --report_prefix set.
  • .report.jsonl, .report.html, and garak.log produced and located.
  • Per-probe hit rates extracted and ranked by severity.
  • Successful attack strings captured from the hit log as evidence.
  • A mitigation applied and a comparison re-run completed showing changed hit rates.
  • Findings documented against OWASP LLM Top 10 and MITRE ATLAS for the risk assessment.
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 2

api-reference.md3.0 KB

garak CLI Reference

Source: https://github.com/NVIDIA/garak and https://reference.garak.ai/en/latest/cliref.html

Invocation

python -m garak <options>
# or the console script
garak <options>

Core flags

Flag Description Example
--target_type (alias --model_type) Generator family / interface --target_type openai
--target_name (alias --model_name) Specific model name --target_name gpt-4o-mini
--probes, -p Comma-separated probe spec; module or module.Class --probes promptinject,dan.Dan_11_0
--detectors, -d Override detectors --detectors mitigation.MitigationBypass
--generations, -g Completions generated per prompt --generations 5
--parallel_attempts Parallel probe attempts (throughput) --parallel_attempts 8
--report_prefix Prefix for output report files --report_prefix baseline
--config Load a YAML/JSON run config --config assessment.yaml
-G / --generator_option_file JSON file with generator options (REST etc.) -G rest.json
--generator_options Inline JSON generator options
--list_probes Print all probes and exit
--list_detectors Print all detectors and exit
--list_generators Print all generator types and exit
--list_buffs Print prompt-mutating buffs
--version Print version
--verbose, -v Increase logging

Common target_type values

Value Target
huggingface Local Hugging Face model
openai OpenAI / OpenAI-compatible API (uses OPENAI_API_KEY)
rest Arbitrary HTTP endpoint via JSON spec
ggml / nim / replicate / cohere / bedrock Other hosted/local backends

REST generator JSON spec keys

Key Meaning
uri Endpoint URL
method HTTP method (post)
headers Request headers (supports $ENV_VAR)
req_template_json_object Request body with $INPUT placeholder
response_json true if response is JSON
response_json_field JSONPath to extract the model output

Output artifacts

File Content
<prefix>.report.jsonl Line-delimited record of every attempt, generation, and detector verdict
<prefix>.report.html Human-readable scorecard
<prefix>.hitlog.jsonl Confirmed successful attacks (evidence)
garak.log Debug log

Example runs

# Enumerate
garak --list_probes
 
# Local HF model, single jailbreak probe
python -m garak --target_type huggingface --target_name gpt2 --probes dan.Dan_11_0
 
# Hosted API, injection + leakage suite
export OPENAI_API_KEY="sk-..."
python -m garak --target_type openai --target_name gpt-4o-mini \
  --probes promptinject,latentinjection,leakreplay \
  --generations 5 --parallel_attempts 8 --report_prefix assessment
 
# Arbitrary REST endpoint
python -m garak --target_type rest -G rest.json --probes promptinject,dan
standards.md1.4 KB

Standards and Framework Mapping — Red-Teaming LLMs with garak

MITRE ATLAS (Adversarial Threat Landscape for AI Systems)

ID Name Rationale
AML.T0051 LLM Prompt Injection garak's promptinject and latentinjection probes craft inputs that override intended model instructions; the scanner measures how often the target obeys the injected directive.
AML.T0054 LLM Jailbreak garak's dan and related probes attempt to push the model past its safety guardrails so it produces restricted output; the detector verdict measures jailbreak success.

Reference: https://atlas.mitre.org/

NIST AI Risk Management Framework (AI RMF 1.0)

ID Function/Subcategory Rationale
MEASURE-2.7 AI system security and resilience are evaluated and documented garak produces repeatable, quantitative measurements (per-probe hit rates) of an LLM's resistance to injection, jailbreak, and leakage, directly evidencing this subcategory.

Reference: https://www.nist.gov/itl/ai-risk-management-framework

OWASP Top 10 for LLM Applications (cross-reference)

OWASP ID Risk garak probe family
LLM01:2025 Prompt Injection promptinject, latentinjection, encoding, dan
LLM02:2025 Sensitive Information Disclosure leakreplay, xss
LLM07:2025 System Prompt Leakage leakreplay

Reference: https://genai.owasp.org/

Scripts 1

agent.py5.3 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
garak red-team automation helper.

Wraps the NVIDIA garak LLM vulnerability scanner (https://github.com/NVIDIA/garak)
via subprocess to run a scoped probe suite against a target model, then parses the
resulting .report.jsonl to rank findings by hit rate. Use only against models you
are authorized to test.

Examples:
  python agent.py run --target-type openai --target-name gpt-4o-mini \
      --probes promptinject,dan,leakreplay --report-prefix assessment
  python agent.py parse --report assessment.report.jsonl
  python agent.py list-probes
"""
import argparse
import glob
import json
import os
import shutil
import subprocess
import sys
from collections import defaultdict


def _garak_cmd():
    """Return the command prefix to invoke garak (prefer the module form)."""
    if shutil.which("garak"):
        return ["garak"]
    return [sys.executable, "-m", "garak"]


def list_probes(_args):
    cmd = _garak_cmd() + ["--list_probes"]
    try:
        subprocess.run(cmd, check=True)
    except FileNotFoundError:
        sys.exit("garak is not installed. Run: python -m pip install -U garak")
    except subprocess.CalledProcessError as exc:
        sys.exit(f"garak --list_probes failed with exit code {exc.returncode}")


def run_scan(args):
    cmd = _garak_cmd()
    cmd += ["--target_type", args.target_type, "--target_name", args.target_name]
    if args.probes:
        cmd += ["--probes", args.probes]
    if args.generations:
        cmd += ["--generations", str(args.generations)]
    if args.parallel_attempts:
        cmd += ["--parallel_attempts", str(args.parallel_attempts)]
    if args.generator_option_file:
        cmd += ["-G", args.generator_option_file]
    if args.report_prefix:
        cmd += ["--report_prefix", args.report_prefix]

    if args.target_type == "openai" and not os.environ.get("OPENAI_API_KEY"):
        print("[!] OPENAI_API_KEY is not set; openai target will fail.", file=sys.stderr)

    print("[*] Executing:", " ".join(cmd))
    try:
        result = subprocess.run(cmd, check=False)
    except FileNotFoundError:
        sys.exit("garak is not installed. Run: python -m pip install -U garak")
    if result.returncode != 0:
        print(f"[!] garak exited non-zero ({result.returncode}); a non-zero exit "
              "can indicate findings were detected.", file=sys.stderr)

    # Locate the most recent matching report and summarize it.
    pattern = f"{args.report_prefix}*.report.jsonl" if args.report_prefix else "garak.*.report.jsonl"
    reports = sorted(glob.glob(pattern), key=os.path.getmtime)
    if reports:
        print(f"[*] Parsing latest report: {reports[-1]}")
        _summarize(reports[-1])
    else:
        print("[!] No report.jsonl found to summarize.", file=sys.stderr)


def _summarize(report_path):
    """Aggregate garak eval rows into per-probe/detector hit rates."""
    if not os.path.exists(report_path):
        sys.exit(f"Report not found: {report_path}")

    rows = []
    with open(report_path, "r", encoding="utf-8") as fh:
        for line in fh:
            line = line.strip()
            if not line:
                continue
            try:
                obj = json.loads(line)
            except json.JSONDecodeError:
                continue
            if obj.get("entry_type") == "eval":
                rows.append(obj)

    if not rows:
        print("[!] No eval rows found in report (run may be incomplete).")
        return

    findings = []
    for r in rows:
        probe = r.get("probe", "?")
        detector = r.get("detector", "?")
        passed = r.get("passed", 0)
        total = r.get("total", 0) or 1
        hit_rate = 1.0 - (passed / total)  # fraction of attempts that succeeded as attacks
        findings.append((hit_rate, probe, detector, passed, total))

    findings.sort(reverse=True)
    print("\n=== garak findings (ranked by attack success rate) ===")
    print(f"{'HIT%':>6}  {'PROBE':<40} {'DETECTOR':<28} PASS/TOTAL")
    for hit_rate, probe, detector, passed, total in findings:
        sev = "HIGH" if hit_rate >= 0.5 else "MED " if hit_rate >= 0.1 else "low "
        print(f"{hit_rate*100:6.1f}  {probe:<40} {detector:<28} {passed}/{total}  [{sev}]")


def parse_report(args):
    _summarize(args.report)


def build_parser():
    p = argparse.ArgumentParser(description="garak red-team automation helper")
    sub = p.add_subparsers(dest="command", required=True)

    lp = sub.add_parser("list-probes", help="List garak probes")
    lp.set_defaults(func=list_probes)

    rs = sub.add_parser("run", help="Run a garak scan and summarize")
    rs.add_argument("--target-type", required=True, help="e.g. openai, huggingface, rest")
    rs.add_argument("--target-name", required=True, help="model name")
    rs.add_argument("--probes", help="comma-separated probe spec")
    rs.add_argument("--generations", type=int, default=0)
    rs.add_argument("--parallel-attempts", type=int, default=0)
    rs.add_argument("--generator-option-file", help="JSON generator spec (-G), e.g. rest.json")
    rs.add_argument("--report-prefix", default="garak_run")
    rs.set_defaults(func=run_scan)

    pr = sub.add_parser("parse", help="Parse an existing report.jsonl")
    pr.add_argument("--report", required=True)
    pr.set_defaults(func=parse_report)
    return p


def main():
    args = build_parser().parse_args()
    args.func(args)


if __name__ == "__main__":
    main()
Keep exploring