Mindket

Red team your own LLM app: Promptfoo, garak and PyRIT, what to test and how to read the results

A black banner titled "AI security" over the line "Prompt injection, jailbreaks and red teaming".

Red teaming an LLM app means attacking it yourself with generated adversarial inputs before someone else does. Promptfoo, NVIDIA's garak and Microsoft's PyRIT are open-source tools that generate the attacks, run them against your app and report which ones worked. Start with a short description of what the app is for, run a scan, then read the failures one by one.

In this lesson

  • Write the app's purpose in two sentences before any scan, since the generated attacks follow it.
  • Run scans against a staging copy that holds test data and test permissions only.
  • Read the log behind each failure and ask whether your app could cause the damage shown.
  • Keep one label per target and run the scan again after each fix.
All courses
On this page
  1. Three open-source red team tools
  2. Red team an app with Promptfoo
  3. What to test
  4. Add the plugins from lessons 1 and 2
  5. Pick attack strategies
  6. The same job with garak or PyRIT
  7. Read the results
  8. Test safely
  9. Common mistakes
  10. Try it yourself
  11. Next course: AI evals
  12. Check yourself
  13. Frequently asked questions
  14. Sources

Three open-source red team tools

Red teaming is attacking your own system before someone else does. For an LLM app that means feeding it adversarial inputs, far more than you would write by hand, and checking which ones make it misbehave. Three open-source tools automate the loop.

Promptfoo's README says it is now part of OpenAI and remains open source and MIT licensed. garak is NVIDIA's scanner, and its README compares it to nmap and Metasploit, but for LLMs. PyRIT comes from the Microsoft AI Red Team and a community of contributors. They overlap, so start with one.

Read on 6 November 2026 in the three READMEs and PyRIT's scanner page.
ComparedPromptfoogarakPyRIT
Installnpx promptfoo@latest, npm, brew or pippython -m pip install -U garakpip install pyrit, with Python 3.11 to 3.14
How you drive itA web setup, then the redteam run and redteam report commandsOne command naming a target and a probe familyThe pyrit_scan and pyrit_shell commands, a browser GUI or Python code
What a scan isPlugins that generate attacks, wrapped in strategiesProbes that send prompts, and detectors that judge the repliesA scenario run against a target, with a configuration
What you readA report with categories, severity levels and logsFAIL rows with failure rates, a log and a JSONL reportThe scenario's results, as the scanner reports them

Red team an app with Promptfoo

Promptfoo needs Node.js 22.22.0 or later. An OpenAI API key is optional. The attacker model that writes the attacks is set by redteam.provider and defaults to openai:gpt-5, and with no OpenAI key the docs say Promptfoo proxies generation and grading requests to its own API. The scanner runs on your machine, so it can attack any endpoint your machine or network can reach.

An HTTP target looks like the config below, copied from the Getting started page. The label names the target in reports, so reuse it when you generate new configs for the same target. The purpose is optional, but the page says it significantly improves the generated test cases and the grading, so say who the user is and what they may reach. To skip the web UI, promptfoo redteam init --no-gui writes a starting config.

targets:
  - id: https
    label: 'travel-agent'
    config:
      url: 'https://example.com/generate'
      method: 'POST'
      headers:
        'Content-Type': 'application/json'
      body:
        myPrompt: '{{prompt}}'

purpose: 'The user is a budget traveler looking for the best deals. The system is a travel agent that helps the user plan their trip. The user is anonymous and should not be able to access any information about other users, employees, or other individuals.'
  1. Run npx promptfoo@latest redteam setup. It opens a web UI that asks questions about the project.
  2. On Application Details, fill in the Purpose field at a minimum. Load Example, at the top of the page, gives you a quick try.
  3. Configure the target: an HTTP endpoint, a model or your own code.
  4. Select plugins. Plugins are adversarial generators that produce the malicious inputs. If in doubt, stick with the Default preset.
  5. Select strategies, the techniques that wrap the generated inputs in an attack pattern.
  6. Review and save the file as promptfooconfig.yaml, then run npx promptfoo@latest redteam run in that folder. It generates several hundred adversarial inputs, saves them in redteam.yaml and runs them against the target.
  7. Run npx promptfoo@latest redteam report to open the results.
A walkthrough from the Promptfoo channel on YouTube.

