SOC Analyst Labs

A prompt injection honeypot I built and run on my own server. It scores every prompt for injection attempts, blocks the risky ones, and logs everything so I can go back and see exactly what was tried.

SOC Analyst Labs

← Back to SOC Analyst Labs
Honey-AI project preview
Python

Honey-AI: LLM Injection Honeypot

I built Honey-AI to get hands on with prompt injection, not just read about it. It started as something running on my own machine and grew into a live server anyone can test. The build was the easy part. What I actually wanted was the review side, catching suspicious prompts, scoring them consistently, logging everything, and sitting down afterward to figure out what actually happened and why.

Try It Live

The left cards use my real Oracle server. The scorer on the right runs only in your browser.

Live Honey-AI Access (Oracle Host)

This is the real live Honey-AI environment running on my Oracle server at https://honeyai.catherinejason.com. I split the live access area into two cards so visitors can either review the API documentation first or open the live honeypot directly. Please do not enter personal information, because every message is scored and logged.

For visitor safety and GitHub Pages compatibility, both links open in a new tab.

FastAPI Docs

Open the live FastAPI documentation first if you want to review the exposed endpoint, request format, and test interface before sending prompts.

Open API Docs
Live Honeypot

Open the live Honey-AI honeypot to chat with Honey, a support assistant backed by a local model. Try a normal question first, then try a prompt injection and see how it responds.

Open Live Honey-AI Honeypot

Educational Browser Risk Scoring Demo

Simulated in your browser

This browser demo mirrors the same keyword based scoring logic used by the project, with the same six patterns as the live server. It runs as a local educational preview, so nothing you type is sent anywhere. It does not call the live backend yet, because browsers block an HTTPS page from calling an HTTP server. Once I add HTTPS to the Oracle host, this box can talk to the real honeypot.

No sample scored yet.

How This Came Together

Here's the quick version of how it went. I started with Ollama (a tool for running AI models locally) running a small local model, llama3.2:1b, so I had something to actually test against. Then I built a FastAPI backend with a chat endpoint to handle incoming messages, and wrote the risk scoring logic myself, checking each prompt against patterns like ignore previous instructions or reveal your system prompt. Every message gets logged two ways, to a plain text file and a SQLite database (a lightweight file-based database), so nothing gets lost and I can go back through it either way. On top of that I built a dashboard in Streamlit (a framework for building data dashboards) so I'm not just collecting data, I'm actually reviewing it, risk scores, trends, what got flagged and why. Once it was live and getting real traffic, I went back through the whole thing with a security review mindset, found gaps, and locked it down properly before calling it done.

How It Works

How It Works

The stack combines a FastAPI backend, a local Ollama model, SQLite logging, a Streamlit dashboard, and a text report generator. A prompt is submitted to the /chat endpoint, sent to a local Ollama instance running llama3.2:1b, and reviewed by a keyword based risk scoring function. Higher risk prompts are logged as security events, and the visitor does not see the model's reply for them.

I designed it to do two things at the same time. First, it gives me a safe place to study how users might try prompt injection against a local LLM. Second, it creates a monitoring trail that I can review through raw logs, a SQLite database, a Streamlit dashboard, and a text summary report.

  • FastAPI backend that accepts prompts and forwards them to a local Ollama llama3.2:1b model
  • Keyword-based scoring logic that detects common prompt override and jailbreak language
  • Dual logging to plain text files and a SQLite database for both quick review and structured analysis
  • Streamlit dashboard with summary metrics, recent events, and basic trend views
  • Plain-text reporting that summarizes prompt counts, high-risk events, critical events, and average risk score
  • Honey Support, a public demo chat that looks like a normal customer support assistant but scores and logs every message
  • Live API documentation, rate limiting, and an admin token (a secret credential that authorizes admin actions) for approving submitted findings, all hosted on Oracle Cloud

The project flow is intentionally simple and easy to audit. A client sends a prompt to the FastAPI /chat endpoint. The backend checks the message length and the rate limit, forwards the content to Ollama, scores the prompt for injection indicators, and decides whether the visitor gets the reply. It then writes the response and risk metadata to the standard chat log, copies higher risk events into a separate security log, stores the event in SQLite, and exposes that history to both the dashboard and the report generator.

Client (Honey Support demo page or API client)
  |
  v
FastAPI /chat endpoint (500 character limit, rate limit per IP)
  |
  +--> Ollama /api/generate (llama3.2:1b, Honey support persona)
  |
  +--> calculate_risk() + get_risk_level()
  |       |
  |       +--> response policy (score 50 or higher: reply withheld from visitor)
  |       +--> chat_log.txt
  |       +--> security_events.txt (risk score >= 50)
  |       +--> logs/honey_ai.db
  |                 |
  |                 +--> Streamlit dashboard
  |                 +--> report_generator.py -> report.txt
  1. Client request: a visitor submits a prompt from the Honey Support demo page, or an API client sends one to the chat endpoint.
  2. Input checks: FastAPI rejects messages over 500 characters and, by default, limits each IP address to 10 messages per hour.
  3. Model proxy: FastAPI sends the prompt to the local Ollama generate API with a short instruction that sets the Honey support persona.
  4. Risk review: the backend normalizes the text, checks it for prompt injection phrases, and assigns a score plus a severity label.
  5. Response policy: at a score of 50 or higher, the visitor sees a notice instead of the model's reply. The original reply is still saved so I can review it.
  6. Log handling: every event is written to chat_log.txt, and higher risk events are copied to security_events.txt.
  7. Structured storage: the same event is stored in logs/honey_ai.db so it can be queried later.
  8. Analyst visibility: the Streamlit dashboard uses the stored data for metrics, daily counts, and recent event review.
  9. Reporting: the report generator creates a plain text summary that can be saved with the rest of the project notes.
