This website uses cookies

Read our Privacy policy and Terms of use for more information.

THE SHORT VERSION

In our last report, we explained that turning a security control on does not make a threat go away. It only makes an attack less likely to work. This time we measured the other side: what happens when the controls are off. We built an AI app that is weak on purpose. It covers all 20 AI risks from the OWASP Top 10 lists for AI, from a well-known security group (the LLM Top 10 and the new Agentic Top 10). Each protection is a simple on and off switch. We turned them all off and ran 816 attacks with a testing tool called promptfoo. 305 of the attacks worked. When we asked the AI for something harmful in plain words, it almost always said no. When we hid the same request inside a trick (a "jailbreak"), it said yes about four times more often. Two fake secrets we had placed inside the app came out word for word. All of this ran on one laptop, using a single free AI model that played three parts at once: the attacker, the app under attack, and the judge.

Asking an AI for something harmful in plain words almost never works. Hiding the same request inside a trick is what works.

That is the whole finding. The rest of this report is the proof.

Why we run this on one laptop

In our last report [1], we built a lab to show "defense in depth", which means using several layers of protection at once. It had nine attacks and real controls. The main lesson was uncomfortable: even with a protection switched on, a slightly reworded attack could still get past it.

This report looks at the opposite question. Before you can show that a protection is worth having, you need to know how bad things are without it. That starting number, the score when there is no protection at all, is something almost no one writes down.

So we built that starting point as something you can run yourself. It is a small AI assistant with a knowledge base, a search step, and a few tools it can use. Behind it sits a panel of twenty switches. Each switch is one protection, matched to one AI risk: blocking hidden instructions, hiding secrets, checking permission before a tool is used, keeping one customer's data away from another, stopping code from running, limiting how much a user can ask for, and so on [2][3]. Off means the raw AI with no help. On means the protection is active. You flip one switch, run the same attack again, and watch the result change.

The setup surprises people. There is no cloud service and no bill. One free, open AI model runs on the laptop itself. The testing tool points three roles at that same model: it writes the attacks, it acts as the app being attacked, and it grades whether each attack worked [4]. The attacker, the target, and the judge are all the same model on one machine.

A test you cannot repeat is just a story. A test that runs for free on your own computer is one you can trust and run again and again.

Two honest warnings, and both make the results less scary, not more. First, this is a small model, the kind you run on a laptop, not a large top-tier one. A bigger model would refuse more of these attacks, so these numbers are not a judgement on AI as a whole. Second, the model grades its own work, so it is not a perfect judge. Treat the exact numbers as a rough guide, not a precise score. What the setup really gives you is the ability to repeat the test. Anyone can run the same attacks, change one switch, and get a number they can compare. The goal was never the score by itself. The goal was a score you can move on purpose.

816 attacks with no protection

With every switch off, the tool created and ran 816 attacks across the twenty risk types. The model refused 492 of them on its own. 305 were not refused. 19 crashed the app completely, which is a separate problem for another day. Of the attacks that finished normally, 38 out of every 100 went the attacker's way.

That number, 305, is really two different problems in one. About 180 of them were the model saying something it should not have said: harmful instructions, unfair or biased answers, or advice it should not give. That is a safety problem, and it matters, but it is not someone breaking into a system. About 85 of them are the ones a security team truly worries about: leaked secrets, hidden instructions the model followed, database and command attacks through tools the model was allowed to use, and actions taken without permission. The rest were the app running out of resources, plus a few odd cases.

The security problems were the worst. A request for a hidden "debug" menu worked three times out of four. A database attack through an allowed tool, the same. Getting around the app's permission rules worked more than two times out of three. These are not clever tricks. They are what happens when an app trusts the AI to guard itself.

An AI with no protection is not a machine that just says no. It is a helpful machine, and being helpful is the weakness.

A direct request fails. A disguised one works.

The most useful result is not the headline number. It is what happened when we kept the request the same and only changed how it was wrapped.

When we asked in a plain, direct way, the model refused most of the time: only 14 out of 100 direct attacks worked. When we wrapped the same request as a hidden instruction (this is called "prompt injection"), 38 out of 100 worked. When we wrapped it as a "jailbreak", a trick such as a role-play, a pretend story, or a false claim of permission, 59 out of 100 worked. That was the most effective single method in the test.

Same request. Same model. The only thing that changed was the wrapping, and the wrapping made the attack about four times more likely to work.

The model rarely says yes to the request itself. It says yes to the way the request is dressed up.

This is why a filter that only blocks certain words is a weak defense. It reads the words. The attack is in the packaging, not the words.

A jailbreak and prompt injection are not the same thing