What to test

Promptfoo's plugins page recommends starting with a limited set of plugins to get a baseline, then adding more as you learn where the model is weak. More plugins mean longer runs and more inference. For an app with agents or retrieval, it recommends testing for application-level vulnerabilities, with the excerpt below. The comments are Promptfoo's.

Two plugins from the earlier lessons belong on your list as well: indirect-prompt-injection, from lesson 1, and prompt-extraction, from lesson 2. Each takes a config field of its own.

plugins:
  - 'agentic:memory-poisoning' # Tests if stateful agents are vulnerable to memory poisoning attacks
  - 'rbac' # Tests if the model properly implements Role-Based Access Control
  - 'bola' # Checks for Broken Object Level Authorization vulnerabilities
  - 'bfla' # Tests for Broken Function Level Authorization issues
  - 'ssrf' # Tests for Server-Side Request Forgery vulnerabilities
  - 'sql-injection' # Tests for SQL injection vulnerabilities (if connected to a SQL database)
  - 'pii' # Checks for leakage of Personally Identifiable Information
  - 'excessive-agency' # Checks if the agent exceeds its intended capabilities
  - 'hijacking' # Checks for goal hijacking of the agent's objectives
  - 'tool-discovery' # Tests if the model reveals its available function calls or tools
Promptfoo's plugins page, read on 6 November 2026.
LLM designTests that do not apply
Foundation modelSecurity and access control tests
Single user roleAccess control tests
Prompt and response onlyResource fetching and injection attacks

Add the plugins from lessons 1 and 2

Both plugins need extra config. Indirect-prompt-injection needs indirectInjectionVar, the name of the template variable that carries untrusted text, such as {{name}} in the travel agent prompt from lesson 1. Per its plugin page, Promptfoo injects adversarial payloads into that variable and fails a test if the model follows them. Prompt-extraction needs systemPrompt, the system prompt you gave the model, as lesson 2 showed and its plugin page requires.

The config below puts the two examples from those plugin pages together. Replace the placeholder with your real system prompt, and name your own untrusted variable.

prompts:
  - |
    You are a travel agent. The user's name is {{name}}.
    User query: {{query}}

redteam:
  plugins:
    - id: indirect-prompt-injection
      config:
        indirectInjectionVar: name
    - id: prompt-extraction
      config:
        systemPrompt: 'Paste the real system prompt of your app here.'

Pick attack strategies

Plugins write the attacks and strategies change how they are delivered. The strategies page recommends two for most apps: jailbreak:meta for single-turn attacks and jailbreak:hydra for multi-turn conversations. The configuration reference lists basic, jailbreak:meta and jailbreak:composite as the defaults, and generates 5 tests per plugin unless you set numTests.

redteam:
  strategies:
    - jailbreak:meta # Single-turn agentic attacks
    - jailbreak:hydra # Multi-turn adaptive conversations
  • Static strategies apply fixed transformations, such as base64 encoding. They cost little and are easy to detect, and the page says foundation models often patch them.
  • Dynamic strategies use an attacker model to refine an input over several attempts. They succeed more often and cost more. By default they stop after the token budget or after they produce a harmful output.
  • Multi-turn strategies work across a conversation. The page says they have the highest success rates, they suit stateful apps and they use more resources than single-turn strategies.

The same job with garak or PyRIT

garak is a command-line tool. By default it tries every probe it knows against the model you name, with the detectors each probe recommends. --spec narrows the run to a probe family such as probes.promptinject, or to one probe. For an app that is not a bare model, its REST generator can reach any endpoint that returns plaintext or JSON, with a short YAML file describing the endpoint.

PyRIT's scanner runs a scenario against a target, and scenarios bundle attack techniques, datasets and scoring. It ships six families: Adaptive, AIRT, Benchmark, Foundry, Garak and Technique. The Garak family includes SystemPromptExtraction. pyrit_scan suits CI and batch runs, and pyrit_shell suits interactive exploring. PyRIT needs your endpoints configured first, and its configuration page starts with three environment variables for an OpenAI chat target. The install page lists Python 3.11 to 3.14.

The commands below are examples from their docs: the garak README, and PyRIT's two scanner pages. The garak README asks you to replace the sample key with a real one.

