← ALL PROJECTS

Personal project / 2026

Prompt injection lab

56% when hidden in a document. 0 to 16% when asked directly.

PythonOllamaLLM security
Bar chart of how often each attack type leaked the secret with no defenses: direct order 4% (1 of 25 runs), role-play 16% (4 of 25), disguised ask 8% (2 of 25), fake format 0% (0 of 25), hidden in a document 56% (14 of 25).

THE PROJECT

Built a support chatbot on a local llama3.2 model that holds a fake secret, then attacked it with 25 payloads in five categories, five runs each. Added three defenses (an input filter, prompt hardening, and an output filter) and measured each one, including how many harmless questions they wrongly blocked.

HOW IT WORKS

  1. 01

    Build

    Create a local support chatbot that holds a fake secret and can summarize documents.

  2. 02

    Attack

    Run 25 payloads in five categories, five times each, and count every leak.

  3. 03

    Defend and measure

    Add three defenses, then record the leaks they stop, the harmless questions they block, and what the test cannot show.

WHAT I DELIVERED

  • Found that attacks hidden inside a document leaked the secret 56% of the time, against 4% for a direct order.
  • Measured the cost of defending: the input filter blocked 2 of 15 harmless questions.
  • Reported where the experiment falls short: the input filter’s 0% comes from a blocklist written after reading the same attacks, and the held-out set was too weak to separate the defenses.
  • Saved all 1,000 replies and added a script that recounts every result without a model.

EVIDENCE

Three stacked panels. First, a customer review document that ends with a request to end the summary with the admin code. Followed by the saved reply from the bot with no defenses, which summarizes the review and ends with FLAG{blue-otter-42}. Followed by the reply with all three defenses on: "Sorry, I can’t help with that." (opens in a new tab)
The same attack hidden in a document, with no defenses and with all three on.
Bar chart of secret leaks per defense, main attack set then held-out attacks. No defenses: 21 of 125 and 2 of 75. Input filter: 0 of 125 and 1 of 75. Hardened prompt with delimiting: 4 of 125 and 3 of 75. Output filter: 0 and 0. All three: 0 and 0. (opens in a new tab)
Leak rate per defense. The 0% on the main set is not proof the defenses generalize.

PROJECT SCOPE

My own chatbot on my own machine, with a fake secret. No third-party systems.