Risk Scoring Methodology

The current logic is intentionally lightweight. Each suspicious pattern adds 25 points, each pattern is counted once no matter how many times it appears, and the total is capped at 100. A prompt that matches four or more patterns still receives a score of 100. That makes the scoring easy to explain, easy to test, and easy to tune later if I want to expand the pattern list.

Pattern checked Why it matters Score impact
ignore previous instructions (also disregard, forget, or override instructions, rules, or guidelines) Classic attempt to override the existing prompt or safety context +25
reveal system prompt (also show or leak a hidden or secret prompt) Direct effort to exfiltrate hidden model instructions +25
developer mode (also dev mode) Common phrasing used to push a model into a less restricted state +25
jailbreak Explicit attempt to bypass guardrails or normal controls +25
bypass safety (also disable or turn off the safety) Attempt to switch off the model's safety behavior +25
bypass restrictions (also disable or turn off restrictions, filters, or guardrails) Attempt to remove the limits and filters around the model +25
  • Low: 0 to 24
  • Medium: 25 to 49
  • High: 50 to 74
  • Critical: 75 to 100
  • Security event logging threshold: prompts scoring 50 or higher are written to security_events.txt, and the visitor does not receive the model's reply

My first version matched exact phrases only. Live testing showed that adding one word to an attack got past it, so the current version lowercases the text, removes punctuation, collapses extra spaces, and matches close variants of each pattern. I then tested harmless questions, such as a password reset, to make sure the wider matching did not create false alarms.

Captured Attempts

Captured Attempts

Live counts from the honeypot database. Prompts are shortened and scrubbed.

Findings from Live Testing / Analyst Workflow

People figured out fast that if they reworded the attack, my first version of the detector missed it completely. I had to move from matching exact phrases to catching variations of them.

The model itself can't be trusted to protect itself once an injection reaches it. The real protection is the detector catching it before that point and the policy deciding what happens next.

A single low-score attempt can still slip through to the model, since keyword matching alone misses paraphrased attacks. That's a real gap, not just a theoretical one.

Screenshots

Screenshots

Honey Support chat showing blocked and logged risk prompts
The Honey Support chat. The High risk prompt was blocked, the hidden prompt one was logged as Medium, and the normal question got a normal answer.
Honey-AI API docs page showing endpoint access
The API docs page. The findings review endpoints are locked, and the public ones are open.
Honey-AI database events with scores and risk levels
The last 10 events logged in the database, with the score and risk level for each one.

The Build

The Build

Honey-AI is a research and education project. It started as a local only build, and the public demo now runs on a separate Oracle Cloud server that holds no real customer data, so a visitor can only ever reach a small chat model and its logs. Visitors are told that messages are logged and are asked not to enter personal information.

Controls in place: a 500 character message limit, a rate limit per IP address, an allowed websites list for browser requests, a switch that turns the public chat off without taking the rest of the site down, a switch that hides the API docs, an admin token required to approve submitted findings, and secrets kept out of the repository. The demo page also shows model replies with safe page building methods so a reply cannot run code in a visitor's browser.

Known limits: the API response includes the risk score and matched patterns, which an attacker could use as feedback. That gives an attacker feedback to refine their next attempt, similar to knowing exactly which alarm sensor they tripped.

Setup & Environment

The public demo runs on an Oracle Cloud free tier virtual machine (Ampere ARM, 1 OCPU (Oracle's virtual CPU unit), 6 GB of memory) with Oracle Linux 9. Ollama serves the llama3.2:1b model on the same machine, and the FastAPI app runs under uvicorn (the server program that runs FastAPI) as a systemd (the Linux service manager) service called honeyai, so it starts on boot and restarts if it stops. Settings such as the model name, allowed websites, rate limit, and the docs switch come from environment variables (settings passed to software outside the code), and the real .env file is never committed. I develop and test in VS Code, push to a private GitHub repository, then pull and restart the service on the server. Along the way I used Claude and GitHub Copilot as resources to help write and debug code.

Challenges

SELinux (Linux security controls) would not let systemd run the executables in my virtual environment until I relabeled them. A page on HTTPS cannot call an HTTP server, which is why the browser demo still scores locally (a mixed content issue, where a secure page calls an insecure server). The hardest part was that a 1B model drifts under injection, so the honeypot has to assume the model will not defend itself.

Security Considerations

Because the honeypot is public, I limited message length, rate limited each IP address, restricted which websites can call the API, added a switch to turn the chat off, and required an admin token for approving findings. Model replies are rendered without HTML injection. The database and logs stay on the server and out of GitHub. The main open items are HTTPS and the fact that scores are visible in direct API responses.

Lessons Learned

Exact phrase matching breaks the moment someone changes one word, so that was the first thing I had to fix. Any detector also needs to be tested against normal, harmless prompts, not just attacks, or it ends up flagging things it shouldn't. Showing the risk score back to the user is a tradeoff I'm still thinking through. And honestly, half of what I learned building this wasn't about detection logic at all, it was about the deployment and access control side, which turned out to matter just as much.

Skills Demonstrated

Skills Demonstrated

Prompt Injection Detection FastAPI LLM Security SQLite Streamlit Dashboards SOC Monitoring Design Python Cloud Deployment (Oracle Cloud) Linux and systemd API Security and Rate Limiting Detection Tuning
↑ Top