# Expected Findings — MCP Cumulative Drift Walkthrough

This is the testable contract. `run-rug-pull.mjs` exits 0 only when
every row matches.

## Per-stage contract

| Stage | per-update advisory | cumulative advisory | OWASP |
|-------|---------------------|---------------------|-------|
| 0 | no | no (baseline seeded) | — |
| 1 | no | no | — |
| 2 | no | no | — |
| 3 | no | no | — |
| 4 | no | no | — |
| 5 | no | no | — |
| 6 | no | no (cum=24.8%, just under 25%) | — |
| 7 | **no** | **YES** | MCP05, LLM03 |

The hook output is JSON `{systemMessage: "..."}` containing
`SECURITY ADVISORY (post-mcp-verify): Potential data leakage detected.`
followed by an enumerated advisory. The `mcp-cumulative-drift`
advisory at stage 7 includes:

- The literal phrase `MCP tool cumulative description drift — MEDIUM`
- The OWASP tag `(mcp-cumulative-drift, OWASP MCP05)`
- The phrase `Slow-burn rug-pull may evade per-update detection`
- A baseline preview matching stage 0's text
- A current preview matching stage 7's text
- A pointer to `/security mcp-baseline-reset`

## Drift math (verifiable)

These ratios are produced by
`scanners/lib/string-utils.mjs::levenshtein()`:

| Stage | Levenshtein vs prev | Levenshtein vs baseline | per_update | cumulative |
|-------|-------------------:|------------------------:|-----------:|-----------:|
| 1 | 4 | 4 | 3.3% | 3.3% |
| 2 | 4 | 8 | 3.3% | 6.6% |
| 3 | 5 | 13 | 4.2% | 10.7% |
| 4 | 7 | 20 | 5.8% | 16.5% |
| 5 | 6 | 26 | 5.2% | 21.5% |
| 6 | 4 | 30 | 3.5% | 24.8% |
| 7 | 9 | 39 | 7.9% | **32.2%** |

per_update threshold = 0.10 → never tripped.
cumulative threshold = 0.25 → tripped at stage 7.

## Cache state at end (verbose mode)

`mcp__knowledge__search` entry should contain:

- `baseline.description` = stage 0 text (immutable since stage 0)
- `description` = stage 7 text (last seen)
- `history.length` = 7 (one entry per stage 1-7)
- `firstSeen` and `lastSeen` set to runtime millis
- No `clearBaseline()` was called, so baseline is still present

## Side effects

- Cache file is written to `mkdtemp` directory provided via env var
- Cache directory is removed by `finally{}` block on exit
- No MCP audit-trail event (audit trail not configured for this demo)
- No interaction with `~/.cache/llm-security/`