# garak
python -m pip install -U garak
garak --list_probes
export OPENAI_API_KEY="sk-123XXXXXXXXXXXX"
python3 -m garak --target_type openai --target_name gpt-5-nano --spec probes.encoding

# PyRIT
pip install pyrit
pyrit_scan list-scenarios
pyrit_scan run foundry.red_team_agent --target openai_chat --initializers target --techniques base64

Read the results

Promptfoo's report shows vulnerability categories, severity levels, the logs of the inputs that triggered failures and suggested mitigations. Selecting a test case shows its raw input and output. Each vulnerability also gets a risk score from 0 to 10, built on CVSS principles, which the table turns into bands.

garak prints a progress bar for each probe, then one row per detector. A response marked FAIL means some attempts produced undesirable behavior, with the failure rate beside it. A figure such as 840/840 counts generations: the total, then how many seemed to behave OK. The count runs high because garak makes 10 generations per prompt by default. Errors go to garak.log, details go to a JSONL report, and analyse/analyse_log.py lists the probes and prompts with the most hits.

Open the log for each failure and check whether your app could do the damage the answer describes. A failure that depended on a tool you can remove is fixed by removing the tool, as the first fixes in lesson 3 say. Then run the scan again under the same label. Promptfoo grades its own results with grading requests, so a verdict you disagree with is a reason to read the log, and LLM as a judge shows how to check a grader.

Promptfoo's risk scoring page, read on 6 November 2026.
Risk scoreBandPromptfoo's wording, shortened
9.0 to 10.0CriticalRequires immediate attention
7.0 to 8.9HighShould be addressed promptly
4.0 to 6.9MediumNeeds investigation
0.1 to 3.9LowCan be monitored

Test safely

A scan sends hostile input to a running app, and it spends tokens. Our advice, with what the docs add:

  • Test an app you own, on a staging copy, with test data and an account that holds only test permissions. The scan tries to make the app act, and the excessive-agency plugin exists to find actions you did not intend.
  • Promptfoo's docs describe attack generation two ways. One passage says it uses your own OpenAI key for generation and grading, and proxies requests to its API if you have none. Another says it uses a remote service for generating adversarial inputs by default. Your target is always evaluated locally. Setting PROMPTFOO_DISABLE_REDTEAM_REMOTE_GENERATION to true forces 100% local generation, and the docs say its quality depends on the model you configure and is generally low for most models.
  • More plugins lengthen runs and need more inference. Dynamic strategies call both an attacker model and your target, and multi-turn runs track target, attacker and grading tokens separately. Keep numTests small while you tune the config.
  • In CI, promptfoo redteam run --tag ci.run-id="$CI_RUN_ID" --tag git.sha="$GIT_SHA" records the run and the commit with the results. Evals in CI covers running checks on every change.
  • If the app is an agent, run it in the sandbox and under the permission rules from agent guardrails first.

Common mistakes

  • Pointing a scanner at a production system or at an app you do not own. It runs from your machine and attacks whatever endpoint it can reach.
  • Leaving Purpose empty, then reading generic failures as findings about your app.
  • Reading a clean run as proof of safety. It shows that the attacks tried did not work. As lesson 1 covered, an attacker who adapts to your defense is a different test.
  • Taking a severity label as final without opening the log.
  • Giving the tested agent live credentials and real data.

Try it yourself

  • Run npx promptfoo@latest redteam setup, press Load Example on Application Details and click through the screens without running a scan.
  • Write two sentences of purpose for an app you own: who the user is and what they should not be able to reach.
  • Point a scan at a staging copy with the plugins from lessons 1 and 2, indirect-prompt-injection and prompt-extraction, plus the ones that fit your app.
  • Open the first failure and write down which OWASP entry from lesson 3 it belongs to, and which first fix would stop it.

Next course: AI evals

Red teaming shows how an app fails under attack. The next course, AI evals: measure whether your LLM app and agent work, turns the same idea into tests you can run on every change.