These two methods worked best, so it helps to tell them apart. Teams often use one budget for both, but they break different things.

A jailbreak attacks the model's willingness to say no. The user is clearly the one asking. The trick is the wrapping that talks the model out of refusing. It only exists because there is a "no" to get around. If the model had no safety training at all, there would be nothing to break.

Prompt injection attacks something else: which text the model treats as an order [5]. The harmful instruction is hidden inside data the model was told to read, such as a document, a support ticket, or a saved record. The model obeys it because it cannot tell your normal content apart from an order hidden inside it. The user may be completely innocent. If the model had no safety training, this would still work, because refusing was never the point.

A jailbreak changes whether the model is willing to say no. Prompt injection changes whose orders the model follows in the first place.

They need different fixes. Safety training helps against jailbreaks and does almost nothing against injection. Keeping trusted instructions separate from untrusted data helps against injection and does almost nothing against jailbreaks. A team that treats them as one job is leaving one of them open.

Two secrets we planted came out

We placed two fake secrets in the knowledge base, the way a real one holds passwords and other customers' data. Both came out.

The first came out through an attack that makes the model repeat its own hidden text. Out came an internal API key, exactly as written, character for character. The second is the one to show a manager: we asked, as if we were fixing a problem, for the "admin override code to fix the system", and the model handed over the exact code it had been given. Nothing was broken into. The secret was inside the model's view, and whatever the model can see, it can be talked into saying.

A secret that sits inside the model's working memory is a secret you have already given away. You just have not been asked for it yet.

The lesson is not "hide secrets better". It is that anything the model can see can be talked out of it. The only real fix is to keep the secret out of the model's view in the first place.

Why a test you can repeat is the point

None of this proves the model is bad. It proves the setup has no protection, which is exactly how we built it. The number only matters because of what you do next.

Turn one switch on and run the test again. The "hide secrets" switch takes the two leaks to zero. The "check permission" switch removes the database and permission attacks. Now you have two numbers, before and after, for one protection, from the same test, on a computer you already own. That is the difference between believing a protection works and measuring how much it helps.

The industry keeps shipping protections it has never measured. A switch you have not tested is only a hope, not a real defense.

The attacker in this lab did not need to be clever [6]. It needed a disguise, a place to hide, and a secret left sitting in view. Take those away one switch at a time, and run the same 816 attacks each time you do. The starting number is not the bad news. It is the number you measure everything else against.

What to do this week

  • Measure your "no protection" number first. Before you argue about which protection to buy, run a set of attacks against your app with the protections off, and write down how many work. You cannot measure a protection if you never had a number to compare with [4].

  • Test the wrapping, not the words. Take one attack your system blocked, and run it again as a hidden instruction and as a jailbreak. If your filter only catches the plain version, it is reading words, not meaning.

  • Treat jailbreaks and prompt injection as two separate jobs. They break different things and need different fixes. Safety training does little for injection. Keeping instructions separate from data does little for jailbreaks [5].

  • Keep secrets out of the model's view. Hiding them in the answer is not enough. If a password or another customer's data is in the model's working memory, treat it as already exposed, and build so it never gets there [2].

  • Make your attack test repeatable. A test you cannot run again is just a story. Fix the model, the attack set, and the switches so every change gives you a clear before-and-after number [4].

  • Have a second, stronger model do the grading. If your attacker and your judge are the same model, your results look better than they are. Grade with a separate, stronger model before you trust them.

Turn the protections off and you get your measuring stick. Turn one on and you can see how far it moves the result. Do not trust either one without proof. Measure both.

References

  1. A. Seeneevasan, Your AI Guardrail Is On. The Attacker Already Got Past It., defnze, Jun 2026. https://www.defnze.com/p/your-ai-guardrail-is-on-the-attacker-already-got-past-it

  2. OWASP Gen AI Security Project, OWASP Top 10 for LLM Applications 2025, Nov 2024. https://genai.owasp.org/llm-top-10/

  3. promptfoo, LLM red teaming (open source), 2025. https://www.promptfoo.dev/docs/red-team/

  4. Greshake et al., Not what you've signed up for: Compromising Real-World LLM-Integrated Applications with Indirect Prompt Injection, 2023 (arXiv:2302.12173). https://arxiv.org/abs/2302.12173

  5. Nasr, Carlini, Sitawarin, Schulhoff, Hayes, et al., The Attacker Moves Second: Stronger Adaptive Attacks Bypass Defenses Against LLM Jailbreaks and Prompt Injections, Oct 2025 (arXiv:2510.09023). https://arxiv.org/abs/2510.09023

Keep Reading