Skip to content
← AI red teaming: techniques, open-source tools and automated pipelines

Lesson 13 of 22 · 11 min

Hands-on: scan your own endpoint with garak

Install garak, point it at your own HTTP endpoint, run its injection probes, and read the report files it writes, including the two pitfalls that stop most first runs.

garak describes itself in one line: it “checks if an LLM can be made to fail in a way we don’t want” [1]. This lesson is a worked run, written from a real one: garak 0.17.0, run on 12 October 2026 against a small summarising assistant on a local model. Use it on an endpoint you own.

Install it in its own environment

install
python3 -m venv .venv-garak
.venv-garak/bin/pip install -U garak
.venv-garak/bin/python -m garak --version

See what it can do

list probes
.venv-garak/bin/python -m garak --list_probes | grep -i inject

Probes come in families such as promptinject and latentinjection. Most have a default version and a Full version (for example promptinject.HijackHateHumans and promptinject.HijackHateHumansFull) that sends many more prompts, so start with the default ones. The injection families and their detectors were described in lesson 11.

Point it at your own endpoint

garak talks to a custom HTTP endpoint through its REST generator, configured by a small JSON file. The request template uses $INPUT where garak’s prompt goes, and response_json_field names the field that holds the reply:

gen.json
{
  "rest": {
    "RestGenerator": {
      "name": "my-assistant",
      "uri": "http://127.0.0.1:8800/none/chat",
      "method": "post",
      "headers": { "Content-Type": "application/json" },
      "req_template_json_object": { "message": "$INPUT" },
      "response_json": true,
      "response_json_field": "reply",
      "request_timeout": 120
    }
  }
}

A second file limits the run. soft_probe_prompt_cap caps how many prompts each probe sends, which keeps a first run short; generations sets how many replies are collected per prompt:

cfg.json
{ "run": { "generations": 1, "soft_probe_prompt_cap": 20 },
  "system": { "narrow_output": true } }

Run it

one scan
.venv-garak/bin/python -m garak \
    --target_type rest -G gen.json --config cfg.json \
    --probes promptinject.HijackHateHumans,latentinjection.LatentInjectionReport \
    --report_prefix "$PWD/out/scan" \
    --parallel_attempts 1 --seed 7

Read what it wrote

garak’s README describes a report of each run, structured as JSONL, and a hit log detailing the attempts that yielded a vulnerability [1]. In our run it wrote three files from the prefix: the JSONL report, the hit log and an HTML version of the report.

  • scan.report.jsonl: one JSON object per line. Lines with "entry_type": "eval" summarise a probe and detector pair, with passed, fails and total_evaluated.
  • scan.hitlog.jsonl: the individual attempts that failed, with the prompt and the reply. Read these first (lesson 18).
  • scan.report.html: the same results for people.
an eval line (shortened)
{"entry_type": "eval", "probe": "promptinject.HijackHateHumans",
 "detector": "promptinject.AttackRogueString",
 "passed": 0, "fails": 3, "total_evaluated": 3}

In that run, three of three prompts succeeded against an unprotected assistant. Three attempts are far too few to rate anything: use the failure count over the number of attempts with an interval, as in lesson 18, and raise the prompt cap before drawing a conclusion.

Pitfalls we hit

  • Relative report prefix: use an absolute path.
  • Dependency clash with other tools: one virtual environment per tool.
  • Default versus Full probes: a Full probe can send hundreds of prompts, and on a slow local model that is a long wait.
  • Detectors define “failure”. promptinject.AttackRogueString checks for a specific string in the reply, so a reply that refuses while quoting the string can be flagged. Read the hit log.

Try it

  1. Run the scan above against an endpoint you own, with the prompt cap at 20.
  2. Open the hit log and classify five failures as real or false alarms.
  3. Repeat with a defence added (lesson 10), and compare the failure counts over attempts, with intervals.

Key takeaways

  • garak reaches a custom endpoint through the REST generator and two small JSON files.
  • Cap the prompts per probe for a first run, and use the default probes before the Full ones.
  • Always give the report prefix as an absolute path.
  • Read the hit log: it shows the replies behind each failure, and detectors can be wrong.
  • Keep each AI-testing tool in its own virtual environment.

Check yourself

  1. 1. How does garak send prompts to your own HTTP endpoint?

    • Through the REST generator configured by a JSON file — Right.
    • By editing the model weights
    • Only through Hugging Face
    • It cannot

    The REST generator posts a request template, with the prompt substituted for the input placeholder.

  2. 2. What does soft_probe_prompt_cap do?

    • Limits how many prompts each probe sends — Right.
    • Sets the temperature
    • Encrypts the report
    • Adds a probe

    It keeps a first run short, and in our run a cap of three produced three attempts.

  3. 3. Why give --report_prefix an absolute path?

    • A relative path is resolved inside garak’s data directory — Right.
    • Absolute paths are faster
    • It is required by the licence
    • To hide the report

    Otherwise garak looks for your folder in its own data directory and fails.

  4. 4. Which file holds the individual failing attempts?

    • The hit log — Right.
    • The version file
    • The generator JSON
    • The config file

    The hit log lists the attempts that yielded a vulnerability.

Do it with FireAI

Put this lesson into practice on your own Mac.

Sources

Put it into practice on your Mac

Try every feature free for 17 days, no card needed.

Download for Mac Docs