What it detects
Offline "lethal trifecta" analyzer for an AI agent's toolset.
An agent can be made to leak data by prompt injection when one session can do all three of these: (P) read private data, (U) take in untrusted content, and (E) send data out. A good example is a filesystem MCP server, a fetch tool and a send_email tool loaded in the same client. No single server looks dangerous, but together they give an attacker a complete path: a web page tells the agent to read ~/.ssh and mail it out.
trifecta reads the tool definitions an agent is given and tags each tool with the legs it provides, plus (A) for consequential actions such as shell, delete, pay or deploy. It then reports the risky combinations across the whole toolset, including combinations that span several servers. For each one it names the smallest group of tools you would need to remove or put behind human approval to break it.
Standard library only (Python 3.10+). It never connects to a server.
Rules
| Code | Severity | Meaning |
|---|---|---|
| TF01 | critical | Private + untrusted + exfil tools are all available. The finding lists each leg, notes when the legs span servers, and suggests the smallest leg to remove or gate. |
| TF02 | high | A single tool both takes in untrusted content and can send data out, for example fetch(url), since data can leave in the query string. |
| TF03 | high | Untrusted content and consequential-action tools together (injection-to-action). |
| TF04 | medium | Private + exfil with no untrusted source yet. Adding one more tool completes the trifecta. |
| TF05 | medium | Private + untrusted with no exfil tool yet. Indirect channels may still exist. |
| TF06 | info | The tool could not be classified. Review it and tag it with --tags. |
Usage
python3 trifecta.py examples/agent # exit 1: lethal trifecta found
python3 trifecta.py examples/safe --tags examples/tags.json --fail-on any # exit 0
python3 trifecta.py tools/ --json
python3 trifecta.py tools/ --ignore 'github/get_me' --min-severity mediumAfter pip install of the kit, the same options work as agentsec trifecta …. Every tool also accepts --help and almost every tool accepts --json.
Example output
$ python3 trifecta.py examples/agent
-UE- fetch/fetch U: fetches caller-chosen URL 'url'; E: arbitrary URL parameter 'url' ...
P--- filesystem/read_file P: name reads file
PU-- mail/search_inbox P: name reads inbox; U: name ingests inbox
--E- mail/send_email E: name verb send
PUEA mail/run_shell P: general command/code execution (name: run/shell); ...
[CRITICAL] TF01 Lethal trifecta: private data + untrusted content + exfiltration channel
4 private / 3 untrusted / 3 exfil tools are available to the same agent across servers
fetch, filesystem, mail. Break it by removing or human-gating the untrusted leg: ...
SARIF and CI
agentsec trifecta path/to/input --sarif > trifecta.sarif
# GitHub Actions (composite action ships with the repo)
- uses: dunkleschitz/agentsec@v0
with:
tools: trifecta
paths: path/to/input
fail-on: high
SARIF 2.1.0 can be uploaded to GitHub code scanning. The composite action writes per-tool reports under agentsec-sarif/ by default.
OWASP mapping
Heuristic mapping of what this tool helps a reviewer look for. Not an official OWASP endorsement, and not complete coverage of any item. Sources: OWASP Top 10 for LLM Applications 2025 and OWASP Top 10 for Agentic Applications 2026.
- LLM06 Excessive Agency — OWASP LLM Top 10 (2025)
- ASI02 Tool Misuse and Exploitation — OWASP Agentic Top 10 (2026)
Known limits
Heuristic scanner, not a security boundary. A clean result does not mean something is safe. All example secrets in this repository are fake.
Full source, tests, and fixtures: tools/trifecta/ in the repository. Install the kit with pip install git+https://github.com/dunkleschitz/agentsec.git.