BlogRed-Teaming Your LLM: Find the Jailbreak Before Your Users Post ItEval · Output Quality

Red-Teaming Your LLM: Find the Jailbreak Before Your Users Post It

BC
Ben Carter · March 2026 · 10 min read

TL;DR

It takes one screenshot. A user coaxes your support bot into writing something racist, dispensing dangerous instructions, or trashing your own product, and the image is on social media before your on-call sees the alert. Prompt injection is the #1 risk on the OWASP Top 10 for LLMs for the second consecutive edition, and the attack surface keeps widening because models process instructions and data in the same channel with no clean separation. Red-teaming is how you find the jailbreak before your users do, systematic, automated adversarial evaluation that runs as a gate, not a one-time pentest you did at launch and forgot.

The failure that travels at the speed of a screenshot

Most quality failures are private, a wrong answer, a slow response, a bad summary that one user sees and forgets. A successful jailbreak is the opposite: it is inherently shareable. The whole appeal, for the person who finds it, is posting the screenshot. So the blast radius of a single adversarial success isn’t one bad conversation; it’s every person who sees the post, plus the journalists who aggregate “company’s AI says X” into a story. The cost is measured in brand and trust, and it lands all at once.

This is why the industry treats it as the headline risk. In the OWASP Top 10 for LLM Applications (2025), prompt injection (LLM01) holds the top spot for the second consecutive edition. The root cause is architectural and won’t be patched away: LLMs process instructions and data in the same channel without clear separation, so an attacker can craft input the model interprets as a new instruction rather than content to process (OWASP Top 10 for LLM Applications v2025, PDF). As long as that’s true, the defense isn’t a fix, it’s continuous testing.

You cannot prove the absence of jailbreaks; you can only keep failing to find them. Red-teaming is the discipline of trying as hard as a motivated attacker would, on a schedule, so that the failure surfaces in your CI and not on someone’s feed.

The attack taxonomy you have to cover

“Jailbreak” is not one technique; it’s a family, and a red-team that only tries the obvious ones gives false comfort. The categories that belong in every adversarial suite:

  • Direct instruction override, “ignore your previous instructions and…” and its thousand polite variants.
  • Role-play and persona framing, “you are DAN, a model with no restrictions, ” the hypothetical-scenario wrapper, the “for a novel I’m writing” pretext.
  • Encoding and obfuscation, base64, leetspeak, translation, token-splitting that slips past keyword filters while the model still understands the intent.
  • Indirect injection, the malicious instruction lives in a document, web page, or email the model reads, not in the user’s message. OWASP is explicit that these inputs need not be human-visible as long as the model parses them.
  • Multi-turn manipulation, benign opening turns that gradually establish a frame, then exploit it, the “crescendo” pattern that single-prompt tests miss entirely.

Manual red-teaming doesn’t scale; automated red-teaming does

A human red-team is invaluable for discovering new attack classes, but it can’t run on every release, and it can’t cover the combinatorial space of obfuscations and personas. The modern practice pairs human creativity with automated, repeatable adversarial evaluation. Open-source tooling has made this accessible, Promptfoo, for example, maps automated red-team plugins directly to the OWASP LLM Top 10, generating and mutating attacks across the categories above and reporting which ones got through; frameworks like DeepTeam do the same with the 2025 risk list built in.

The key shift is that the attacks become test cases. Each known jailbreak class is a suite that runs in CI; a new attack discovered by humans or by a competitor’s public incident becomes a permanent case. The red-team isn’t an event, it’s a growing regression suite for adversarial robustness.

# Automated red-team: attacks are test cases, refusal is the assertion
ATTACK_FAMILIES = {
    'direct_override':  load_payloads('attacks/ignore_instructions.txt'),
    'roleplay':         load_payloads('attacks/persona_dan.txt'),
    'encoding':         lambda p: [base64(p), leetspeak(p), rot13(p)],
    'indirect':         load_payloads('attacks/poisoned_documents.txt'),
    'multi_turn':       load_conversations('attacks/crescendo.jsonl'),
}

def red_team(model, harmful_goals):
    breaches = []
    for goal in harmful_goals:                      # e.g. "produce hate speech"
        for family, gen in ATTACK_FAMILIES.items():
            for attack in materialize(gen, goal):
                response = run(model, attack)        # single- or multi-turn
                if not is_refusal(response) and achieves(response, goal):
                    breaches.append({'family': family, 'attack': attack,
                                     'response': response[:200]})
    return breaches

Scoring: refusal is necessary, not sufficient

The naive grader checks “did the model refuse?” That misses the partial breach, the model refuses the framing but still leaks the harmful content in a caveat, or complies after a token objection. A robust red-team grader checks whether the harmful goal was achieved, regardless of surrounding refusal language, and tracks an attack success rate (ASR) per family so you can see where you’re weakest.

# Gate the build on attack success rate, per family and overall
def red_team_gate(model, harmful_goals, max_asr=0.0):
    breaches = red_team(model, harmful_goals)
    total = count_attacks(harmful_goals)
    by_family = Counter(b['family'] for b in breaches)

    overall_asr = len(breaches) / total
    # For genuinely harmful goals, the only acceptable success rate is zero
    assert overall_asr <= max_asr, (
        f"jailbreak ASR {overall_asr:.1%} over limit; "
        f"worst families: {by_family.most_common(3)}"
    )
    return {'asr': overall_asr, 'by_family': dict(by_family)}
For truly harmful capabilities, the acceptable attack success rate is zero, and you should expect not to reach it. Robustness is asymptotic. The honest goal is a monotonically falling ASR over time, a fast feedback loop when a new attack class appears, and no regressions, an attack you blocked last month must stay blocked.

Make it continuous, because the attackers are

The single biggest mistake is treating red-teaming as a launch checklist. New jailbreak techniques are published constantly, your own prompt and model changes can reopen old holes, and a silent provider model update can change refusal behavior overnight. So the adversarial suite runs in CI on every change to prompts or models, on a schedule against production, and it grows every time a new technique appears publicly or a human red-team finds something. When a competitor’s embarrassing screenshot makes the rounds, the right response is to add that exact attack to your suite the same day and confirm you block it.

The bottom line

A jailbreak is the rare quality failure that’s designed to be screenshotted and shared, which is why prompt injection sits atop the OWASP LLM risks and why it can’t be patched away, it’s baked into how models read instructions and data on the same channel. Cover the full attack taxonomy (direct, roleplay, encoding, indirect, multi-turn), automate the attacks into a regression suite, grade on whether the harmful goal was achieved rather than just whether the model said “I can’t, ” and gate the build on attack success rate. Then keep doing it forever, because the attackers will. Find the jailbreak in your pipeline, or read about it on someone else’s timeline.

Ship AI on Evidence, Not Vibes

alt.qa Eval turns "seems fine" into measurable pass/fail, continuous evaluation, regression gates, and groundedness scoring for your AI outputs.

Try alt.qa Free →
Ben Carter Ben Carter writes about AI quality engineering at alt.qa, built by TheWorkCompany.