Check yourself

  1. Which field should you fill in at a minimum on the Application Details page of the Promptfoo setup?

    Show answer

    A. Purpose The page says to fill out Purpose with a description of your application, since more detail tailors the generated test cases.

  2. What does promptfoo redteam run do?

    Show answer

    D. Generates test inputs into redteam.yaml, then runs them against the target It generates several hundred adversarial inputs, saves them in redteam.yaml and runs them against the target.

  3. In garak output, what does a FAIL on a probe mean?

    Show answer

    C. Some attempts produced behavior the detector marks as undesirable If any attempt yielded undesirable behavior, the response is marked FAIL and the failure rate is given.

  4. What do the docs say about forcing local generation in Promptfoo?

    Show answer

    B. Its quality depends on your model and is generally low for most models Setting the environment variable forces 100% local generation, but the docs say its quality depends on the model you configure and is generally low for most models.

Frequently asked questions

What is red teaming for LLMs?

In AI, red teaming means testing a system with adversarial inputs to find where it fails: jailbreaks, prompt injection, data leaks and harmful output. The tools generate many inputs for each vulnerability type, run them against the target and grade the replies.

Which is the best tool to red team an LLM app: Promptfoo, garak or PyRIT?

Choose by workflow. A guided web setup with a report suits Promptfoo, a command-line probe scan suits garak, and a Python codebase suits PyRIT. All three are open source.

Can I run an LLM red team scan in CI?

Yes. Promptfoo's docs show tagging runs with promptfoo redteam run --tag, and PyRIT's docs describe pyrit_scan for CI/CD pipelines and batch processing.

Does a Promptfoo scan send my app's data anywhere?

It can. Attack generation may go through Promptfoo's API, and the pages read for this lesson do not detail what that service receives. Force local generation, or check first, before you test anything sensitive.

How often should I red team an LLM app?

Promptfoo's docs call red teaming an ongoing process and advise running it regularly as the app changes. Running it again after a change to prompts, tools or models is a sensible rule of thumb.

Sources

  1. GitHub: Promptfoo repository (read November 6, 2026)https://github.com/promptfoo/promptfoo
  2. GitHub: Promptfoo, red team getting started (read November 6, 2026)https://github.com/promptfoo/promptfoo/blob/main/site/docs/red-team/quickstart.md
  3. GitHub: Promptfoo, red team configuration (read November 6, 2026)https://github.com/promptfoo/promptfoo/blob/main/site/docs/red-team/configuration.md
  4. GitHub: Promptfoo, plugins (read November 6, 2026)https://github.com/promptfoo/promptfoo/blob/main/site/docs/red-team/plugins/index.md
  5. GitHub: Promptfoo, strategies (read November 6, 2026)https://github.com/promptfoo/promptfoo/blob/main/site/docs/red-team/strategies/index.md
  6. GitHub: Promptfoo, risk scoring (read November 6, 2026)https://github.com/promptfoo/promptfoo/blob/main/site/docs/red-team/risk-scoring.md
  7. GitHub: Promptfoo, indirect prompt injection plugin (read November 6, 2026)https://github.com/promptfoo/promptfoo/blob/main/site/docs/red-team/plugins/indirect-prompt-injection.md
  8. GitHub: Promptfoo, prompt extraction plugin (read November 6, 2026)https://github.com/promptfoo/promptfoo/blob/main/site/docs/red-team/plugins/prompt-extraction.md
  9. GitHub: NVIDIA garak repository (read November 6, 2026)https://github.com/NVIDIA/garak
  10. GitHub: Microsoft PyRIT repository (read November 6, 2026)https://github.com/microsoft/PyRIT
  11. GitHub: PyRIT scanner (read November 6, 2026)https://github.com/microsoft/PyRIT/blob/main/doc/scanner/0_scanner.md
  12. GitHub: PyRIT scan command (read November 6, 2026)https://github.com/microsoft/PyRIT/blob/main/doc/scanner/1_pyrit_scan.ipynb
  13. GitHub: PyRIT local installation (read November 6, 2026)https://github.com/microsoft/PyRIT/blob/main/doc/getting_started/install_local.md
  14. GitHub: PyRIT configuration (read November 6, 2026)https://github.com/microsoft/PyRIT/blob/main/doc/getting_started/configuration.md
  15. YouTube: Red Team an AI App with Promptfoo (Promptfoo channel) (read November 6, 2026)https://www.youtube.com/watch?v=e7MlDhfN22s

Share this lesson

Turn the scan into a test you run every time

The AI evals course shows how to build a test set from failures and run it on every change.

What are LLM evals?

This lesson as Markdown · AI security: prompt injection, jailbreaks and red teaming · All courses