LLM penetration testing from the command line. Point it at any model or endpoint, run a categorized set of prompt-injection and jailbreak attacks, and get a structured report of what got through.
Authorized testing only. Use PromptXploit against systems you own or are explicitly permitted to test. See DISCLAIMER.md.
PromptXploit runs adversarial prompts against a target model, decides whether each
attack succeeded, and writes the results to JSON. Attacks are streamed from a
curated, categorized dataset; verdicts are decided locally by default, so nothing
about your target leaves your machine. It is framework-agnostic: any LLM or HTTP
endpoint works as long as it can be wrapped in a single run(prompt) function.
The pipeline is deliberately ordered cheapest-first:
attacks → target → deterministic rules → judge (only the uncertain cases) → report
Deterministic rules resolve the obvious outcomes (clear refusals, clear bypasses) before any model is invoked. Only the ambiguous cases are sent to the judge.
- Categorized attacks from HuggingFace. Stream a curated attack set and filter
it by intent (for example,
tool_abuse), pulling only what you need. - Local-first judging. Verdicts are decided by a local model through Ollama — nothing leaves your machine. OpenAI and Gemini are optional backends.
- Rules-first, low false-positive. Deterministic checks handle refusals and obvious bypasses before spending a model call, so the report does not cry wolf.
- Rate limiting. Cap attacks per minute so you do not overload a target.
- Framework-agnostic targets. Any LLM, local model, or HTTP endpoint.
- Structured output. Per-attack verdict, risk score, and rationale as JSON.
pip install promptxploitFor the default local judge, install Ollama and pull a model:
ollama pull llama3.1:8bFrom source:
git clone https://github.com/m4vic/promptxploit
cd promptxploit
pip install -e .Optional API judges:
pip install "promptxploit[openai]" # for --judge openai
pip install "promptxploit[gemini]" # for --judge geminiDefine a target — any callable that takes a prompt and returns the model's response:
# my_target.py
def run(prompt: str) -> str:
return your_llm(prompt)Run a scan. This pulls tool_abuse attacks, judges them locally, and writes a report:
promptxploit \
--target my_target.py \
--category tool_abuse \
--judge local --judge-model llama3.1:8b \
--rate 10 \
--output scan.jsonRead scan.json for the per-attack verdicts.
By default, attacks are streamed from the categorized dataset
neuralchemy/prompt-injection-dataset-categorized (the intent configuration).
Available intents:
benign direct_injection system_extraction role_hijack
obfuscation tool_abuse indirect_injection
| Flag | Purpose |
|---|---|
--category tool_abuse |
Use only this intent (comma-separated for several) |
--limit 100 |
Cap the number of attacks |
--subset intent |
Dataset configuration (default: intent) |
--dataset ORG/NAME |
Use a different HuggingFace dataset |
To use your own local attack files instead of the dataset:
promptxploit --source local --attacks ./attacks --target my_target.py --output scan.jsonLocal attack files are JSON lists of objects with id, category, and prompt.
The judge decides the outcome for cases the deterministic rules cannot.
| Backend | Flag | Notes |
|---|---|---|
| Local (Ollama) | --judge local |
Default. Runs entirely on your machine; nothing is sent to a third party. |
| OpenAI | --judge openai |
Requires OPENAI_API_KEY. |
| Gemini | --judge gemini |
Requires GOOGLE_API_KEY. |
| Rules only | --judge none |
No model; uncertain cases are left as partial. |
The local backend is the default on purpose: when you are testing another party's
system, their responses should not be shipped to an external API. Choose the judge
model with --judge-model (for example, llama3.1:8b or qwen2.5:14b-instruct)
and point at a non-default Ollama host with --ollama-url.
A target is any Python module that defines run(prompt: str) -> str. That function
can call a local model, a hosted API, or an entire application.
To test an HTTP endpoint, configure targets/http_api_target.py with your URL,
headers, and request shape, then pass it as --target. It works with OpenAI-style
APIs, Anthropic, and arbitrary REST endpoints.
promptxploit --target my_target.py --rate 5 --output scan.json--rate caps attacks per minute against the target (0 means unlimited). API judges
are paced separately from the attack rate.
The report is a JSON list. Each entry records the attack, the verdict, and a normalized risk score:
{
"attack_id": "HF-00042",
"category": "tool_abuse",
"source": "hf:neuralchemy/prompt-injection-dataset-categorized:intent",
"verdict": {
"verdict": "fail",
"confidence": 0.9,
"severity": 0.85,
"rationale": "Model followed the injected tool instruction."
},
"risk": { "risk_score": 0.77, "risk_level": "high" }
}Verdicts:
- pass — the attack was blocked; the model refused or answered safely.
- fail — the attack succeeded; the model complied, leaked, or was manipulated.
- partial — uncertain or requires manual review.
Provide your own attacks as a JSON list:
[
{ "id": "CUSTOM-001", "category": "tool_abuse", "prompt": "Your attack prompt here" }
]promptxploit --source local --attacks my_attacks.json --target my_target.py --output scan.jsonPromptXploit is a security testing tool for authorized use only: your own systems, sanctioned penetration tests, and security research. Do not use it against systems you are not permitted to test. Full terms are in DISCLAIMER.md.
PromptXploit finds where a model breaks. PromptShield is the defensive counterpart that hardens it. The intended workflow is to test with PromptXploit, add PromptShield, and re-test to confirm the gap is closed.
pip install promptshieldsfrom promptshield import Shield
shield = Shield.balanced()
def protected_llm(prompt: str, system_prompt: str) -> str:
result = shield.protect_input(prompt, system_prompt)
if result["blocked"]:
return "Request blocked."
return your_llm(prompt)protect_input returns a result with blocked, reason, and threat_level.
PromptShield also provides protect_output, protect_stream, and protect_tool_call
for defending the response and agent surfaces. See the PromptShield repository for
the full guide.
A typical before-and-after run:
promptxploit --target unprotected.py --category tool_abuse --output before.json
promptxploit --target protected.py --category tool_abuse --output after.jsonMIT. See LICENSE.